我想通过crontab执行我的python文件,只要它已经关闭或没有运行。我尝试在cron选项卡中添加以下条目,但它不起作用
24 07 * * * pgrep -f test.py || nohup python /home/dp/script/test.py & > /var/tmp/test.out
如果我手动运行pgrep -f test.py || nohup python /home/dp/script/test.py & > /var/tmp/test.out
test.py工作正常,如果我删除pgrep -f test.py ||它也适用于crontab从我的crontab,只是保持24 07 * * * nohup python /home/dp/script/test.py & > /var/tmp/test.out
如果我添加pgrep -f,任何想法为什么crontab不起作用?有没有其他方法我可以运行test.py一次,以避免test.py的多个运行进程?谢谢,迪帕克
我用一个运行无限循环的script.py
进行了测试。然后
pgrep -f script.py
...从终端,给了一个pid,13132
,从cron运行:
pgrep -f script.py > /path/to/out.txt
输出两个pids,13132
和13635
。
因此,我们可以得出结论,当从cron运行时,命令pgrep -f script.py
将自己列为匹配。不确定如何以及为什么,但最有可能的是,这是由于cron
使用非常有限的一组环境变量(HOME,LOGNAME和SHELL)运行而间接引起的。
从(包装器)脚本运行pgrep -f
使得命令不会自行列出,即使从cron
运行也是如此。随后,从cron
运行包装器:
#!/bin/bash
if ! pgrep -f 'test.py'
then
nohup python /home/dp/script/test.py & > /var/tmp/test.out
# run the test, remove the two lines below afterwards
else
echo "running" > ~/out_test.txt
fi
通常最好在应用程序中检查应用程序是否正在运行,而不是从外部检查并启动它。在流程中管理流程而不是期望其他流程执行流程。
这将确保您可以更好地控制流程的生命周期,并让您决定在发生故障时该怎么做。
更不用说,如果您想确保应用程序的运行时间很长,最好使用Monit等监控服务。同样,这将取决于您的应用程序添加一个健全层,说明它是否正常。
cron可能会看到pgrep -f test.py
进程以及test.py
进程,从pgrep
给你错误的结果。
尝试没有-f
的命令,这应该只是寻找test.py
的出现或用-f
替换-o
,它将寻找最老的事件。
您的另一个选择是插入test.py中的内容:
Pid = os.popen('pgrep -f test.py').read(5).strip()
这将允许您检查代码本身,如果它已经在运行。
遇到这个老问题,我自己寻找解决方案。
使用psutil:
import psutil
import sys
from subprocess import Popen
for process in psutil.process_iter():
if process.cmdline() == ['python', 'your_script.py']:
sys.exit('Process found: exiting.')
print('Process not found: starting it.')
Popen(['python', 'your_script.py'])
您还可以使用上一个进程的开始时间来确定它是否运行得太长并且可能会挂起:
process.create_time()
该过程还有大量其他有用的元数据。
问题是pgreg -f
正在识别cron用来运行命令本身的shell脚本。
我通过在rot13中编码文件名并使用python单行解码来解决pgrep -f
问题,因为我不想为cron作业添加脚本包装器。即:
pgrep -f $(python3 -c 'import codecs; print(codecs.decode("grfg.cl", "rot13"))') || nohup python /home/dp/script/test.py & > /var/tmp/test.out
补充:您可以使用tr来解码rot13,这将导致更短且更容易阅读的命令:
pgrep -f $(echo grfg.cl | tr a-zA-Z n-za-mN-ZA-M) || nohup python /home/dp/script/test.py & > /var/tmp/test.out
为什么只检查pid已经像这样运行了
Pid = os.popen('pgrep -f myscript.py').readlines()
if len(Pid) > 1:
exit()
您可以通过名称test.py创建测试文件如果您尝试再次执行相同的文件,它应该退出。
import time
import os
from tempfile import TemporaryFile
import subprocess
def cron_running(p_name):
run_cnt=0
with TemporaryFile() as tf:
subprocess.call(["ps","ax"], stdout=tf)
tf.seek(0)
for line in tf:
if p_name in line.decode('ascii'):
run_cnt+=1
if run_cnt > 1:
quit()
if cron_running(os.path.basename(__file__)):
print("cron is already running")
quit()
for i in range(60):
time.sleep(1)