简体   繁体   English

Shell脚本获取正确的PID

[英]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. 我在Opensuse 11.3上编写了一个想作为服务启动的小程序,它是从init.d脚本启动的,它可以按我的意愿启动进程,但我没有得到正确的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. 但pidof会返回其他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"

Add exec to it to prevent forking: 向其中添加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}") &"

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)

When you have a shell-command inside parentheses you start a new sub-shell. 当括号内有shell命令时,将启动一个新的子shell。 You run this sub-shell in the background and it's that sub-shells process id you get with $! 您在后台运行此子shell,这是子shell处理通过$!获得的ID $! .

There are two solutions: The first is to not run the /sbin/startproc command in a subshell, but directly and put that in the background. 有两种解决方案:第一种是不在子shell中运行/sbin/startproc命令,而是直接将其放在后台。 The secomd solution is to monitor the pid file created by /sbin/startproc . 第二个解决方案是监视/sbin/startproc创建的pid文件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM