Bash script to start process, wait random, kill process, restart

后端 未结 2 1130
予麋鹿
予麋鹿 2021-02-15 13:42

I\'m an absolute beginner and am trying to create a bash script to randomize the start and exit of a command line app. I plan to autostart the script on boot (Crunchbang) after

2条回答
  •  南笙
    南笙 (楼主)
    2021-02-15 14:03

    In bash, $! is the PID of the last launched process, so something patterned along the lines of this should work:

    mycommand &
    last_pid=$!
    sleep( $RANDOM )
    kill -KILL $last_pid
    

    You can, of course, fiddle around to change the signal you send, the relationship between $RANDOM and the time you want to sleep, etc.

    It's somewhat unlikely that a new process will get the same PID unless either a) the sleep time is very long or b) your machine launches a lot of short-lived processes. On Linux, PIDs are allocated cyclically with a max of 32,765, so, roughly speaking, you would have to have launched about that many processes in the sleep time to risk hitting the same PID belonging to a different process. If that's a risk, you could add a test (technically, there's a race here, but it's very unlikely to be a problem). The following seems like it would do what you want.

    signal=KILL
    
    sleep_a_while () {
        sleep $[ ( $RANDOM % 150 ) + 60 ]m
    }
    
    while true; do
        # Note: command launched in background:
        /path/to/applicationfile -s 111.222.333.444 -u username -p password &
    
        # Save PID of command just launched:
        last_pid=$!
    
        # Sleep for a while:
        sleep_a_while
    
        # See if the command is still running, and kill it and sleep more if it is:
        if ps -p $last_pid -o comm= | grep -qs '^applicationfile$'; then
            kill -$signal $last_pid 2> /dev/null
            sleep_a_while
        fi
    
        # Go back to the beginning and launch the command again
    done
    

    I've replaced the self-exec with an equivalent loop.

    On the kill line, the redirect of stderr to /dev/null is desirable because of a race. The process might exit naturally between the time the ps completes and the time that the kill is executed, resulting in a harmless error message. This race is unavoidable (and harmless) unless the test that the PID exists and the sending of the signal are coincident.

    If there is intended to be at most one instance of applicationfile running at a time, then this race can be avoided entirely by replacing:

    # See if the command is still running, and kill it and sleep more if it is:
    if ps -p $last_pid -o comm= | grep -qs '^applicationfile$'; then
        kill -$signal $last_pid 2> /dev/null
        sleep_a_while
    fi
    

    With:

    killall -q applicationfile && sleep_a_while
    

    If this cannot be used, Keith Reynolds's variant of the test is better, since it avoids an unnecessary grep, i.e. using:

    # See if the command is still running, and kill it and sleep more if it is:
    if [ "$(ps -p $last_pid -o comm=)" = "applicationfile" ]; then
        kill -$signal $last_pid 2> /dev/null
        sleep_a_while
    fi
    

提交回复
热议问题