开发者

How can I determine if a python script is executed from crontab?

I would like to know how can I determine if a python script is executed from crontab?

I don't want a solution that will require adding a parameter because I want to be able to detect t开发者_开发问答his even from an imported module (not the main script).


Not quite what you asked, but maybe what you want is os.isatty(sys.stdout.fileno()), which tells if stdout is connected to (roughly speaking) a terminal. It will be false if you pipe the output to a file or another process, or if the process is run from cron.


Check its PPID - the ID of its parent process. Compare that to the cron pid; If they are the same, it was invoked by the crontab.

This can be done by:

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

The PID of the cron process in this example is 6363. It is worth mentioning that the PPID of cron is 1 - the init process.

Now find out what is the PID of your python program:

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

Its PID is 12992 and PPID is 6363, so it was indeed invoked by the cron process.

EDIT:

The cron process might not invoke your process directly. Hence, you'll have to traverse the PPIDs from your process upwards, till reaching PPID=1 or PPID=/usr/sbin/cron's PID. This can easily be done using a small shell or python script; just parse the output of ps:

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

The next step would be checkig /proc/7238, and so forth. Again, This is really easy to implement using shell or python script.

Thanks, @digitalarbeiter and @Noufal Ibrahim for pointing it out in your comments.


Set an environment variable at the cron command invocation. That works even within a module, as you can just check os.getenv().


The following shows how to detect whether the program has a terminal and whether it has a display. As a cron job, both will be returned as None.

#!/usr/bin/python

import os

term = os.getenv( "TERM" )
print( "term %s"%term )

display = os.getenv( "DISPLAY" )
print( "display %s"%display )

The output when run from a desktop terminal session will be similar to the following:

term xterm-256color
display :0

And when it is run as a cron job, the output will be:

term None
display None

You can test for the presence of either of these, like this

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

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

For one further example, the following selects an appropriate matplotlib backend when run from a cron job:

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


An easier workaround would be to pass a flag to the script only from the crontab, like --crontab, and then just check for that flag.


If you want to detect this from an imported module, I would have the main program set a global variable in the module, which would output different things depending on the value of this global variable (and have the main program decide how to set the variable through a flag that you would use in your crontab). This is quite robust (comparing to studying PPIDs).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