Jeff Pang的站点

Squid中文权威指南

(第5章)

译者序:

本人在工作中维护着数台Squid服务器,多次参阅Duane Wessels(他也是Squid的创始人)的这本书,原书名是"Squid: The Definitive Guide",由O'Reilly出版。我在业余时间把它翻译成中文,希望对中文Squid用户有所帮助。对普通的单位上网用户,Squid可充当代理服务器;而对Sina,NetEase这样的大型站点,Squid又充当WEB加速器。这两个角色它都扮演得异常优秀。窗外繁星点点,开源的世界亦如这星空般美丽,而Squid是其中耀眼的一颗星。

对本译版有任何问题,请跟我联系,我的Email是:yonghua_peng@yahoo.com.cn

彭勇华

目 录

第5章 运行Squid



5.1 squid命令行选项

在开始其他事情之前,让我们先看一下squid的命令行选项。这里的许多选项你从不会使用,另外有些仅仅在调试问题时有用。

-a port

指定新的http_port值。该选项覆盖了来自squid.conf的值。然而请注意,你能在squid.conf里指定多个值。-a选项仅仅覆盖配置文件里的第一个值。(该选项使用字母a是因为在Harvest cache里,HTTP端口被叫做ASCII端口)

-d level

让squid将它的调试信息写到标准错误(假如配置了,就是cache.log和syslog)。level参数指定了显示在标准错误里的消息的最大等级。在多数情况下,d1工作良好。请见16.2章关于调试等级的描述。

-f file

指定另一个配置文件。

-h

显示用法。

-k function

指示squid执行不同的管理功能。功能参数是下列之一:reconfigure, rotate, shutdown, interrupt, kill, debug, check, or parse. reconfigure导致运行中的squid重新读取配置文件。rotate导致squid滚动它的日志,这包括了关闭日志,重命名,和再次打开它们。shutdown发送关闭squid进程的信号。interrupt立刻关闭squid,不必等待活动会话完成。kill发送KILL信号给squid,这是关闭squid的最后保证。debug将squid设置成完全的调试模式,假如你的cache很忙,它能迅速的用完你的磁盘空间。check简单的检查运行中的squid进程,返回的值显示squid是否在运行。最后,parse简单的解析squid.conf文件,如果配置文件包含错误,进程返回非零值。

-s

激活将日志记录到syslog进程。squid使用LOCAL4 syslog设备。0级别调试信息以优先级LOG_WARNING被记录,1级别消息以LOG_NOTICE被记录。更高级的调试信息不会被发送到syslogd.你可以在/etc/syslogd.conf文件里使用如下接口:

local4.warning			/var/log/squid.log
    
-u port

指定另一个ICP端口号,覆盖掉squid.conf文件里的icp_port。

-v

打印版本信息。

-z

初始化cache,或者交换,目录。在首次运行squid,或者增加新的cache目录时,你必须使用该选项。

-C

阻止安装某些信号句柄,它们捕获特定的致命信号例如SIGBUS和SIGSEGV。正常的,这些信号被squid捕获,以便它能干净的关闭。然而,捕获这些信号可能让以后调试问题困难。使用该选项,致命的信号导致它们的默认动作,通常是coredump。

-D

禁止初始化DNS测试。正常情况下,squid直到验证它的DNS可用才能启动。该选项阻止了这样的检测。你也能在squid.conf文件里改变或删除dns_testnames选项。

-F

让squid拒绝所有的请求,直到它重新建立起存储元数据。假如你的系统很忙,该选项可以减短重建存储元数据的时间。然而,如果你的cache很大,重建过程可能会花费很长的时间。

-N

阻止squid变成后台服务进程。

-R

阻止squid在绑定HTTP端口之前使用SO_REUSEADDR选项。

-V

激活虚拟主机加速模式。类似于squid.conf文件里的httpd_accel_host virtual指令。

-X

强迫完整调试模式,如你在squid.conf文件里指定debug_options ALL,9一样。

-Y

在重建存储元数据时,返回ICP_MISS_NOFETCH代替ICP_MISS.忙碌的父cache在重建时,该选项可以导致最少的负载。请见10.6.1.2章。



5.2 对配置文件查错

在开启squid之前,你应该谨慎的验证配置文件。这点容易做到,运行如下命令即可:

