How to determine the script is called from CRON?

Hello expert,

What I want is to determine whether the script is called from CRON or it is executed interactively?

I tried the following but no luck:

#!/bin/ksh

cronID=`pgrep -x cron`
GPID=`ps -ef -o ppid,pid | grep " $PPID$" | awk '{print $1}'`

if [ "$cronID" == "$GPID" ]; then
echo I am being run through cron
else
echo I am NOT being run through cron
fi

There can be a lot of processes named cron. You are picking one at random and attempting to see if it's your parent. In your crontab entry do something that you won't do interactively. Like:
55 18 * * * /path/to/script runfromcron
Then just check $1.

if [[ $1 = runfromcron ]] ; then
      echo running from cron
      shift
else
      echo not running from cron
fi

This faster, easier, and you have a way to more easily test the script's operation.

How about checking those LOGIN specific environment variables from within the script? These variables are (check man page of the shell) such as $TERM, $PS1, etc.

Tom

While agreeing with the rest of your post on this (minor) issue I'd like to disagree: that depends on the system you're running on. AIX, for instance, has cron started in /etc/inittab with the "respawn" option and hence there is no need to start more than one cron processes. In my career as AIX administrator I have never seen mor than one cron process active (or any number of cron instances save 1, for that matter).

bakunin

crontab -e and look for the script.

I guess the real question is you want to
know whether your script is running interactively or not?
I do this for bash scripts:

if ! tty > /dev/null; then
    echo "running non interactively"
fi

How often have you looked for multiple cron processes? Would you notice a second cron if you simply ran a "ps -ef" but were looking for something else? I can't speak to AIX since I've never worked on it. But on other systems, cron runs programs by forking itself, fiddling with the environment, and then exec'ing the program to be run. After the fork, and prior to the exec you have a 2nd process named cron. Most people tend to not schedule jobs to be run at, say, exactly at 4 minutes after midnight. Instead everyone and his brother will tend to schedule stuff,say, exactly at midnight. At these busy points, you can have dozens of cron processes waiting to exec. I have often seen several cron processes on both HP-UX and Solaris. In addition, we have a monitoring system called Big Brother that used to check for for exactly one copy of cron running. I got dragged out of bed at 2 in the morning because cron forked and Big Bro freaked. Big Bro has now been corrected.

Also I do not really approve of running "ps -ef" and looking for processing by name. Users can write their own programs and they can call one of their own programs "cron". We just had a case where a developer wrote a program to be invoked from cron. And yes, he called the program to be invoked: cron. In the case of pgrep, "pgrep -u root -x cron" would at least avoid that, but the forking problem remains.

... i'm no expert but ...

if you're running the script or program on the command line by yourself --- it's running interactively

if the script is regularly running at specific times (i.e., at 1 PM every day) without your intervention or anybody else's --- it's most likely being run by cron (see "man cron")

:smiley:

What he meant was he wants his script to determine if it running via cron so that it can take different actions. For example an interactive script might give a progress report and request permission to proceed to phase 2. An interactive script might just send errors to fd 2 while a cron run script might:
mv /var/log/somescript/errors /var/log/somescript/errors.old
exec 2> /var/log/somescript/errors
or something like that.

now i get it ...

have the script check for $TERM --- if set, the script is most likely running interactively ... if not, the script is most likely running through cron ...

#! /bin/ksh

if [ $TERM ]
then
    echo "I'm running interactively."
else
    echo "I'm running through cron" | mailx -s "cron test" user@domain.com
fi

exit 0
#!/bin/ksh
if [ -t 0 ] ; then
   echo "I am interactive"
else
   echo "I have no controlling terminal - cronned?"
fi;

That was what I said in #3.

... my apologies ... my wrong interpretation of the question didn't help my understanding of what people have posted ... going back through the posts now ... pixelbeat posted similar code but i missed that too ... seems i need new glasses or at least a brain that works ...

Hi,

Am new and got registered only for this one thread......  :confused: 

Well got the same prob. but i need to differentiate if my script was invoked by rc script or by cron.....i used this but prob is that the parent of my perl script is shown as shell (bash) and not cron and that is not what i want.....how do i get around this??????

            $cronpid=\`ps -ef|grep cron| awk '\{if\(NR==1\) print \\$2;\}'\`;
            $parentpid=\`ps -ef | grep action.pl |awk '\{if\(NR == 1\) print \\$3; \}'\`;
            $printst=\`ps -ef| grep action.pl\`;
            print "Output of ps is\\n$printst\\n ";
            print "************Cron pid is $cronpid and parentpid is $parentpid\\n**************";
            $printst1=\`ps -ef | grep $parentpid\`;
            print "My parent is\\n $printst\\n";
            if\($cronpid == $parentpid\)\{
                    print "This process was invoked by cron...it cannot reboot machine";
                    $rebootnow=2;
            \}
             else\{ print "Rebooting.....";
               \}

Output shown is---------------------
Output of ps is
pooja 10890 8350 0 16:43 pts/0 00:00:00 /usr/bin/perl ./action.pl
pooja 10915 10890 0 16:43 pts/0 00:00:00 sh -c ps -ef| grep action.pl

************Cron pid is 7877
and parentpid is 8350

**************My parent is
pooja 10890 8350 0 16:43 pts/0 00:00:00 /usr/bin/perl ./action.pl
pooja 10915 10890 0 16:43 pts/0 00:00:00 sh -c ps -ef| grep action.pl

Nevermind... :rolleyes:
I found out the solution

#!/usr/bin/perl
#Find my parent pid
#CR=`ps -ef | grep -i cron`
$parentpid=`ps -ef | grep "(/remote/idshome/pooja/parentpid.pl 1>/remote/idshome/pooja/OUT 2>/remote/idshome/pooja/ERR)"|awk '{if(NR==1) print \$3;}'`;
@cronpids=`ps -ef | grep -i cron |awk '{print \$2;}'`;
print "My parent pid is\n$parentpid\n";
print "Cron pid is\n@cronpids";
foreach $pid (@cronpids){
if(chomp($pid) eq chomp($parentpid)){
print "I was invoked by cron\n" ;
last;
}
}

i think i have simialr problem
i have scripting running in loop always but not croned.
whe i issue a ps command i dont see the scrip parent i see it
as a .sh only and not by the name of the shell script.
how to find pid from a shell script?