5

with a shell script, it is possible to tell when it's run with cron vs run manually?

UPDATE:

it was asked why I want to know. My cron job will be logging, and i want to be able to log if someone is executing it manually.

1
  • I had identical need and the first search result was this question. I ♥ teh internets (and Stack Exchange). Mar 22, 2012 at 18:09

4 Answers 4

8

In the times that I've needed to do this, i know it's a script that I'll never redirect to a file or to a pipe. So a simple test is to check if stdout (a.k.a file descriptor 1) is a tty (which it won't be from cron). In bash:

if [ -t 1 ]
then
    : # running from terminal
else
    : # not running from terminal, cron maybe
fi

Again, warning, this is a test simply if your stdout is a tty. But works for my simple purposes.

You could also check what your parent process is. In Linux, it can be as simple as:

if grep -q cron /proc/$PPID/cmdline &> /dev/null
then
    : # running from cron
fi
5
  • i still have to validate, but seems solid enough so far. if works, i'll mark as answer
    – Roy Rico
    Aug 4, 2010 at 22:16
  • More clever and more native than my environment variable answer. Be careful that using $PPID isn't checked within a grandchild process of cron. Aug 4, 2010 at 22:21
  • 1
    Hm, this will also fail if output is redirected (as then stdout is not a tty either). So just ./myscript > output will be detected as "not a tty", and even ./myscript | cat . So this does not really check for cron/not cron...
    – sleske
    Aug 4, 2010 at 22:27
  • 1
    Just FYI, it is easy to defeat the second check by wrapping the program with a script called 'cron'. Aug 5, 2010 at 4:46
  • This works great for what I intend to use it for.
    – Roy Rico
    Aug 21, 2010 at 18:36
5

You could define a unique environment variable in your crontab:

RUNNINGFROMCRON=1

16 18 * * *     /usr/local/bin/crontest

I tested with this script:

#! /bin/bash

echo " running script "

echo -n "testing for var: "
echo $RUNNINGFROMCRON

When I ran from cron output was:

running script 
testing for var: 1

When I ran from the command line manualy, output was:

running script 
testing for var:
1

You can inspect the name of the parent process, which can be retrieved with ps -p $PPID -o comm=. This is spoofable, of course.

However this is not necessarily a good idea (for example, you won't be able to easily test your cron jobs manually). Maybe if you explain why you want this someone can suggest a better solution.

2
  • This would work. It's a bit easier with my code snippet, checking out /proc/$PPID/cmdline. ps on Linux in effect snoops /proc/ anyway. Jan 24, 2014 at 16:08
  • @RichHomolka My ps snippet works on any POSIX system. If you target Linux only then using /proc is indeed slightly easier. Jan 24, 2014 at 17:11
0

You could create a special user for the cron job to run under. Then make your script readably by that user only, and put it in the user's crontab. That way, no other user can even read the script, let alone execute it.

BTW, for a secure solution you need to make the cron script unreadable anyway. If other users can read the script, they can copy it, remove whatever cron-check mechanism you have and then run it, bypassing your logging if they want to.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .