linux - 用于启动进程的 Bash 脚本,随机等待,终止进程,重新启动

标签 linux bash random

我是一个绝对的初学者,我正在尝试创建一个 bash 脚本来随机化命令行应用程序的启动和退出。我计划在 autostart.sh 中稍作延迟后在启动时自动启动脚本 (Crunchbang)(在此处找到:http://interwebworld.co.uk/2011/10/23/how-to-launch-programs-automatically-at-startup-in-crunchbang-linux/)

(sleep 300s && /home/myuser/Scripts/randomizer.sh) &

这基本上是我需要在 randomizer.sh 脚本中用一些伪代码完成的:

start applicationfile
wait a random period of time
if applicationfile is still running
    kill its process
    wait a random period of time
    exit this script and restart this script
else exit this script and restart this script

我目前拥有的 randomizer.sh 如下(包含伪代码的残余部分), sleep 延迟在此处找到:http://blog.buberel.org/2010/07/howto-random-sleep-duration-in-bash.html,欢迎提供帮助。

/path/to/applicationfile -s 111.222.333.444 -u username -p password
sleep $[ ( $RANDOM % 150 ) + 60 ]m
if applicationfile is still running
    kill $(ps aux | grep '[u]sername' | awk '{print $2}')
    sleep $[ ( $RANDOM % 150 ) + 60 ]m
    exec $randomizer.sh
else exec $randomizer.sh

我“认为”非伪部分应该可以正常工作,但如果我错了请纠正我或进行调整。初始的 applicationfile 命令行按原样工作,我已经测试了进程终止行并且它按预期工作。 Applicationfile 没有从命令行结束自身的内置方法,但是远程机器上的死连接将在本地被杀死 5 分钟后被杀死,所以在本地杀死它可以满足我的需要。

我不知道如何处理 kill 上面的那一行,它首先检查进程“是否”正在运行。抱歉文字墙,但我想表明我已经尽我所能。

最佳答案

在 bash 中,$! 是最后启动的进程的 PID,所以按照这样的模式应该可以工作:

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

当然,您可以随意更改发送的信号、$RANDOM 与您想 sleep 的时间之间的关系等。

新进程不太可能获得相同的 PID,除非 a) 休眠时间很长或 b) 您的机器启动了很多短暂的进程。在 Linux 上,PID 是循环分配的,最大值为 32,765,因此,粗略地说,您必须在 sleep 时间内启动大约那么多的进程,才能冒着遇到属于不同进程的相同 PID 的风险。如果这是一个风险,您可以添加一个测试(从技术上讲,这里有一场比赛,但不太可能成为问题)。以下内容似乎可以满足您的要求。

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

我用等效循环替换了 self-exec

kill 行,由于竞争,将 stderr 重定向到 /dev/null 是可取的。该进程可能会在 ps 完成和执行 kill 之间自然退出,从而产生无害的错误消息。这种竞争是不可避免的(也是无害的),除非 PID 存在的测试和信号的发送是重合的。

如果打算同时运行最多一个 applicationfile 实例,则可以通过替换来完全避免这种竞争:

# 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

与:

killall -q applicationfile && sleep_a_while

如果这不能使用,Keith Reynolds 的测试变体更好,因为它避免了不必要的 grep,即使用:

# 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

关于linux - 用于启动进程的 Bash 脚本,随机等待,终止进程,重新启动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22867130/

相关文章:

node.js - Karma PhantomJs - Linux 和 Win 7 上的 TypeError 所有测试都成功

python - 使用 Python 从 Linux 核心服务器下载经过身份验证的 Django 应用程序的文件

linux - 是否有任何快捷方式可以引用 MV 命令中第一个参数的路径?

string - 在 bash 中,如何将 N 个参数连接在一起作为空格分隔的字符串

java - 从文本文件读取乐透

c++ - 你如何生成一个随机的 12 位数字?

python - 如何在Python中获取手动锁定机制的进程PID?

android - Android 上的 TCP FAST OPEN

macos - 如何在 Mac OS X 上以编程方式挂起/恢复进程及其子进程?

java - 在java中使用数组生成4个不重复的随机数