squid第16章 调试和故障处理

原贴:http://www.opendigest.org/article.php/302

第16章 调试和故障处理

  • 16.1 一些通用问题
    • 16.1.1 "Failed to make swap directory"
    • 16.1.2 "Address already in use"
    • 16.1.3 "Could not determine fully qualified hostname"
    • 16.1.4 "DNS name lookup tests failed"
    • 16.1.5 "Illegal character in hostname"
    • 16.1.6 "Running out of filedescriptors"
    • 16.1.7 "icmpRecv: Connection refused"
    • 16.1.8 在运行一段时间后,Squid变慢了
    • 16.1.9 调试访问控制
  • 16.2 通过cache.log进行调试
  • 16.3 Coredump,断点,和堆栈跟踪
  • 16.3.1 不能找到core文件?
  • 16.4 重现问题
  • 16.5 报告Bug
  • 译后序

16.1 一些通用问题

在讨论通用debug前,我先提起一些经常发生的问题。


16.1.1 "Failed to make swap directory"
Failed to make swap directory /var/spool/cache: (13) Permission denied

这点发生在你运行squid -z,并且squid的用户ID没有对/var/spool目录的写权限的时候。记住假如以root来启动squid,并且没有增加cache_effective_user行,那么squid默认以nobody用户运行。解决方法很简单:

# chown nobody:nobody /var/spool

16.1.2 "Address already in use"
commBind: Cannot bind socket FD 10 to *:3128: Address already in use

这个消息出现在bind()系统调用失败时,因为请求端口已经被其他应用程序所打开。通常,若已有一个squid在运行,而又试图启动第2个squid实例,就会发生这种情况。假如你见到这个错误消息,请使用ps来观察是否squid已经在运行。

Squid使用SO_REUSEADDR socket选项,以便bind()调用总能成功,即使仍有一些残余的socket位于TIME_WAIT状态。若该消息出现,尽管squid没有在运 行,但你的操作系统可能在处理这个问题上有bug。重启操作系统是解决问题的一个方法。

另一个可能性是端口(例如3128)当前已被其他应用程序使用。假如你怀疑这点,就可使用lsof程序来发现哪个应用正在该端口上侦听。FreeBSD用户能使用sockstat代替。


16.1.3 "Could not determine fully qualified hostname"
FATAL: Could not determine fully qualified hostname.  Please set 'visible_hostname'

假如squid不能识别它自己的完整可验证域名,就会报这个错。如下是squid使用的算法:

  • 1) 假如你将squid的HTTP端口绑定在指定的接口地址上,squid试图对该地址执行反向DNS查询。假如成功,查询答案就被用上。

  • 2) Squid调用gethostname( )函数,然后使用 gethostbyname( )函数,试着解析其IP地址。假如成功,squid使用后者函数返回的官方主机名串。

假如以上2项技术都不能工作,squid以前面提到的致命错误消息退出。在该情形下,必须使用visible_hostname指令来告诉squid它的主机名。例如:

visible_hostname my.host.name

16.1.4 "DNS name lookup tests failed"

默认情况下,squid在启动前执行一些DNS查询。这点确保你的DNS服务器可到达,并且运行正确。假如测试失败,可在cache.log或syslog里见到如下消息:

FATAL: ipcache_init: DNS name lookup tests failed

假如你在内网里使用squid,squid可能不能查询到它的标准主机名列表。可使用dns_testnames指令来指定你自己的主机名。只要接受到响应,squid就会认为DNS测试成功。

假如你想完全跳过DNS测试,简单的在启动squid时,使用-D命令行选项:

% squid -D ...

16.1.5 "Illegal character in hostname"
urlParse: Illegal character in hostname 'super_bikes.tripod.com'

默认情况下,squid检查URL的主机名部分的字符,假如它发现了非标准的字符,squid会抱怨。参考RFC 1034和1035,名字必须由字母A-Z,数字0-9,以及短横线(-)组成。下划线(_)是最有问题的字符之一。

Squid验证主机名是因为,在某些情形下,DNS对畸形字符的解析会很困难。例如:

% host super_bikes.tripod.com

super_bikes.tripod.com has address 209.202.196.70


% ping super_bikes.tripod.com

ping: cannot resolve super_bikes.tripod.com: Unknown server error

Squid事先检查主机名,这好过于以后返回Unknown server error消息。然后它会告诉用户主机名包含畸形字符。