%squid -k parse

假如你看不到输出,配置文件有效,你能继续后面的步骤。然而,如果配置文件包含错误,squid会告诉你:

squid.conf line 62: http_access allow okay2
    
aclParseAccessLine: ACL name 'okay2' not found.

这里你可以看到,62行的http_access指令指向的ACL不存在。有时候错误信息很少:

FATAL: Bungled squid.conf line 76: memory_pools

在这个情形里,我们忘记了在76行的memory_pools指令后放置on或off. 建议你养成习惯:在每次修改配置文件后,使用squid -k parse。假如你不愿麻烦,并且你的配置文件有错误,squid会告诉你关于它们而且拒绝启动。假如你管理着大量的cache,也许你会编辑脚本来自动启动,停止和重配置squid。你能在脚本里使用该功能,来确认配置文件是有效的。



5.3 初始化cache目录

在初次运行squid之前,或者无论何时你增加了新的cache_dir,你必须初始化cache目录。命令很简单:

%squid -z

对UFS相关的存储机制(ufs,aufs,and diskd;见第8章),该命令在每个cache_dir下面创建了所需的子目录。你不必担心squid会破坏你的当前cache目录(如果有的话)。

在该阶段属主和许可权是通常遇到的问题。squid在特定的用户ID下运行,这在squid.conf文件里的cache_effective_user里指定。用户ID必须对每个cache_dir目录有读和写权限。否则,你将看到如下信息:

Creating Swap Directories

FATAL: Failed to make swap directory /usr/local/squid/var/cache/00:
    
    (13) Permission denied

在这样的情形下,你该确认/usr/local/squid/var/cache目录的所有组成都可被squid.conf给定的用户ID访问。最终的组件--cache目录--必须对该用户ID可写。

cache目录初始化可能花费一些时间,依赖于cache目录的大小和数量,以及磁盘驱动器的速度。假如你想观察这个过程,请使用-X选项:

%squid -zX


5.4 在终端窗口里测试squid

一旦你已经初始化cache目录,就可以在终端窗口里运行squid,将日志记录到标准错误。这样,你能轻易的定位任何错误或问题,并且确认squid是否成功启动。使用-N选项来保持squid在前台运行,-d1选项在标准错误里显示1级别的调试信息。

%squid -N -d1

你将看到类似于以下的输出:

2003/09/29 12:57:52| Starting Squid Cache 
    
version 2.5.STABLE4 for i386-unknown-freebsd4.8...
    
2003/09/29 12:57:52| Process ID 294
    
2003/09/29 12:57:52| With 1064 file descriptors available
    
2003/09/29 12:57:52| DNS Socket created on FD 4
    
2003/09/29 12:57:52| Adding nameserver 206.107.176.2 from /etc/resolv.conf
    
2003/09/29 12:57:52| Adding nameserver 205.162.184.2 from /etc/resolv.conf
    
2003/09/29 12:57:52| Unlinkd pipe opened on FD 9
    
2003/09/29 12:57:52| Swap maxSize 102400 KB, estimated 7876 objects
    
2003/09/29 12:57:52| Target number of buckets: 393
    
2003/09/29 12:57:52| Using 8192 Store buckets
    
2003/09/29 12:57:52| Max Mem  size: 8192 KB
    
2003/09/29 12:57:52| Max Swap size: 102400 KB
   
2003/09/29 12:57:52| Rebuilding storage in /usr/local/squid/var/cache (DIRTY)
    
2003/09/29 12:57:52| Using Least Load store dir selection
    
2003/09/29 12:57:52| Set Current Directory to /usr/local/squid/var/cache
    
2003/09/29 12:57:52| Loaded Icons.
    
2003/09/29 12:57:52| Accepting HTTP connections at 0.0.0.0, port 3128, FD 11.
    
2003/09/29 12:57:52| Accepting ICP messages at 0.0.0.0, port 3130, FD 12.
    
2003/09/29 12:57:52| WCCP Disabled.
    
2003/09/29 12:57:52| Ready to serve reques

假如你看到错误消息,你该首先修正它。请检查输出信息的开始几行以发现警告信息。最普通的错误是文件/目录许可问题,和配置文件语法错误。假如你看到一条不引起注意的错误消息,请见16章中关于squid故障处理的建议和信息。如果还不行,请检查squid FAQ,或查找邮件列表来获得解释。

