Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

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.

share|improve this question
    
I had identical need and the first search result was this question. I ♥ teh internets (and Stack Exchange). –  unhillbilly Mar 22 '12 at 18:09

4 Answers 4

up vote 7 down vote accepted

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
share|improve this answer
    
+1 for proc/$PPID/cmdline –  matthias krull Aug 4 '10 at 22:15
    
i still have to validate, but seems solid enough so far. if works, i'll mark as answer –  Roy Rico Aug 4 '10 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. –  Doug Harris Aug 4 '10 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 '10 at 22:27
1  
Just FYI, it is easy to defeat the second check by wrapping the program with a script called 'cron'. –  Slartibartfast Aug 5 '10 at 4:46

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:
share|improve this answer

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.

share|improve this answer
    
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. –  Rich Homolka Jan 24 at 16:08
    
@RichHomolka My ps snippet works on any POSIX system. If you target Linux only then using /proc is indeed slightly easier. –  Gilles Jan 24 at 17:11

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.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.