Sample Header Ad - 728x90

pidofproc or pidof working from init.d but not from /usr/sbin

1 vote
0 answers
817 views
I have a Linux service I'm supporting. It offers the usual start and stop commands. The designer created a wrapper command that is meant to control startup and retries of the main function. The wrapper includes a preliminary check to see if it is already running by calling pidofproc on itself. The start and stop functions also use this for checking. What I'm finding is that the start and stop functions in the init.d program have no problem using pidofproc after calling . /etc/init.d/functions but the wrapper fails doing what appears to me to be the same thing. I noticed a few things wrong with the original wrapper. Initially it wasn't invoking functions. Then it wasn't testing the return value as a string correctly. I also noticed that the service script is a bash script and the wrapper was a shell, so I switched it to bash. None of those helped. I created a MCVE of the problem. It seems to behave much like the real code, although the wrapper is just doing a useless while loop to remain running. The problem is that if you run myprog when there is already an instance running, the trace clearly shows that the __pids_pidof function in functions fails to get a return value from pidof, while the start and stop scripts work fine. What's the difference? Wrapper script example /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
Service program /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
If I do a service myprog start twice and then run safe_myprog directly the key part of the trace output from safe_myprog is:
++ __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 '' ']'
While the second call to start gave this output from what seems to be the same function call:
++ __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'
If I run pidof -c -m -o 14454 -o 30619 -o %PPID -x /usr/sbin/safe_myprog on the command line (after executing functions) it provides the correct answer. What is different about the wrapper shell using the pidofproc function compared to the init.d shell using it, and specifically why is pidof seeming to give different answers?
Asked by Sinc (193 rep)
Jul 3, 2019, 08:24 PM
Last activity: Jul 5, 2019, 03:47 PM