一旦你见到"Ready to serve requests"消息,就可用一些HTTP请求来测试squid。配置你的浏览器使用squid作为代理,然后打开某个web页面。假如squid工作正常,页面被迅速载入,就象没使用squid一样。另外,你可以使用squidclient程序,它随squid发布:

% squidclient http://www.squid-cache.org/

假如它正常工作,squid的主页html文件会在你的终端窗口里滚动。一旦确认squid工作正常,你能中断squid进程(例如使用ctrl-c)并且在后台运行squid。



5.5 将squid作为服务进程运行

正常情况下你想将squid以后台进程运行(不出现在终端窗口里)。最容易的方法是简单执行如下命令:

%squid -s

-s选项导致squid将重要的状态和警告信息写到syslogd。squid使用LOCAL4设备,和LOG_WARNING和LOG_NOTICE优先权。syslog进程实际可能会或不会记录squid的消息,这依赖于它被如何配置。同样的消息被写进cache.log文件,所以假如你愿意,忽略-s选项也是安全的。

当你不使用-N选项来启动squid,squid自动在后台运行并且创建父/子进程对。子进程做所有的实际工作。父进程确认子进程总在运行。这样,假如子进程意外终止,父进程启动另外一个子进程以使squid正常工作。通过观察syslog消息,你能看到父/子进程交互作用。

Jul 31 14:58:35 zapp squid[294]: Squid Parent: child process 296 started

这里显示的父进程ID是294,子进程是296。当你查看ps的输出,你可以看到子进程以(squid)形式出现:

% ps ax | grep squid
  294  ??  Is     0:00.01 squid -sD
  296  ??  S      0:00.27 (squid) -sD (squid)

假如squid进程意外终止,父进程启动另一个。例如:

Jul 31 15:02:53 zapp squid[294]: Squid Parent: child process 296 exited due to signal 6
Jul 31 15:02:56 zapp squid[294]: Squid Parent: child process 359 started

在某些情形下,squid子进程可能立即终止。为了防止频繁的启动子进程,假如子进程连续5次没有运行至少10秒钟,父进程会放弃。

Jul 31 15:13:48 zapp squid[455]: Squid Parent: child process 474 exited with status 1
Jul 31 15:13:48 zapp squid[455]: Exiting due to repeated, frequent failures

如果发生这样的事,请检查syslog和squid的cache.log以发现错误。


5.5.1 squid_start脚本

当squid以后台进程运行时,它查找squid执行程序目录下的名为squid_start的文件。假如发现,该程序在父进程创建子进程之前被执行。你能使用该脚本完成特定的管理任务,例如通知某人squid在运行,管理日志文件等。除非squid_start程序存在,squid不会创建子进程。

squid_start脚本在你使用绝对或相对路径启动squid时才开始工作。换句话说,squid不使用PATH环境变量来定位squid_start.这样,你应该养成习惯这样启动squid:

% /usr/local/squid/sbin/squid -sD

而不要这样:

%squid -sD


5.6 启动脚本

通常你希望squid在每次计算机重启后自动启动。对不同的操作系统,它们的启动脚本如何工作也很不同。我在这里描述一些通用的环境,但对你自己的特殊操作系统,也许该有特殊的处理方法。


5.6.1 /etc/rc.local

最容易的机制之一是/etc/rc.local脚本。这是个简单的shell脚本,在每次系统启动时以root运行。使用该脚本来启动squid非常容易,增加一行如下:

/usr/local/squid/sbin/squid -s

当然你的安装位置可能不同,还有你可能要使用其他命令行选项。不要在这里使用-N选项。

假如因为某些理由,你没有使用cache_effective_user指令,你可以尝试使用su来让squid以非root用户运行:

/usr/bin/su nobody -c '/usr/local/squid/sbin/squid -s'

5.6.2 init.d和rc.d

init.d和rc.d机制使用独立的shell脚本来启动不同的服务。这些脚本通常在下列目录之中:/sbin/init.d, /etc/init.d, /usr/local/etc/rc.d.脚本通常获取单一命令行参数,是start或stop。某些系统仅仅使用start参数。如下是启动squid的基本脚本:

