views:

332

answers:

5

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 this even from an imported module (not the main script).

+7  A: 

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.

Adam Matan
cron will run your crontab entry in a new shell, which would be the PPID of your Python script. You'll need to compare the PPID of the PPID.
digitalarbeiter
This assumes that the parent (cron) directly spawned off the child without a shell or something else in between. Not always true.
Noufal Ibrahim
+8  A: 

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.

Jason Orendorff
+1 This would be the right thing to do if you want different output based on whether you're outputting to the 'screen' or not.
Noufal Ibrahim
+3  A: 

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

Stefano Borini
+1  A: 

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.

njk
yup but he does not want to do that.
Stefano Borini
A: 

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

EOL