某些DNS解析器确实能处理下划线和其他非标准字符。假如你想让squid不检查主机名,请在运行./configure时,使用—disable -hostname-checks选项。假如你允许下划线作为唯一的例外,那么使用—enable-underscores选项。


16.1.6 "Running out of filedescriptors"
WARNING! Your cache is running out of filedescriptors

上述消息出现在squid用完了所有可用文件描述符时。假如这点发生在正常条件下,就有必要增加内核的文件描述符限制,并且重新编译squid。请见3.3.1章。

假如squid成为了拒绝服务攻击的目标,那也会见到这条消息。某些人可能有意或无意的,同时对squid发送成百上千条请求。在这种情形下,可以增加一条包过滤规则,阻止来自恶意地址的TCP进入连接。假如攻击是分布式的,或使用假冒源地址,就很难阻止它们。

转发循环(见10.2章)也可能耗尽squid的所有文件描述符,但仅仅发生在squid不能检测到死循环时。Via头部包含了某个请求遍历过的所 有代理的主机名。squid在头部里查找它自己的主机名,假如发现了,就报告这个循环。假如因为某些理由,Via头部从外出或进入HTTP请求里过滤掉 了,squid就不能检测到循环。在该情形下,所有文件描述符被循环遍历squid的同一请求迅速耗完。


16.1.7 "icmpRecv: Connection refused"

假如pinger程序没有正确的安装,可见到下列消息:

icmpRecv: recv: (61) Connection refused

不过看起来更象是因为没有打开ICMP socket的权限,pinger立刻退出了。因为该进程未在运行,当squid试图与它会话时,会接受到I/O错误。为了解决该问题,请到源代码目录以root运行:

# make install-pinger

假如成功,你可见到pinger程序有下列文件属主和许可设置:

# ls -l /usr/local/squid/libexec/pinger

-rws--x--x 1 root squid 140728 Sep 16 19:58 /usr/local/squid/libexec/pinger

16.1.8 在运行一段时间后,Squid变慢了

看起来更象squid与其他进程,或与它自己,在竞争系统中的内存。当squid进程的内存不再充足时,操作系统被迫从交换空间进行内存读写。这对squid的性能有强烈影响。

为了证实这个想法,请使用top和ps等工具检查squid的进程大小。也检查squid自己的页面错误计数器,见14.2.1.24章的描述。一旦你已确认内存耗费是问题所在,请执行下列步骤来减少squid的内存使用:

  • 1. 减少cache_mem值,见附录B。

  • 2. 关掉内存池,用该选项:
    memory_pools off
  • 3. 通过降低一个或多个cache目录的size,减少磁盘cache大小。

16.1.9 调试访问控制

假如访问控制不能正确工作,如下是一些有用帮助。编辑squid.conf文件,设置debug_options行如下:

debug_options ALL,1 33,2

然后,重配置squid:

% squid -k reconfigure

现在,对每个客户端请求以及每个响应,squid都写一条消息到cache.log。该消息包含了请求方式,URI,是否请求/响应被允许或拒绝,以及与之匹配的最后ACL的名字。例如:

2003/09/29 20:22:05| The request

GET http://images.slashdot.org:80/topics/topicprivacy.gif is ALLOWED,

because it matched 'localhost'


2003/09/29 20:22:05| The reply for

GET http://images.slashdot.org/topics/topicprivacy.gif is ALLOWED,

because it matched 'all'

知道ACL的名字,并非总能知道相应的http_access行,但也相当接近了。假如必要,可以复制acl行,并给予它们唯一的名字,以便给定的ACL名字仅仅出现在一个http_access规则里。



16.2 通过cache.log进行调试

从13.1章已了解到,cache.log包含了不同的操作消息,squid认为这些消息足够重要,从而告诉了你。我们也将这些作为debug消息 考虑。可以使用debug_options指令来控制出现在cache.log里的消息的冗长度。通过增加debug等级,可以见到更详细的消息,有助于 理解squid正在做什么。例如:

debug_options ALL,1 11,3 20,3

在squid源代码里的每个debug消息有2个数字特征:1个节和1个等级。节范围从0到100,等级范围从0到10。通常来说,节号对应着源代 码的组成成分。换句话说,在单一源文件里的所有消息,有相同的节号。在某些情形下,多个文件使用同一debug节,这意味着某个源文件变得太大,从而被拆 分成多个小块。

每个源文件的顶部有一行,用于指示debug节。它看起来如此:

* DEBUG: section 9     File Transfer Protocol (FTP)

我不指望你通过查看源文件来查找节号,所有相关信息定义在表16-1里。



Table 16-1. Debugging section numbers for the debug_options directive

NumberDescriptionSource file(s)
0Client Databaseclient_db.c
1Startup and Main Loopmain.c
2Unlink Daemonunlinkd.c
3Configuration File Parsingcache_cf.c
4Error Generationerrorpage.c
5Socket Functionscomm.c
5Socket Functionscomm_select.c
6Disk I/O Routinesdisk.c
7Multicastmulticast.c
8Swap File Bitmapfilemap.c
9File Transfer Protocol (FTP)ftp.c
10Gophergopher.c
11Hypertext Transfer Protocol (HTTP)http.c
12Internet Cache Protocolicp_v2.c
12Internet Cache Protocolicp_v3.c
13High Level Memory Pool Managementmem.c
14IP Cacheipcache.c
15Neighbor Routinesneighbors.c
16Cache Manager Objectscache_manager.c
17Request Forwardingforward.c
18Cache Manager Statisticsstat.c
19Store Memory Primitivesstmem.c
20Storage Managerstore.c
20Storage Manager Client-Side Interfacestore_client.c
20Storage Manager Heap-Based Replacementrepl/heap/store_heap_replacement.c
20Storage Manager Logging Functionsstore_log.c
20Storage Manager MD5 Cache Keysstore_key_md5.c
20Storage Manager Swapfile Metadatastore_swapmeta.c
20Storage Manager Swapin Functionsstore_swapin.c
20Storage Manager Swapout Functionsstore_swapout.c
20Store Rebuild Routinesstore_rebuild.c
21Misc Functionstools.c
22Refresh Calculationrefresh.c
23URL Parsingurl.c
24WAIS Relaywais.c
25MIME Parsingmime.c
26Secure Sockets Layer Proxyssl.c
27Cache Announcersend-announce.c
28Access Controlacl.c
29Authenticatorauth/basic/auth_basic.c
29Authenticatorauth/digest/auth_digest.c
29Authenticatorauthenticate.c
29NTLM Authenticatorauth/ntlm/auth_ntlm.c
30Ident (RFC 1413)ident.c
31Hypertext Caching Protocolhtcp.c
32Asynchronous Disk I/Ofs/aufs/async_io.c
33Client-Side Routinesclient_side.c
34Dnsserver Interfacedns.c
35FQDN Cachefqdncache.c
37ICMP Routinesicmp.c
38Network Measurement Databasenet_db.c
39Cache Array Routing Protocolcarp.c
40Referer Loggingreferer.c
40User-Agent Logginguseragent.c
41Event Processingevent.c
42ICMP Pinger Programpinger.c
43AIOPSfs/aufs/aiops.c
44Peer Selection Algorithmpeer_select.c
45Callback Data Registrycbdata.c
45Callback Data Registryleakfinder.c
46Access Logaccess_log.c
47Store COSS Directory Routinesfs/coss/store_dir_coss.c
47Store Directory Routinesfs/aufs/store_dir_aufs.c
47Store Directory Routinesfs/diskd/store_dir_diskd.c
47Store Directory Routinesfs/null/store_null.c
47Store Directory Routinesfs/ufs/store_dir_ufs.c
47Store Directory Routinesstore_dir.c
48Persistent Connectionspconn.c
49SNMP Interfacesnmp_agent.c
49SNMP Supportsnmp_core.c
50Log File Handlinglogfile.c
51File Descriptor Functionsfd.c
52URN Parsingurn.c
53AS Number Handlingasn.c
54Interprocess Communicationipc.c
55HTTP HeaderHttpHeader.c
56HTTP Message BodyHttpBody.c
57HTTP Status-LineHttpStatusLine.c
58HTTP Reply (Response)HttpReply.c
59Auto-Growing Memory Buffer with printfMemBuf.c
60Packer: A Uniform Interface to Store Like ModulesPacker.c
61Redirectorredirect.c
62Generic HistogramStatHist.c
63Low Level Memory Pool ManagementMemPool.c
64HTTP Range HeaderHttpHdrRange.c
65HTTP Cache Control HeaderHttpHdrCc.c
66HTTP Header ToolsHttpHeaderTools.c
67StringString.c
68HTTP Content-Range HeaderHttpHdrContRange.c
69HTTP Header: Extension FieldHttpHdrExtField.c
70Cache DigestCacheDigest.c
71Store Digest Managerstore_digest.c
72Peer Digest Routinespeer_digest.c
73HTTP RequestHttpRequest.c
74HTTP MessageHttpMsg.c
75WHOIS Protocolwhois.c
76Internal Squid Object handlinginternal.c
77Delay Poolsdelay_pools.c
78DNS Lookups; interacts with lib/rfc1035.cdns_internal.c
79Squid-Side DISKD I/O Functionsfs/diskd/store_io_diskd.c
79Storage Manager COSS Interfacefs/coss/store_io_coss.c
79Storage Manager UFS Interfacefs/ufs/store_io_ufs.c
80WCCP Supportwccp.c
82External ACLexternal_acl.c
83SSL Accelerator Supportssl_support.c
84Helper Process Maintenancehelper.c


