【问题标题】:crontab to run python file if not running alreadycrontab 如果尚未运行,则运行 python 文件
【发布时间】:2023-04-01 16:20:01
【问题描述】:

我只想通过 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 的多个运行进程? 谢谢, 迪帕克

【问题讨论】:

标签: python crontab


【解决方案1】:

pgrep -f 从 cron 运行时将自身列为错误匹配

我使用运行无限循环的script.py 进行了测试。那么

pgrep -f script.py

...从终端,给 一个 pid, 13132 ,同时从 cron 运行:

pgrep -f script.py > /path/to/out.txt

输出 两个 pid,1313213635

因此,我们可以得出结论,当从 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

【讨论】:

  • if [ -z $(command) ] 通常是 if command 的反模式,前提是 command 编写正确。
  • @tripleee 不确定你的意思,if [ -z "$(pgrep -f 'test.py')" ] 是一个有效的测试。
  • 这不是错误的,但在风格上非常可疑。命令产生退出代码的原因是您可以在ifwhile 条件下使用它们。
  • @triplee 感谢提及,这对我来说是新的,但很有意义。现已修复。
  • if 中的第二个pgrep 似乎也是多余的。
【解决方案2】:

通常最好在应用程序内部检查应用程序是否正在运行,而不是从外部检查并启动它。在流程中管理流程,而不是期望另一个流程来做。

  1. 让 cron 始终运行应用程序
  2. 在应用程序开始执行时,有一个锁定文件或类似的机制来判断进程是否已经在运行。
  3. 如果应用程序已在运行,请在上次测试时间的某处更新并中断新进程。
  4. 如果应用程序未运行,请登录某处并通知某人(如果需要)并触发进程启动。

这将确保您可以更好地控制流程的生命周期,并让您决定在出现故障时该怎么做。

更不用说,如果你想确保应用程序的正常运行时间很高,最好使用Monit等监控服务。同样,这将取决于您的应用程序是否添加一个健全层来说明它是否正常。

【讨论】:

    【解决方案3】:

    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()
    

    这将允许您检查代码本身,如果它已经在运行。

    【讨论】:

      【解决方案4】:

      自己遇到了这个老问题,正在寻找解决方案。

      使用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()
      

      该过程还有大量其他有用的元数据。

      【讨论】:

        【解决方案5】:

        问题是pgreg -f 正在识别 cron 用来运行命令本身的 shell 脚本。

        我解决了pgrep -f 问题,方法是在 rot13 中编码文件名并使用 python 单线对其进行解码,因为我不想仅为 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
        

        【讨论】:

          【解决方案6】:

          为什么只检查 pid 已经像这样运行了

          Pid = os.popen('pgrep -f myscript.py').readlines()
          if len(Pid) > 1:
           exit()
          

          【讨论】:

            【解决方案7】:

            你可以创建一个名为 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)
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2015-11-17
              • 2017-11-27
              • 1970-01-01
              • 2018-08-09
              • 2018-07-17
              • 1970-01-01
              • 1970-01-01
              • 2022-10-24
              相关资源
              最近更新 更多