Shell脚本获得正确的PID

时间:2014-08-12 12:36:11

标签: linux shell pid init.d

我写了一个小程序,我想在Opensuse 11.3上作为服务启动 这是来自init.d脚本,它按我的意愿启动我的进程,但我没有得到正确的PID。

我错过了什么?

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

结果

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 )&

但是pidof会返回一些其他的pid。

如果我尝试直接执行它:

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

然后我收到错误:

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

我想因为我没有以正确的方式逃避变量?

这是整个剧本:

#!/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

配置文件:

## 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"

2 个答案:

答案 0 :(得分:3)

向其添加exec以防止分叉:

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

更新。请尝试以下脚本:

#!/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

配置文件:

## 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)

答案 1 :(得分:2)

如果在括号内有shell命令,则启动一个新的子shell。您在后台运行此子shell,它是您使用$!获得的子shell进程ID。

有两种解决方案:第一种是不在子shell中运行/sbin/startproc命令,而是直接将其放在后台。 secomd解决方案是监视由/sbin/startproc创建的pid文件。