debug等级这样分配:重要消息有较低值,非重要消息有较高值。0等级是非常重要的消息,10等级是相对不紧要的消息。另外,关于等级其实并没有严格的向导或要求。开发者通常自由选择适应的debug等级。

debug_options指令决定哪个消息出现在cache.log,它的语法是:

debug_options section,level section,level ...

默认设置是ALL,1,这意味着squid会将所有等级是0或1的debug消息打印出来。假如希望cache.log里出现更少的debug消息,可设置debug_options为ALL,0。

假如想观察某个组件的其他debug信息,简单的将相应的节号和等级增加到debug_options列表的末端。例如,如下行对FTP服务端代码增加了等级5的debug:

debug_options ALL,1 9,5

如同其他配置指令一样,可以改变debug_options,然后给squid发送重置信号:

% squid -k reconfigure

注意debug_options参数是按顺序处理的,后来的值会覆盖先前的值。假如使用ALL关键字,这点尤其要注意。考虑如下示例:

debug_options 9,5 20,9 4,2 ALL,1

在该情形下,最后的值覆盖了所有先前的设置,因为ALL,1对所有节设置了debug等级为1。

选择合适的debug节号和等级有时非常困难,尤其是对squid新手而言。许多更详细的debug消息仅对squid开发者和熟悉源代码的用户有 意义。无经验的squid用户会发现许多debug消息无意义和不可理解。进一步的说,假如squid相对忙的话,你可能对某个特殊请求或事件进行独立 debug有困难。假如你能一次用一个请求来测试squid,那么高的debug等级通常更有用。

若以高debug等级来运行squid较长时间,需要特别谨慎。假如squid繁忙,cache.log增长非常快,并可能最终耗尽它的分区的剩余 空间。假如这点发生,squid以致命消息退出。另一个关注点是性能可能下降明显。因为有大量的debug消息,squid要耗费许多CPU资源来格式化 和打印字符串。将所有debug消息写往cache.log,也浪费了大量的磁盘带宽。



16.3 Coredump,断点,和堆栈跟踪

假如不幸,squid可能在运行时遭遇致命错误。这类型的错误来自3个风格:断点,总线错误,和异常分片。

断点是源代码里的正常检测。它是一个工具,被开发者用来确认在处理某事情前,相应的条件总为真。假如条件为假,程序退出并创建一个core文件,以便开发者能分析形势。如下是个典型的示例:

int some_array[100];


void

some_func(int idx)

{
...

assert(idx < 100);


some_array[idx]++;

...
}

这里,断点确保数组索引的值位于数组范围内。假如去访问大于或等于100的数组元素,就会遇到错误。假如不知何故,idx的值不小于100,程序运行时会打印如下消息:

assertion failed: filename.c:123: "idx < 100"

假如这点发生在squid上,就可在cache.log里见到"assertion failed"消息。另外,操作系统会创建一个core文件,这对事后分析有用。在本节结尾,我会解释如何去处理core文件。

总线错误是:由于处理器检测到其总线上的异常条件,会引发机器语言指令执行时致命失败。当处理器试图操作非连续的内存地址时,通常会发生这种错误。在64位处理器系统上可能更容易见到总线错误,例如Alpha和某些SPARC CPU。幸运的是,它们容易修复。

