【问题标题】:How can I determine if a python script is executed from crontab?如何确定是否从 crontab 执行 python 脚本?
【发布时间】:2011-01-06 09:58:29
【问题描述】:

我想知道如何确定是否从 crontab 执行 python 脚本?

我不想要需要添加参数的解决方案,因为我希望即使从导入的模块(不是主脚本)也能检测到这一点。

【问题讨论】:

  • 你为什么想知道这个?
  • 例如我想改变它的输出方式。从终端运行时,我想通过 ANSI 转义序列使用着色,但从终端运行时,我想要纯文本以便接收漂亮的电子邮件。
  • 然后检查终端,而不是cron。
  • @digitalarbeiter:我认为这只是一个例子。也许他想要比这更复杂的东西。
  • @Stefano:是的,但是“显式优于隐式”。明确地检查你真正需要的东西。适用于 TERM,适用于任何其他行为变化。

标签: python unix terminal cron


【解决方案1】:

检查其 PPID - 其父进程的 ID。将其与 cron pid 进行比较;如果它们相同,则由 crontab 调用。

这可以通过以下方式完成:

$ sudo ps -Af | grep cron | grep -v grep
root  6363  1  0 10:17 ?  00:00:00 /usr/sbin/cron

本例中cron进程的PID为6363,值得一提的是cron的PPID为1-the init process

现在找出你的python程序的PID是什么:

$  sudo ps -Af | grep SorinSbarnea.py
adam  12992  6363  1 12:24 pts/2  00:04:21 /usr/bin/python SorinSbarnea.py

它的PID是12992,PPID是6363,所以确实是cron进程调用的。

编辑:

cron 进程可能不会直接调用您的进程。因此,您必须从您的进程向上遍历 PPID,直到达到 PPID=1 或 PPID=/usr/sbin/cron 的 PID。这可以使用小型 shell 或 python 脚本轻松完成;只解析ps的输出:

$ cat /proc/12992/status
....
Pid:    12992
PPid:   7238
Uid:    1000    1000    1000    1000
Gid:    1000    1000    1000    1000
...

下一步是检查 /proc/7238,依此类推。同样,这很容易使用 shell 或 python 脚本实现。

感谢@digitalarbeiter 和@Noufal Ibrahim 在您的 cmets 中指出这一点。

【讨论】:

  • cron 将在一个新的 shell 中运行你的 crontab 条目,这将是你的 Python 脚本的 PPID。您需要比较 PPID 的 PPID。
  • 这假定父 (cron) 直接从子生成,没有外壳或其他东西。并非总是如此。
【解决方案2】:

不是你问的那样,但也许你想要的是os.isatty(sys.stdout.fileno()),它告诉stdout是否连接到(粗略地说)终端。如果您将输出通过管道传输到文件或另一个进程,或者该进程是从 cron 运行的,那么它将是错误的。

【讨论】:

  • +1 如果您希望根据是否输出到“屏幕”而产生不同的输出,这将是正确的做法。
  • sys.stdout.isatty()os.isatty(sys.stdout.fileno()) 更直接。
【解决方案3】:

cron 命令调用处设置环境变量。这甚至在一个模块中也有效,因为您只需检查os.getenv()

【讨论】:

    【解决方案4】:

    更简单的解决方法是仅从 crontab 将标志传递给脚本,例如 --crontab,然后检查该标志。

    【讨论】:

    • 是的,但他不想那样做。
    • 原帖明确表示这不是他想要的。
    【解决方案5】:

    如果你想从导入的模块中检测到这一点,我会让主程序在模块中设置一个全局变量,它会根据这个全局变量的值输出不同的东西(并让主程序决定如何通过您将在 crontab 中使用的标志设置变量)。这是相当稳健的(与研究 PPID 相比)。

    【讨论】:

      【解决方案6】:

      下面展示了如何检测程序是否有终端以及是否有显示。作为 cron 作业,两者都将返回为 None。

      #!/usr/bin/python
      
      import os
      
      term = os.getenv( "TERM" )
      print( "term %s"%term )
      
      display = os.getenv( "DISPLAY" )
      print( "display %s"%display )
      

      从桌面终端会话运行时的输出将类似于以下内容:

      term xterm-256color
      display :0
      

      当它作为 cron 作业运行时,输出将是:

      term None
      display None
      

      您可以像这样测试其中任何一个的存在

      if term is None:
          print( "no terminal" )
      
      if display is None:
          print( "no display" )
      

      再举一个例子,当从 cron 作业运行时,下面会选择一个合适的 matplotlib 后端:

      if os.getenv( "DISPLAY" ) is None:
          print( "Using Agg" )
          import matplotlib
          matplotlib.use('Agg')
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-03-16
        • 1970-01-01
        • 2012-02-02
        • 2012-10-26
        • 1970-01-01
        • 1970-01-01
        • 2015-10-14
        • 1970-01-01
        相关资源
        最近更新 更多