Bash脚本启动进程,等待随机,终止进程,重启

我是一个绝对的初学者,并试图创build一个bash脚本来随机化命令行应用程序的开始和退出。 我打算在启动(Crunchbang)后自动启动脚本,在autostart.sh中稍微延迟一下(可在http://interwebworld.co.uk/2011/10/23/how-to-launch-programs-自动启动在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,因为我到目前为止,我会欢迎一些帮助,如下(包含伪代码的残余),并在这里find睡眠延迟: http : //blog.buberel.org/2010/ 07 / HOWTO随机睡眠持续时间的function于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命令行照原样运行,我已经testing了进程kill行,并且按预期工作。 应用程序文件没有内置的方法从命令行自行结束,但远程计算机上的死连接在本地死亡5分钟后将被终止,因此在本地查杀是可以接受的。

我不知道如何处理kill之上的行,它首先检查进程是否在运行。 对不起墙上的文字,但我想表明我已经做了尽可能多的事情了。

Solutions Collecting From Web of "Bash脚本启动进程,等待随机,终止进程,重启"

在bash中, $! 是上一次启动的进程的PID,所以应该按照这个方式进行工作:

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

当然,您可以调整发送的信号,$ RANDOM和您想要睡觉的时间之间的关系等等。

除非a)睡眠时间很长,或者b)您的机器启动大量短暂的进程,否则新进程得到相同的PID不太可能。 在Linux上,PID的周期性分配最多为32,765个,所以,粗略地说,你必须在睡眠时间内启动大量的进程,才有可能触及属于不同进程的同一个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 

我用一个等价的循环取代了自我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 

试试这个代码为你的randomizer.sh

 min_val=60 range=150 while true ; do run_this_command & last_pid=$! sleep $[ ( $RANDOM % $range ) + $min_val ] { [ "$(ps -p $last_pid -o comm= )" ] && \ [ "$(ps -p $last_pid -o comm= )" = run_this_command ]; } && { kill -KILL $last_pid ;} done 

一些说明:

  1. 而不是使用exec语句。 只要呆在一个while循环中,你就可以完成你想要做的更多的事情。 我呈现的randomiser.sh只能从硬盘读取一次。
  2. 代码{ [ condition ] && { command ;} && command运行速度比if [ condition ]; then command, else command; fi更快if [ condition ]; then command, else command; fi if [ condition ]; then command, else command; fi
  3. 在变量$ last_pid被赋值为$!的情况下,命令ps -p $last_pid -o comm=会将PID $last_pid的进程名称吐出。 如果没有这个值的PID,那么它的存在代码是1。

修改为在开始之前满足额外的随机等待时间要求:

 # Minimum and range values for random Wait before start in seconds MinA=60;RangeA=150 # Minimum and range values for random Wait before kill in seconds MinB=60; RangeB=150 # while true ; do sleep $[ ( $RANDOM % $RangeA ) + $MinA ] run_this_command & last_pid=$! sleep $[ ( $RANDOM % $RangeB ) + $MinB ] { [ "$(ps -p $last_pid -o comm= )" ] && \ [ "$(ps -p $last_pid -o comm= )" = run_this_command ] } && \{ kill -KILL $last_pid ;} done