Search code examples
linuxshellpidinit.d

Shell script get the right PID


I wrote a little program that I want to start as a service on Opensuse 11.3 This is from the init.d script, it starts my processes as I want but I don't get the right PID.

What am I missing?

echo "Starting DHCPALERT"
for (( i = 1; i <= $DHCP_AL_DAEMONS; i++ ))
do
    var="DHCP_AL_$i"
    START_CMD="exec /sbin/startproc -p "$DHCP_AL_PID_DIR"p_"$i".pid -l "$DHCP_AL_LOG_DIR"log_"$i".log "$DHCPALERT_BIN" "${!var}" &"
    eval $START_CMD
    echo "PID: "$!
    echo "Command: "$START_CMD
done

results in

PID: 47347
Command: (/sbin/startproc -p /var/log/sthserver/dhcpalert/p_2.pid -l /var/log/sthserver/dhcpalert/log_2.log /usr/sbin/dhcpalert -i eth1 -c ./test.sh -a 00:15:5D:0A:16:07 -v )&

but pidof returns some othe pid.

If I try to execute it directly:

exec /sbin/startproc -p "$DHCP_AL_PID_DIR"p_"$i".pid -l "$DHCP_AL_LOG_DIR"log_"$i".log "$DHCPALERT_BIN" "${!var}" &

Then I get errors:

startproc:  exit status of parent of /usr/sbin/dhcpalert: 1

I suppose because I don't escape the variables the right way?

This is the whole script:

#!/bin/sh
# Check for missing binaries (stale symlinks should not happen)
# Note: Special treatment of stop for LSB conformance
DHCPALERT_BIN=/usr/sbin/dhcpalert
#-x FILE exists and is executable
test -x $DHCPALERT_BIN || { echo "$DHCPALERT_BIN not installed"; 
    if [ "$1" = "stop" ]; then exit 0;
    else exit 5; fi; }

# Check for existence of needed config file and read it
DHCPALERT_CONFIG=/etc/sysconfig/dhcpalert
#-r FILE exists and is readable
test -r $DHCPALERT_CONFIG || { echo "$DHCPALERT_CONFIG not existing";
    if [ "$1" = "stop" ]; then exit 0;
    else exit 6; fi; }

# Read config to system VARs for this shell session only same as "source FILE"
. $DHCPALERT_CONFIG

#check for exitstence of the log dir
if [ -d "$DHCP_AL_LOG_DIR" ]; then
        echo "exists 1"
        echo "exists 2"
        echo "exists 3"
        if [ "$1" = "start" ]; then
            echo "Deleting all old log files from: "
            echo "Dir:... "$DHCP_AL_LOG_DIR
            rm -R $DHCP_AL_LOG_DIR
            mkdir $DHCP_AL_LOG_DIR
        fi
    else
        echo "does not exist 1"
        echo "does not exist 2"
        echo "does not exist 3"
        echo "Directory for Logfiles does not exist."
        echo "Dir:... "$DHCP_AL_LOG_DIR
        echo "Createing dir..."
        mkdir $DHCP_AL_LOG_DIR
    fi


. /etc/rc.status

# Reset status of this service
rc_reset

case "$1" in
    start)
    echo "Starting DHCPALERT"
    for (( i = 1; i <= $DHCP_AL_DAEMONS; i++ ))
    do
        var="DHCP_AL_$i"

        exec /sbin/startproc -p "$DHCP_AL_PID_DIR"p_"$i".pid -l "$DHCP_AL_LOG_DIR"log_"$i".log "$DHCPALERT_BIN" "${!var}" &

       # START_CMD="exec /sbin/startproc -p "$DHCP_AL_PID_DIR"p_"$i".pid -l "$DHCP_AL_LOG_DIR"log_"$i".log "$DHCPALERT_BIN" "${!var}" &"
       # eval $START_CMD
        echo "PID: "$!
       # echo "Command: "$START_CMD
    done

    rc_status -v
    ;;
    stop)
    echo -n "Shutting down DHCPALERT "

    /sbin/killproc -TERM $DHCPALERT_BIN
    rc_status -v
    ;;
    try-restart|condrestart)
    if test "$1" = "condrestart"; then
        echo "${attn} Use try-restart ${done}(LSB)${attn} rather than condrestart ${warn}(RH)${norm}"
    fi
    $0 status
    if test $? = 0; then
        $0 restart
    else
        rc_reset    # Not running is not a failure.
    fi
    rc_status
    ;;
    restart)
    $0 stop
    $0 start
    rc_status
    ;;
    force-reload)
    echo -n "Reload service DHCPALERT "
    /sbin/killproc -HUP $DHCPALERT_BIN
    rc_status -v
    ;;
    reload)
    echo -n "Reload service DHCPALERT "
    /sbin/killproc -HUP $DHCPALERT_BIN
    rc_status -v
    ;;
    status)
    echo -n "Checking for service DHCPALERT "
    /sbin/checkproc $DHCPALERT_BIN
    rc_status -v
    ;;
    probe)

    test /etc/DHCPALERT/DHCPALERT.conf -nt /var/run/DHCPALERT.pid && echo reload
    ;;
    *)
    echo "Usage: $0 {start|stop|status|try-restart|restart|force-reload|reload|probe}"
    exit 1
    ;;
esac
rc_exit

The configfile:

## Specifiy where to store the Pid files
DHCP_AL_PID_DIR="/var/log/sthserver/dhcpalert/"
##
## Specifiy where to store the Log file
DHCP_AL_LOG_DIR="/var/log/sthserver/dhcpalert/"
##
## is needed to determine how many vars should be read and started!
DHCP_AL_DAEMONS="2"
##                        
## Then DHCP_AL_<number> to specify the command that one instance of 
## dhcpalert should be started
DHCP_AL_1="-i eth0 -c ./test.sh -a 00:15:5D:0A:16:06 -v"
DHCP_AL_2="-i eth1 -c ./test.sh -a 00:15:5D:0A:16:07 -v"

Solution

  • Add exec to it to prevent forking:

    START_CMD="(exec /sbin/startproc -p "$DHCP_AL_PID_DIR"p_"$i".pid -l "$DHCP_AL_LOG_DIR"log_"$i".log "$DHCPALERT_BIN" "${!var}") &"
    

    Update. Please try this script:

    #!/bin/bash
    # Check for missing binaries (stale symlinks should not happen)
    # Note: Special treatment of stop for LSB conformance
    DHCPALERT_BIN=/usr/sbin/dhcpalert
    #-x FILE exists and is executable
    [[ -x $DHCPALERT_BIN ]] || {
        echo "$DHCPALERT_BIN not installed"
        if [ "$1" = "stop" ]; then
            exit 0
        else
            exit 5
        fi
    }
    
    # Check for existence of needed config file and read it
    DHCPALERT_CONFIG=/etc/sysconfig/dhcpalert
    #-r FILE exists and is readable
    [[ -r $DHCPALERT_CONFIG ]] || {
        echo "$DHCPALERT_CONFIG not existing"
        if [[ $1 == stop ]]; then
            exit 0
        else
            exit 6
        fi
    }
    
    # Read config to system VARs for this shell session only same as "source FILE"
    . "$DHCPALERT_CONFIG"
    
    #check for exitstence of the log dir
    
    CREATE_DIR=false
    
    if [[ -d $DHCP_AL_LOG_DIR ]]; then
        echo "exists 1"
        echo "exists 2"
        echo "exists 3"
        if [[ $1 == start ]]; then
            echo "Deleting all old log files from: "
            echo "Dir:... $DHCP_AL_LOG_DIR"
            rm -R "$DHCP_AL_LOG_DIR"
            CREATE_DIR=true
        fi
    else
        echo "does not exist 1"
        echo "does not exist 2"
        echo "does not exist 3"
        echo "Directory for Logfiles does not exist."
        CREATE_DIR=true
    fi
    
    if [[ $CREATE_DIR == true ]]; then
        echo "Dir:... $DHCP_AL_LOG_DIR"
        echo "Createing dir..."
        mkdir "$DHCP_AL_LOG_DIR" || {
            echo "Failed to create directory $DHCP_AL_LOG_DIR"
            exit 1
        }
    fi
    
    . /etc/rc.status
    
    # Reset status of this service
    rc_reset
    
    case "$1" in
    start)
        echo "Starting DHCPALERT"
        for (( I = 1; I <= DHCP_AL_DAEMONS; ++I )); do
            REF="DHCP_AL_${I}[@]"
            COMMAND=(/sbin/startproc -p "${DHCP_AL_PID_DIR}p_${I}.pid" -l "${DHCP_AL_LOG_DIR}log_${I}.log" "$DHCPALERT_BIN" "${!REF}")
            echo "COMMAND: ${COMMAND[*]}"
            "${COMMAND[@]}" &
            PID=$!
            echo "PID: $PID"
        done
        rc_status -v
        ;;
    stop)
        echo -n "Shutting down DHCPALERT "
        /sbin/killproc -TERM "$DHCPALERT_BIN"
        rc_status -v
        ;;
    try-restart|condrestart)
        [[ $1 == condrestart ]] && echo "${attn} Use try-restart ${done}(LSB)${attn} rather than condrestart ${warn}(RH)${norm}"
        "$0" status  ## ??
        if [[ $? -eq 0 ]]; then
            "$0" restart
        else
            rc_reset    # Not running is not a failure.
        fi
        rc_status
        ;;
    restart)
        "$0" stop
        "$0" start
        rc_status
        ;;
        force-reload)
        echo -n "Reload service DHCPALERT "
        /sbin/killproc -HUP "$DHCPALERT_BIN"
        rc_status -v
        ;;
    reload)
        echo -n "Reload service DHCPALERT "
        /sbin/killproc -HUP "$DHCPALERT_BIN"
        rc_status -v
        ;;
    status)
        echo -n "Checking for service DHCPALERT "
        /sbin/checkproc "$DHCPALERT_BIN"
        rc_status -v
        ;;
    probe)
        [[ /etc/DHCPALERT/DHCPALERT.conf -nt /var/run/DHCPALERT.pid ]] & echo reload
        ;;
    *)
        echo "Usage: $0 {start|stop|status|try-restart|restart|force-reload|reload|probe}"
        exit 1
        ;;
    esac
    
    rc_exit
    

    Config file:

    ## Specifiy where to store the Pid files
    DHCP_AL_PID_DIR="/var/log/sthserver/dhcpalert/"
    ##
    ## Specifiy where to store the Log file
    DHCP_AL_LOG_DIR="/var/log/sthserver/dhcpalert/"
    ##
    ## is needed to determine how many vars should be read and started!
    DHCP_AL_DAEMONS="2"
    ##
    ## Then DHCP_AL_<number> to specify the command that one instance of
    ## dhcpalert should be started
    DHCP_AL_1=(-i eth0 -c ./test.sh -a 00:15:5D:0A:16:06 -v)
    DHCP_AL_2=(-i eth1 -c ./test.sh -a 00:15:5D:0A:16:07 -v)