pidofproc 或 pidof 从 init.d 工作,但不从 /usr/sbin 工作

pidofproc 或 pidof 从 init.d 工作,但不从 /usr/sbin 工作

我有一个正在支持的 Linux 服务。它提供了常用的start命令stop。设计者创建了一个包装命令,旨在控制主函数的启动和重试。包装器包括一个初步检查,以查看它是否已经通过调用pidofproc自身来运行。启动和停止功能也使用它来进行检查。

我发现 init.d 程序中的启动和停止函数在调用后使用 pidofproc 没有问题. /etc/init.d/functions,但包装器无法执行在我看来是同一件事的操作。

我注意到原来的包装纸有一些问题。最初它没有调用functions.然后它没有正确测试字符串形式的返回值。我还注意到服务脚本是 bash 脚本,包装器是 shell,所以我将其切换为 bash。这些都没有帮助。

我创建了问题的 MCVE。它的行为似乎很像真实的代码,尽管包装器只是做了一个无用的 while 循环来保持运行。问题是,如果您myprog在已经有一个实例正在运行时运行,则跟踪清楚地表明,__pids_pidoffunctions 中的函数无法从 获取返回值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似乎给出了不同的答案?

相关内容