我有一个正在支持的 Linux 服务。它提供了常用的start
命令stop
。设计者创建了一个包装命令,旨在控制主函数的启动和重试。包装器包括一个初步检查,以查看它是否已经通过调用pidofproc
自身来运行。启动和停止功能也使用它来进行检查。
我发现 init.d 程序中的启动和停止函数在调用后使用 pidofproc 没有问题. /etc/init.d/functions
,但包装器无法执行在我看来是同一件事的操作。
我注意到原来的包装纸有一些问题。最初它没有调用functions
.然后它没有正确测试字符串形式的返回值。我还注意到服务脚本是 bash 脚本,包装器是 shell,所以我将其切换为 bash。这些都没有帮助。
我创建了问题的 MCVE。它的行为似乎很像真实的代码,尽管包装器只是做了一个无用的 while 循环来保持运行。问题是,如果您myprog
在已经有一个实例正在运行时运行,则跟踪清楚地表明,__pids_pidof
functions 中的函数无法从 获取返回值pidof
,而启动和停止脚本工作正常。
有什么不同?
包装脚本示例 /usr/sbin/safe_myprog:
#!/bin/bash
set -x
PROG_NAME=myprog
INSTALL_DIR=/var/www/${PROG_NAME}
PROG=${INSTALL_DIR}/bin/${PROG_NAME}
SAFE_PROG_NAME=safe_myprog
SAFE_MYPROG=/usr/sbin/${SAFE_PROG_NAME}
message() {
# echo "$1" >&2
logger -t safe_myprog[$$] "$1"
}
. /etc/init.d/functions
safe_myprog=`pidofproc $SAFE_MYPROG`
if [ -n "$safe_myprog" ]; then
if [ -n "$(ps -p $safe_myprog -o pid=)" ]; then
message "$SAFE_PROG_NAME: is already running. pid: $safe_myprog"
exit 0
fi
fi
while :; do
sleep 60
done
服务程序/etc/init.d/myprog:
#!/bin/bash
set -x
# Source function library.
. /etc/init.d/functions
cd /
PROG_NAME=myprog
INSTALL_DIR=/var/www/${PROG_NAME}
SAFE_PROG_NAME=safe_myprog
SAFE_MYPROG=/usr/sbin/${SAFE_PROG_NAME}
PROG=${INSTALL_DIR}/bin/${PROG_NAME}
PROG_LOCK_FILE=/var/lock/subsys/${PROG_NAME}
PROG_PID_FILE=/var/lib/${PROG_NAME}/${PROG_NAME}.pid
RETVAL=0
txtgrn=$(tput setaf 2)
txtred=$(tput setaf 1)
txtrst=$(tput sgr0)
message() {
if [ $RETVAL -eq 0 ]; then
printf "%-45s[${txtgrn} OK ${txtrst}]\n" "$1"
else
printf "%-45s[${txtred}FAILED${txtrst}]\n" "$1"
fi
}
start() {
safe_myprog=`pidofproc $SAFE_MYPROG`
if [ -n "${safe_myprog}" ]; then
message $"$SAFE_PROG_NAME: is already running. pid: $safe_myprog"
return 0
fi
#$SAFE_MYPROG > /dev/null 2>&1
$SAFE_MYPROG &
RETVAL=$?
message $"Starting $PROG_NAME: "
if [ $RETVAL -eq 0 ]; then
touch $PROG_LOCK_FILE
fi
return $RETVAL
}
stop() {
safe_myprog=`pidofproc $SAFE_MYPROG`
if [ -n "${safe_myprog}" ]; then
/bin/kill $safe_myprog
fi
if [ -e $PROG_PID_FILE ]; then
pid=$(cat $PROG_PID_FILE)
if [ -n "$(ps -p $pid -o pid=)" ]; then
/bin/kill -9 "$pid"
RETVAL=$?
#if [ $# -eq 0 ]; then
message "Stopping $PROG_NAME: pid: $pid"
#fi
else
#if [ $# -eq 0 ]; then
message "$PROG_NAME is already stopped."
#fi
/bin/rm -f $PROG_PID_FILE
RETVAL=0
fi
fi
if [ -f $PROG_PID_FILE ]; then
/bin/rm -f $PROG_PID_FILE
fi
if [ -e $PROG_LOCK_FILE ]; then
/bin/rm -f $PROG_LOCK_FILE
fi
return $RETVAL
}
case "$1" in
start)
start
;;
stop)
stop
;;
esac
exit $RETVAL
如果我执行service myprog start
两次然后直接运行 safe_myprog,则 safe_myprog 跟踪输出的关键部分是:
++ __pids_pidof /usr/sbin/safe_myprog
++ pidof -c -m -o 14454 -o 30619 -o %PPID -x /usr/sbin/safe_myprog
++ pidof -c -m -o 14454 -o 30619 -o %PPID -x safe_myprog
++ return 3
+ safe_myprog=
+ '[' -n '' ']'
虽然第二次调用 start 给出了似乎是相同函数调用的输出:
++ __pids_pidof /usr/sbin/safe_myprog
++ pidof -c -m -o 14406 -o 14399 -o %PPID -x /usr/sbin/safe_myprog
+ safe_myprog=14339
+ '[' -n 14339 ']'
+ message 'safe_myprog: is already running. pid: 14339'
如果我pidof -c -m -o 14454 -o 30619 -o %PPID -x /usr/sbin/safe_myprog
在命令行上运行(执行后functions
),它会提供正确的答案。
使用该函数的包装器 shell 与使用该函数的 init.d shell 相比有什么不同pidofproc
,具体来说为什么pidof
似乎给出了不同的答案?