异常分片错误不幸的更常见,且有时难以修复。SEGV通常发生在进程试图访问无效内存区域时(可能是个NULL指针,或超出进程空间之外的内存地址)。当bug原因和SEGV影响在不同时间呈现时,它们特别难于捕获到。

Squid默认捕获总线错误和异常分片,当它们发生时,squid试图执行一个clean shutdown(清理关闭)。可在cache.log里见到类似的语句:

FATAL: Received Bus Error...dying.

2003/09/29 23:18:01| storeDirWriteCleanLogs: Starting...

大多数情形下,squid能够写swap.state文件的clean版本。在退出前,squid调用abort()函数来创建core文件。core文件可以帮助你或其他开发者来捕获和修复bug。

在错误发生时马上创建core文件,而不是先调用clean shutdown过程,这样更利于调试。使用-C命令行选项,可以告诉squid不去捕获总线错误和异常分片:

% squid -C ...

注意某些操作系统使用文件名core,而另外一些优先考虑进程名(例如squid.core)。一旦找到core文件,请使用调试器来进行堆栈跟 踪。gdb是GNU调试器--GNU C编译器的配套工具。假如没有gdb,可试着运行dbx或adb代替。如下显示如何使用gdb来进行堆栈跟踪:

% gdb /usr/local/squid/sbin/squid /path/to/squid.core


...

Core was generated by 'squid'.

Program terminated with signal 6, Abort trap.
...

然后,敲入where来打印堆栈轨迹:

(gdb) where

#0 0x28168b54 in kill ( ) from /usr/lib/libc.so.4

#1 0x281aa0ce in abort ( ) from /usr/lib/libc.so.4

#2 0x80a2316 in death (sig=10) at tools.c:301

#3 0xbfbfffac in ?? ( )

#4 0x80abe0a in storeDiskdSend (mtype=4, sd=0x82101e0, id=1214000,

sio=0x9e90a10, size=4096, offset=-1, shm_offset=0)

at diskd/store_io_diskd.c:485

#5 0x80ab726 in storeDiskdWrite (SD=0x82101e0, sio=0x9e90a10,

buf=0x13e94000 "...", size=4096, offset=-1, free_func=0)

at diskd/store_io_diskd.c:251

#6 0x809d2fb in storeWrite (sio=0x9e90a10, buf=0x13e94000 "...",

size=4096, offset=-1, free_func=0) at store_io.c:89

#7 0x80a1c2d in storeSwapOut (e=0xc5a7800) at store_swapout.c:259

#8 0x809b667 in storeAppend (e=0xc5a7800, buf=0x810f9a0 "...", len=57344)

at store.c:533

#9 0x807873b in httpReadReply (fd=134, data=0xc343590) at http.c:642

#10 0x806492f in comm_poll (msec=10) at comm_select.c:445

#11 0x8084404 in main (argc=2, argv=0xbfbffa8c) at main.c:742

#12 0x804a465 in _start ( )

你可见到,堆栈轨迹打印了每个函数的名字,它的参数,以及源代码文件名和行数。当捕获bug时,这些信息特别有用。然而在某些情形下,这些还不够。可能要求你在调试器里执行其他命令,例如打印来自某个函数的变量的值:

(gdb) frame 4


#4 0x80abe0a in storeDiskdSend (mtype=4, sd=0x82101e0, id=1214000,

sio=0x9e90a10, size=4096, offset=-1, shm_offset=0)

at diskd/store_io_diskd.c:485

485 x = msgsnd(diskdinfo->smsgid, &M,

msg_snd_rcv_sz, IPC_NOWAIT);

(gdb) set print pretty

(gdb) print M

$2 = {

mtype = 4,

id = 1214000,

seq_no = 7203103,

callback_data = 0x9e90a10,

size = 4096,

offset = -1,

status = -1,

shm_offset = 0

}

在报告了某个bug后,请保留core文件一些天,可能还需要从它获取其他信息。


16.3.1 不能找到core文件?

core文件写在进程的当前目录。squid在启动时默认不改变其当前目录。这样你的core文件(如果有的话),会写在启动squid的目录。假 如文件系统没有足够的自由空间,或进程属主没有对该目录的写权限,就无法产生core文件。可以使用coredump_dir指令来让squid使用指定 的coredump目录--位于其他地方的有充足自由空间和完全权限的目录。

