"--check"和"--pidfile"都是用来检查是否已运行的,不是用来启动的,如果提供了"--check",则检查的是名为servicename的进程,否则检查的是program名称的进程。
"--force"则表示进程已存在时仍启动。
prog_args是向program传递它的运行参数,一般会从/etc/sysconfig/$base文件中获取。
例如httpd的启动脚本中。
echo -n $"Starting $prog: " daemon --pidfile=${pidfile} $httpd $OPTIONS这样的语句的执行结果大致如下:
[root@xuexi ~]# service httpd start Starting httpd: [ OK ]还需注意,通常program的运行参数可能也是"--"开头的,要和program前面的选项区分。例如:
daemon --pidfile $pidfile --check $servicename $processname --pid-file=$pidfile第二个"--pid-file"是"$processname"的运行参数,第一个"--pidfile"是daemon检测"$processname"是否已运行的选项。由于提供了"--check $servicename",所以函数调用语句__pids_var_run $base [pidfile]中的$base等于$servicename,即表示检查$servicename进程是否允许。如果没有提供该选项,则检查的是$processname。
至此,daemon函数已经分析完成。实际上很简单,就是为daemon提供几个选项,再提供要执行的命令,并为该命令提供启动参数。
7.重头戏(二):killproc函数killproc函数的作用是根据给定程序名杀进程。中间它会获取程序名对应的pid号,且保证/proc目录下没有pid对应的目录才表示进程关闭成功。
# A function to stop a program. killproc() { local RC killlevel= base pid pid_file= delay try RC=0; delay=3; try=0 # Test syntax. if [ "$#" -eq 0 ]; then echo $"Usage: killproc [-p pidfile] [ -d delay] {program} [-signal]" return 1 fi if [ "$1" = "-p" ]; then # 指定pid_file。不给"-p"时,"__pids_var_run"将检查/var/run下的文件 pid_file=$2 shift 2 fi if [ "$1" = "-d" ]; then # awk的多目运算符。delay的有效值单位为d(天)、时(h)、分(m)、秒(s)。 # 不写单位时默认为秒。该语句将所给时间转换成秒,接受小数,做四舍五入计算 delay=$(echo $2 | awk -v RS=' ' -v IGNORECASE=1 '{if($1!~/^[0-9.]+[smhd]?$/) exit 1;d=$1~/s$|^[0-9.]*$/?1:$1~/m$/?60:$1~/h$/?60*60:$1~/d$/?24*60*60:-1;if(d==-1) exit 1;delay+=d*$1} END {printf("%d",delay+0.5)}') if [ "$?" -eq 1 ]; then echo $"Usage: killproc [-p pidfile] [ -d delay] {program} [-signal] return 1 fi shift 2 fi # check for second arg to be kill level [ -n "${2:-}" ] && killlevel=$2 # 获取稍后的kill程序将要发送的信号 # Save basename. base=${1##*/} # Find pid. # 获取program的pid号,以让kill程序杀掉 __pids_var_run "$1" "$pid_file" # 检查program是否已有对应pid文件,并返回pidfile中所有pid值 RC=$? if [ -z "$pid" ]; then if [ -z "$pid_file" ]; then pid="$(__pids_pidof "$1")" # pid为空,且没有pidfile时,获取program的pid else [ "$RC" = "4" ] && { failure $"$base shutdown" ; return $RC ;} fi fi # Kill it. # 根据pid,杀掉已存在的进程 if [ -n "$pid" ] ; then # 如果进程pid存在,则杀死它 [ "$BOOTUP" = "verbose" -a -z "${LSB:-}" ] && echo -n "$base " if [ -z "$killlevel" ] ; then # 没有指定要传递的信号时 if checkpid $pid 2>&1; then # 给定pid在/proc目录中是否有对应目录 # TERM first, then KILL if not dead kill -TERM $pid >/dev/null 2>&1 # 先发送TERM信号 usleep 50000 if checkpid $pid ; then # 0.5秒后还没死透,则 try=0 while [ $try -lt $delay ] ; do # 在给定delay时间内不断检测是否已死 checkpid $pid || break sleep 1 let try+=1 done if checkpid $pid ; then # 超出delay后,发送KILL信号强制杀死 kill -KILL $pid >/dev/null 2>&1 usleep 50000 fi fi fi checkpid $pid # 若/proc下还有pid对应的目录,则进程关闭失败 RC=$? [ "$RC" -eq 0 ] && failure $"$base shutdown" || success $"$base shutdown" RC=$((! $RC)) # use specified level only else # 使用指定的信号杀进程 if checkpid $pid; then kill $killlevel $pid >/dev/null 2>&1 RC=$? [ "$RC" -eq 0 ] && success $"$base $killlevel" || failure $"$base $killlevel" elif [ -n "${LSB:-}" ]; then RC=7 # Program is not running fi fi else # 如果进程pid不存在,表示未运行 if [ -n "${LSB:-}" -a -n "$killlevel" ]; then RC=7 # Program is not running else failure $"$base shutdown" RC=0 fi fi # Remove pid file if any. if [ -z "$killlevel" ]; then # 未给定信号时,可能KILL信号强杀时使得pid文件还存在,手动移除它 rm -f "${pid_file:-/var/run/$base.pid}" fi return $RC }