cron:运行一个进程,但仅当它不在运行时?


11

有没有办法告诉我cron运行某个应用程序,但如果已经存在某个进程,则不要运行它?

linux  cron 

您能否说明该应用程序是否已经在运行,或者是否已经在运行其他进程,则该应用程序不应该运行。谢谢
Linker3000

Answers:


23

最简单的方法,使用pgrep

在crontab中:

* * * * * pgrep processname > /dev/null || /path/to/processname -args0 -args1

喜欢这个答案的简单性。仅供参考,您应该能够将-f标志添加到pgrep中,然后可以检查完整的进程名称,如果您还想检查进程的参数作为条件的一部分,则这很有用。
2014年

6
不,您不能在cronjob中对pgrep使用-f标志。原因是您将与用于运行cronjob本身的shell脚本匹配。
CpnCrunch

使用cron运行GUI进程时,请添加前缀export DISPLAY=:0以防止Could not connect to display发生错误。* * * * * export DISPLAY=:0 && pgrep processname > /dev/null || /path/to/processname -args0 -args1
杰姆(Benjam)

9

运行脚本,而不是直接运行程序。有很多可能性。例如 :

MYPROG="myprog"
RESTART="myprog params"
PGREP="/usr/bin/pgrep"
# find myprog pid
$PGREP ${MYPROG}
# if not running
if [ $? -ne 0 ]
then
   $RESTART
fi

1
仅供参考-使用标量变量存储参数列表被认为是不好的做法。有关失败情况的示例,请参见mywiki.wooledge.org/BashFAQ/050
Charles Duffy 2013年

...类似,pgrep myprog; if [ $? -ne 0 ]; then ...最好写成if ! pgrep myprog; then ...
Charles Duffy 2013年

...后一种样式不仅可读性强,而且更不易出错:$?例如,通过在行之间添加日志消息或错误处理,很容易无意间破坏的值。
Charles Duffy 2013年

7

如果先前的实例尚未完成,则此脚本将不会再次运行。如果您不想在运行其他特定进程的情况下不运行某些程序,请参阅harrymc的脚本。

DATE=`date +%c`;
ME=`basename "$0"`;
LCK="./${ME}.LCK";
exec 8>$LCK;

if flock -n -x 8; then
  echo ""
  echo "Starting your script..."
  echo ""

[PUT YOUR STUFF HERE]

  echo ""
  echo "Script started  $DATE";
  echo "Script finished `date +%c`";
else
  echo "Script NOT started - previous one still running at $DATE";
fi

3

您可以在脚本中使用锁定文件,但请参阅“ 流程管理”

flock 是一种可以使用的实用程序。


好一个!现在,在这条慢速线路上进行rsync可以花费所有时间,无需客户端干预即可在客户端主机上线后5分钟内触发:*/5 * * * * root flock /run/shm rsync -auhx --numeric-ids -e "ssh -T -c arcfour128 -o Compression=no -x" [source] [user]@[host]:[dest]
eMPee584 2016年

1

通常由程序本身而不是由处理cron。为此,有两种标准技术:

1)grep的输出ps以查看是否已经有该名称的进程正在运行

2)在启动时,首先检查pid(进程ID)文件的存在(通常在/var/run/program_name.pid),如果存在,则从文件中读取pid,并检查该进程是否仍然存在;如果是这样,请拒绝启动。如果pid文件不存在或文件中的pid已消失,则创建一个pid文件,将您的进程ID写入其中,然后继续正常启动。

虽然在技术上可以将可以直接执行这两个操作的bash管道写入到crontab中,但最好将它们添加到正在启动的程序中(以便无论如何启动它们都可以应用)或编写包装脚本来如harrymc建议的那样处理此问题。


0

* * * * * pgrep -f "[p]attern" > /dev/null || /path/to/processname -args0 -args1

我将上述答案重新用于模式匹配。没有f选项的pgrep与进程模式不匹配。但是使用f选项存在问题。使用f选项,生成cron的外壳程序总是匹配并返回其pid,因此该进程永远不会重新启动。

在其中一个字母模式附近添加[]只会匹配该进程,并且不会返回cron shell的pid。


0

文件:https//www.timkay.com/solo/

solo是一个非常简单的脚本(10行),可防止程序一次运行多个副本。使用cron来确保作业在上一个作业完成之前不会运行是很有用的。

* * * * * solo -port=3801 ./job.pl blah blah
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.