进程资源限制也会阻止产生core文件。进程限制参数之一是coredump文件的大小。大部分操作系统默认设置这个值为"无限"。在当前 shell里使用limits或ulimit命令,可以检查当前限制。然而请注意,你的shell的限制可能不同于squid的进程限制,特别是当 squid随系统启动而自动启动时。假如怀疑进程限制阻止了core文件的产生,试试这样:

csh% limit coredumpsize unlimited

csh% squid -NCd1

在FreeBSD上,某个sysctl参数控制了操作系统对调用了setuid()或setgid()函数的进程,是否产生core文件。假如以root启动,squid会用到这些函数。这样为了得到coredump,必须告诉内核创建core文件,用这个命令:

# sysctl kern.sugid_coredump=1

请见sysctl.conf的manpage,关于在系统启动时如何自动设置变量的信息。



16.4 重现问题

有时候可能遇到这样的问题:某个请求,或原始服务器看起来不能与squid协调工作。可以使用下面的技术来确定问题在于squid,客户端,或原始服务器。技巧就是捕获HTTP请求,然后用不同的方法响应它,直到你验证了问题。

捕获HTTP请求意味着获取除了URL外的更多信息,包括请求方式,HTTP版本号,和所有请求头部。捕获请求的一个方法是,短期激活squid的完整debug模式。在squid主机上,敲入:

% squid -kdebug

然后,到web浏览器上发布请求。squid几乎会立刻接受到请求。在若干秒后,回到squid主机,并发布同样的命令:

% squid -kdebug

现在cache.log文件包含了上述客户端的请求。假如squid繁忙,cache.log会包含大量的请求,所以你必须查找它。它看起来如下:

2003/09/29 10:37:40| parseHttpRequest: Method is 'GET'

2003/09/29 10:37:40| parseHttpRequest: URI is 'http://squidbook.org/'

2003/09/29 10:37:40| parseHttpRequest: Client HTTP version 1.1.

2003/09/29 10:37:40| parseHttpRequest: req_hdr = {

User-Agent: Mozilla/5.0 (compatible; Konqueror/3)

Pragma: no-cache

Cache-control: no-cache

Accept: text/*, image/jpeg, image/png, image/*, */*

Accept-Encoding: x-gzip, gzip, identity

Accept-Charset: iso-8859-1, utf-8;q=0.5, *;q=0.5

Accept-Language: en

Host: squidbook.org

注意squid把首行元素分开打印,必须手工组合它们如下:

GET http://squidbook.org/ HTTP/1.1

捕获完整请求的另一个方法是使用工具例如netcat或socket (http://www.jnickelsen.de/socket/ )。启动socket程序侦听在某个端口,然后配置浏览器使用该端口作为代理地址。当再次发起请求时,socket打印出HTTP请求:

% socket -s 8080

GET http://squidbook.org/ HTTP/1.1

User-Agent: Mozilla/5.0 (compatible; Konqueror/3)

Pragma: no-cache

Cache-control: no-cache

Accept: text/*, image/jpeg, image/png, image/*, */*

Accept-Encoding: x-gzip, gzip, identity

Accept-Charset: iso-8859-1, utf-8;q=0.5, *;q=0.5

Accept-Language: en

Host: squidbook.org

最后,还可以使用网络包分析工具例如tcpdump或ethereal。使用tcpdump捕获到一些包后,可以使用tcpshow来查看它们:

# tcpdump -w tcpdump.log -c 10 -s 1500 port 80

# tcpshow -noHostNames -noPortNames < tcpdump.log | less

...
Packet 4

TIME: 08:39:29.593051 (0.000627)

LINK: 00:90:27:16:AA:75 -> 00:00:24:C0:0D:25 type=IP

IP: 10.0.0.21 -> 206.168.0.6 hlen=20 TOS=00 dgramlen=304 id=4B29

MF/DF=0/1 frag=0 TTL=64 proto=TCP cksum=15DC

TCP: port 2074 -> 80 seq=0481728885 ack=4107144217

hlen=32 (data=252) UAPRSF=011000 wnd=57920 cksum=EB38 urg=0

DATA: GET / HTTP/1.0.

Host: www.ircache.net.

Accept: text/html, text/plain, application/pdf, application/

postscript, text/sgml, */*;q=0.01.

Accept-Encoding: gzip, compress.

Accept-Language: en.

Negotiate: trans.

User-Agent: Lynx/2.8.1rel.2 libwww-FM/2.14.
.

注意tcpshow按数据里的新行字符为周期来进行打印。

一旦捕获到了某个请求,就将它存到文件。然后可以使用netcat或socket来让它重新通过squid:

% socket squidhost 3128 < request | less

假如响应看起来正常,问题可能在于用户代理。否则,可以改变不同事情来孤立问题。例如,假如你看到一些古怪的HTTP头部,那就从请求里删除它们, 然后再试一次。让请求直接到达原始服务器,而不是经过squid,这样做也可调试。方法就是从请求里删除http://host.name/,并将请求发 送到原始服务器:

% cat request

GET / HTTP/1.1

User-Agent: Mozilla/5.0 (compatible; Konqueror/3)

Pragma: no-cache

Cache-control: no-cache

Accept: text/*, image/jpeg, image/png, image/*, */*

Accept-Encoding: x-gzip, gzip, identity

Accept-Charset: iso-8859-1, utf-8;q=0.5, *;q=0.5

Accept-Language: en

Host: squidbook.org

% socket squidbook.org 80 < request | less

以这种方式使用HTTP时,请参考RFC 2616和Oreilly的HTTP:The Definitive Guide这本书。



16.5 报告Bug

假如你的squid版本已经有几个月未更新了,在报告bug前你应该更新它。因为其他人可能也注意了同样的bug,并且它已被修复。

假如你发现了squid的合理bug,请将它填入到squid的bug跟踪数据库:http://www.squid-cache.org/bugs/ 。 它当前是个"bugzilla"数据库,需要你创建一个帐号。当bug被squid开发者处理了时,你会接到更新通知。

假如你对报告bug很陌生,请先花时间阅读Simon Tatham写的"How to Report Bugs Effectively" (http://www.chiark.greenend.org.uk/~sgtatham/bugs.html )。

当报告bug时,确认包含下列信息:

  • 1) Squid版本号。假如bug发生在不止一个版本上,就也要写上其他版本号。

  • 2) 操作系统名字和版本。

  • 3) bug每次都发生,还是偶尔发生。

  • 4) 所发生事情的精确描述。类似于"它不能工作","请求失败"之类的语句,本质上对bug修复者无用。记得要非常详细。

  • 5) 对断点,总线错误,或异常分片的堆栈跟踪。

记住squid开发者通常是无报酬的义务劳动,所以要有耐心。严重bug比小问题享有更高的解决优先级。

译后序

当译完本书最后一章时,心头袭来深深的寂寞。


在计算机领域,国内外技术水平差之甚远,部分原因归咎于语言的差异。

某种技术在国外流行若干年后,才有相应的中文文档出现。

没有文档,技术人员无法起步;而不规范的发行文档,更是误导了一批又一批的初学者。


本书的作者Duane Wessels是位大师级的人物,除了精湛的技术外,他写的本书文笔通畅,脉络清晰,丝毫不晦涩。

若对研究Squid抱着严肃的态度,那么请认真的拜读原著。

而我所能做的,只是按照我自己的理解,把原著译成中文。


好的软件只是解决了某一方面的问题,而真正可贵的,是开源的精神。

在开源的世界里,可以体会到现实中所没有的无私与奉献。

责任编辑: mayu8758

相关文章
Squid中文权威指南(第15章 服务加速模式 ) - 06-20 11:46 am - 点击: 422
Squid中文权威指南(第14章 监视Squid) - 06-20 11:44 am - 点击: 505
Squid中文权威指南(第13章 日志文件) - 06-20 11:42 am - 点击: 573
Squid中文权威指南(第12章 验证辅助器 ) - 06-20 11:40 am - 点击: 520
Squid中文权威指南(第11章 重定向器) - 06-20 11:38 am - 点击: 588
Squid中文权威指南(第10章 与其他Squid会话 ) - 06-20 11:34 am - 点击: 557
Squid中文权威指南(第九章) - 04-26 07:03 pm - 点击: 748
Squid中文权威指南(第八章) - 04-26 07:02 pm - 点击: 734
Squid中文权威指南(第七章) - 04-26 07:01 pm - 点击: 635
Squid中文权威指南(第六章) - 04-26 07:00 pm - 点击: 541
 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值