#!/bin/sh
# this script starts and stops Squid
case "$1" in
start)
          /usr/local/squid/sbin/squid -s
          echo -n ' Squid'
          ;;
stop)
          /usr/local/squid/sbin/squid -k shutdown
          ;;
esac

Linux用户可能在启动squid之前需要设置文件描述符限制。例如:

echo 8192 > /proc/sys/fs/file-max
limit -HSn 8192

为了使用该脚本,先找到脚本存放的目录。给它一个有意义的名字,类似于其他的系统启动脚本。可以是S98squid或squid.sh。通过重启计算机来测试该脚本,而不要假想它会正常工作。


5.6.3 /etc/inittab

某些操作系统支持另一种机制,是/etc/inittab文件。在这些系统中,init进程启动和停止基于运行等级的服务。典型的inittab接口类似如此:

sq:2345:once:/usr/local/squid/sbin/squid -s

使用该接口,init进程启动squid一次并且随后忘记它。squid确认它驻留在运行状态,象前面描述的一样。或者,你能这样做:

sq:2345:respawn:/usr/local/squid/sbin/squid -Ns

这里我们使用了respawn选项,假如进程不存在init会重启squid。假如使用respawn,请确认使用-N选项。

在编辑完inittab文件后,使用下面的命令来使init重新读取它的配置文件和启动squid:

# init q


5.7 chroot环境

某些人喜欢在chroot环境运行squid。这是unix的功能,给予进程新的root文件系统目录。在squid受安全威胁时,它提供额外等级的安全保护。假如攻击者在某种程度上通过squid获取了对操作系统的访问权,她仅仅能访问在chroot文件系统中的文件。在chroot树之外的系统文件,她不可访问。

最容易在chroot环境里运行squid的方法是,在squid.conf文件里指定新的root目录,如下:

chroot /new/root/directory

chroot()系统调用需要超级用户权限,所以你必须以root来启动squid。

chroot环境不是为unix新手准备的。它有点麻烦,因为你必须在新的root目录里重复放置大量的文件。例如,假如默认的配置文件正常在/usr/local/squid/etc/squid.conf,并且你使用chroot指令,那么文件必须位于/new/root/directory/usr/local/squid/etc/squid.conf.你必须将位于$prefix/etc,$prefix/share,$prefix/libexec下的所有文件拷贝到chroot目录。请确认$prefix/var和cache目录在chroot目录中存在和可写。

同样的,你的操作系统需要将大量的文件放在chroot目录里,例如/etc/resolv.conf和/dev/null.假如你使用外部辅助程序,例如重定向器(见11章)或者验证器(见12章),你也需要来自/usr/lib的某些共享库。你可以使用ldd工具来查找给定的程序需要哪些共享库:

% ldd /usr/local/squid/libexec/ncsa_auth
/usr/local/squid/libexec/ncsa_auth:
        
        libcrypt.so.2 => /usr/lib/libcrypt.so.2 (0x28067000)
        
        libm.so.2 => /usr/lib/libm.so.2 (0x28080000)
        
        libc.so.4 => /usr/lib/libc.so.4 (0x28098000)

你可以使用chroot命令来测试辅助程序:

# chroot /new/root/directory /usr/local/squid/libexec/ncsa_auth
    
/usr/libexec/ld-elf.so.1: Shared object "libcrypt.so.2" not found

更多的关于chroot的信息,请见你系统中chroot()的manpage.



5.8 停止squid

最安全的停止squid的方法是使用squid -k shutdown命令:

%squid -k shutdown

该命令发送TERM信号到运行中的squid进程。在接受到TERM信号后,squid关闭进来的套接字以拒收新请求。然后它等待一段时间,用以完成外出请求。默认时间是30秒,你可以在shutdown_lifetime指令里更改它。

假如因为某些理由,squid.pid文件丢失或不可读,squid -k命令会失败。在此情形下,你可以用ps找到squid的进程ID,然后手工杀死squid。例如:

%ps ax |grep squid

假如你看到不止一个squid进程,请杀死以(squid)显示的那个。例如:

% ps ax | grep squid
  
  294  ??  Is     0:00.01 squid -sD
  
  296  ??  S      0:00.27 (squid) -sD (squid)

% kill -TERM 296

在发送TERM信号后,你也许想查看日志,以确认squid已关闭:

% tail -f logs/cache.log

2003/09/29 21:49:30| Preparing for shutdown after 9316 requests

2003/09/29 21:49:30| Waiting 10 seconds for active connections to finish

2003/09/29 21:49:30| FD 11 Closing HTTP connection

2003/09/29 21:49:31| Shutting down...

2003/09/29 21:49:31| FD 12 Closing ICP connection

2003/09/29 21:49:31| Closing unlinkd pipe on FD 9

2003/09/29 21:49:31| storeDirWriteCleanLogs: Starting...

2003/09/29 21:49:32| Finished.  Wrote 253 entries.

2003/09/29 21:49:32| Took 0.1 seconds (1957.6 entries/sec).

2003/09/29 21:49:32| Squid Cache (Version 2.5.STABLE4): Exiting normally.

假如你使用squid -k interrupt命令,squid立即关闭,不用等待完成活动请求。这与在kill里发送INT信号相同。



5.9 重配置运行中的squid进程

在你了解了更多关于squid的知识后,你会发现对squid.conf文件做了许多改动。为了让新设置生效,你可以关闭和重启squid,或者在squid运行时,重配置它。

重配置运行中的squid最好的方法是使用squid -k reconfigure命令:

%squid -k reconfigure

当你运行该命令时,HUP信号被发送到运行中的squid进程。然后squid读取和解析squid.conf文件。假如操作成功,你可以在cache.log里看到这些:

2003/09/29 22:02:25| Restarting Squid Cache (version 2.5.STABLE4)...

2003/09/29 22:02:25| FD 12 Closing HTTP connection

2003/09/29 22:02:25| FD 13 Closing ICP connection

2003/09/29 22:02:25| Cache dir '/usr/local/squid/var/cache' size remains unchanged
                     
                     at 102400 KB

2003/09/29 22:02:25| DNS Socket created on FD 5

2003/09/29 22:02:25| Adding nameserver 10.0.0.1 from /etc/resolv.conf

2003/09/29 22:02:25| Accepting HTTP connections at 0.0.0.0, port 3128, FD 9.

2003/09/29 22:02:25| Accepting ICP messages at 0.0.0.0, port 3130, FD 11.

2003/09/29 22:02:25| WCCP Disabled.

2003/09/29 22:02:25| Loaded Icons.

2003/09/29 22:02:25| Ready to serve requests.

在使用reconfigure选项时你须谨慎,因为所做的改变可能会导致致命错误。例如,请注意squid关闭和重新打开进来的HTTP和ICP套接字;假如你将http_port改变为squid不能打开的端口,它会发生致命错误并退出。

在squid运行时,某些指令和和选项不能改变,包括:

solaris用户在重配置squid过程中可能遇到其他问题。solaris的stdio执行组件里的fopen()调用要求使用小于256的未用文件描述符。FILE结构以8位值存储该文件描述符。正常情况下这不构成问题,因为squid使用底层I/O(例如open())来打开cache文件。然而,在重配置过程中的某些任务使用fopen(),这就有可能失败,因为前面的256个文件描述符已被分配出去。



5.10 滚动日志文件

除非你在squid.conf里禁止,squid会写大量的日志文件。你必须周期性的滚动日志文件,以阻止它们变得太大。squid将大量的重要信息写入日志,假如写不进去了,squid会发生错误并退出。为了合理控制磁盘空间消耗,在cron里使用如下命令:

%squid -k rotate

例如,如下任务接口在每天的早上4点滚动日志:

0 4 * * * /usr/local/squid/sbin/squid -k rotate

该命令做两件事。首先,它关闭当前打开的日志文件。然后,通过在文件名后加数字扩展名,它重命名cache.log,store.log,和access.log。例如,cache.log变成cache.log.0,cache.log.0变成cache.log.1,如此继续,滚动到logfile_rotate选项指定的值。

squid仅仅保存每个日志文件的最后logfile_rotate版本。更老的版本在重命名过程中被删除。假如你想保存更多的拷贝,你需要增加logfile_rotate限制,或者编写脚本用于将日志文件移动到其他位置。 请见13.7章关于滚动日志的其他信息。



content by Jeff Pang · design by Sebastian Haase