Check if script is started by cron, rather than invoked manually

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
19
down vote

favorite
8












Is there any variable that cron sets when it runs a program ? If the script is run by cron, I would like to skip some parts; otherwise invoke those parts.



How can I know if the Bash script is started by cron ?










share|improve this question























  • Why don't you just us ps?
    – terdon
    Aug 31 '12 at 9:20










  • see: serverfault.com/questions/146745/…
    – Tim Kennedy
    Aug 31 '12 at 11:25










  • @terdon: probably because ps is fairly badly documented (especially Linux's version which supports several different syntax styles) and the man page is even more dense and cryptic than most tools. I suspect most people don't even realise just how useful and versatile a tool ps can be.
    – cas
    Aug 31 '12 at 12:55















up vote
19
down vote

favorite
8












Is there any variable that cron sets when it runs a program ? If the script is run by cron, I would like to skip some parts; otherwise invoke those parts.



How can I know if the Bash script is started by cron ?










share|improve this question























  • Why don't you just us ps?
    – terdon
    Aug 31 '12 at 9:20










  • see: serverfault.com/questions/146745/…
    – Tim Kennedy
    Aug 31 '12 at 11:25










  • @terdon: probably because ps is fairly badly documented (especially Linux's version which supports several different syntax styles) and the man page is even more dense and cryptic than most tools. I suspect most people don't even realise just how useful and versatile a tool ps can be.
    – cas
    Aug 31 '12 at 12:55













up vote
19
down vote

favorite
8









up vote
19
down vote

favorite
8






8





Is there any variable that cron sets when it runs a program ? If the script is run by cron, I would like to skip some parts; otherwise invoke those parts.



How can I know if the Bash script is started by cron ?










share|improve this question















Is there any variable that cron sets when it runs a program ? If the script is run by cron, I would like to skip some parts; otherwise invoke those parts.



How can I know if the Bash script is started by cron ?







bash shell scripting cron






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Jan 23 '17 at 6:12









codeforester

368314




368314










asked Aug 31 '12 at 9:07









daisy

28.2k48166297




28.2k48166297











  • Why don't you just us ps?
    – terdon
    Aug 31 '12 at 9:20










  • see: serverfault.com/questions/146745/…
    – Tim Kennedy
    Aug 31 '12 at 11:25










  • @terdon: probably because ps is fairly badly documented (especially Linux's version which supports several different syntax styles) and the man page is even more dense and cryptic than most tools. I suspect most people don't even realise just how useful and versatile a tool ps can be.
    – cas
    Aug 31 '12 at 12:55

















  • Why don't you just us ps?
    – terdon
    Aug 31 '12 at 9:20










  • see: serverfault.com/questions/146745/…
    – Tim Kennedy
    Aug 31 '12 at 11:25










  • @terdon: probably because ps is fairly badly documented (especially Linux's version which supports several different syntax styles) and the man page is even more dense and cryptic than most tools. I suspect most people don't even realise just how useful and versatile a tool ps can be.
    – cas
    Aug 31 '12 at 12:55
















Why don't you just us ps?
– terdon
Aug 31 '12 at 9:20




Why don't you just us ps?
– terdon
Aug 31 '12 at 9:20












see: serverfault.com/questions/146745/…
– Tim Kennedy
Aug 31 '12 at 11:25




see: serverfault.com/questions/146745/…
– Tim Kennedy
Aug 31 '12 at 11:25












@terdon: probably because ps is fairly badly documented (especially Linux's version which supports several different syntax styles) and the man page is even more dense and cryptic than most tools. I suspect most people don't even realise just how useful and versatile a tool ps can be.
– cas
Aug 31 '12 at 12:55





@terdon: probably because ps is fairly badly documented (especially Linux's version which supports several different syntax styles) and the man page is even more dense and cryptic than most tools. I suspect most people don't even realise just how useful and versatile a tool ps can be.
– cas
Aug 31 '12 at 12:55











8 Answers
8






active

oldest

votes

















up vote
27
down vote



accepted










I'm not aware that cron does anything to its environment by default that can be of use here, but there are a couple of things you could do to get the desired effect.



1) Make a hard or soft link to the script file, so that, for example, myscript and myscript_via_cron point to the same file. You can then test the value of $0 inside the script when you want to conditionally run or omit certain parts of the code. Put the appropriate name in your crontab, and you're set.



2) Add an option to the script, and set that option in the crontab invocation. For example, add an option -c, which tells the script to run or omit the appropriate parts of the code, and add -c to the command name in your crontab.



And of course, cron can set arbitrary environment variables, so you could just put a line like RUN_BY_CRON="TRUE" in your crontab, and check its value in your script.






share|improve this answer


















  • 4




    +1 for RUN_BY_CRON=true
    – cas
    Aug 31 '12 at 9:50










  • the answer by cas is working very well and can be used for anything else too
    – Deian
    Jun 30 '16 at 15:01

















up vote
18
down vote













Scripts run from cron are not run in interactive shells. Neither are startup scripts. The differentiation is that interactive shells have STDIN and STDOUT attached to a tty.



Method 1: check if $- includes the i flag. i is set for interactive shells.



case "$-" in
*i*)
interactive=1
;;
*)
not_interactive=1
;;
esac


Method 2: check is $PS1 is empty.



if [ -z "$PS1" ]; then
not_interactive=1
else
interactive=1
fi


reference: http://techdoc.kvindesland.no/linux/gnubooks/bash/bashref_54.html



Method 3: test your tty. it's not as reliable, but for simple cron jobs you should be ok, as cron does not by default allocate a tty to a script.



if [ -t 0 ]; then
interactive=1
else
non_interactive=1
fi


Keep in mind that you can however force an interactive shell using -i, but you'd probably be aware if you were doing this...






share|improve this answer


















  • 1




    Note that the $PS1 command does not work when checking if script is started by systemd or not. the $- one does
    – mveroone
    Nov 17 '15 at 10:08






  • 1




    Your Winnipeg University link is broken.
    – WinEunuuchs2Unix
    Dec 31 '16 at 4:07






  • 1




    @TimKennedy You're welcome.... from Edmonton :)
    – WinEunuuchs2Unix
    Jan 6 '17 at 4:20










  • 'case "$-" in' doesn't appear to work in bash scripts.
    – Hobadee
    May 17 '17 at 23:13










  • @Hobadee - every bash i have access to has $-, as do dash and ksh. even the restricted shells in Solaris have it. What platform are you trying to use it where it's not working? What does case "$-" in *i*) echo true ;; *) echo false ;; esac show you?
    – Tim Kennedy
    May 18 '17 at 15:51


















up vote
5
down vote













First, get cron's PID, then get the current process's parent PID (PPID), and compare them:



CRONPID=$(ps ho %p -C cron)
PPID=$(ps ho %P -p $$)
if [ $CRONPID -eq $PPID ] ; then echo Cron is our parent. ; fi


If your script is started by another process that might have been started by cron, then you can walk your way back up the parent PIDs until you get to either $CRONPID or 1 (init's PID).



something like this, maybe (Untested-But-It-Might-Work<TM>):



PPID=$$ # start from current PID
CRON_IS_PARENT=0
CRONPID=$(ps ho %p -C cron)
while [ $CRON_IS_PARENT -ne 1 ] && [ $PPID -ne 1 ] ; do
PPID=$(ps ho %P -p $PPID)
[ $CRONPID -eq $PPID ] && CRON_IS_PARENT=1
done


From Deian:
This is a version tested on RedHat Linux



# start from current PID
MYPID=$$
CRON_IS_PARENT=0
# this might return a list of multiple PIDs
CRONPIDS=$(ps ho %p -C crond)

CPID=$MYPID
while [ $CRON_IS_PARENT -ne 1 ] && [ $CPID -ne 1 ] ; do
CPID_STR=$(ps ho %P -p $CPID)
# the ParentPID came up as a string with leading spaces
# this will convert it to int
CPID=$(($CPID_STR))
# now loop the CRON PIDs and compare them with the CPID
for CRONPID in $CRONPIDS ; do
[ $CRONPID -eq $CPID ] && CRON_IS_PARENT=1
# we could leave earlier but it's okay like that too
done
done

# now do whatever you want with the information
if [ "$CRON_IS_PARENT" == "1" ]; then
CRON_CALL="Y"
else
CRON_CALL="N"
fi

echo "CRON Call: $CRON_CALL"





share|improve this answer






















  • that almost worked - Thank you!
    – Deian
    Jun 30 '16 at 14:50






  • 1




    On Solaris cron starts a shell and the shell runs the script, which itself starts another shell. So the parent pid in the script is not the pid of cron.
    – ceving
    Dec 15 '16 at 17:17

















up vote
2
down vote













If your script file is invoked by cron and it contains a shell in the first line like #!/bin/bash you need to find the parent-parent name for your purpose.



1) cron is invoked at the given time in your crontab, executing a shell
2) shell executes your script
3) your script is running



The parent PID is available in bash as variable $PPID. The ps command to get the parent PID of the parent PID is:



PPPID=`ps h -o ppid= $PPID`


but we need the name of the command, not the pid, so we call



P_COMMAND=`ps h -o %c $PPPID`


now we just need to test the result for "cron"



if [ "$P_COMMAND" == "cron" ]; then
RUNNING_FROM_CRON=1
fi


Now you can test anywhere in your script



if [ "$RUNNING_FROM_CRON" == "1" ]; then
## do something when running from cron
else
## do something when running from shell
fi


Good luck!






share|improve this answer





























    up vote
    1
    down vote













    Works on FreeBSD or on Linux:



    if [ "Z$(ps o comm="" -p $(ps o ppid="" -p $$))" == "Zcron" -o 
    "Z$(ps o comm="" -p $(ps o ppid="" -p $(ps o ppid="" -p $$)))" == "Zcron" ]
    then
    echo "Called from cron"
    else
    echo "Not called from cron"
    fi


    You can go as far up the process tree as you wish.






    share|improve this answer



























      up vote
      1
      down vote













      A generic solution to the question "is my output a terminal or am I running from a script" is:



      ( : > /dev/tty) && dev_tty_good=y || dev_tty_good=n





      share|improve this answer



























        up vote
        0
        down vote













        A simple echo $TERM | mail me@domain.com in cron showed me that on both Linux and AIX, cron seems to set $TERM to 'dumb'.



        Now theoretically there may still be actual dumb terminals around, but I suspect that for most occasions, that should suffice...






        share|improve this answer





























          up vote
          0
          down vote













          There is no authoritative answer, but the prompt ($PS1) and terminal ($TERM) variables are pretty decent here. Some systems set TERM=dumb while most leave it empty, so we'll just check for either:



          if [ "$TERM:-dumb$PS1" != "dumb" ]; then
          echo "This is not a cron job"
          fi


          The above code substitutes the word "dumb" when there is no value for $TERM. Therefore, the conditional fires when there is no $TERM or $TERM is set to "dumb" or if the $PS1 variable is not empty.



          I've tested this on Debian 9 (TERM=), CentOS 6.4 & 7.4 (TERM=dumb), and FreeBSD 7.3 (TERM=).






          share|improve this answer






















            Your Answer








            StackExchange.ready(function()
            var channelOptions =
            tags: "".split(" "),
            id: "106"
            ;
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function()
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled)
            StackExchange.using("snippets", function()
            createEditor();
            );

            else
            createEditor();

            );

            function createEditor()
            StackExchange.prepareEditor(
            heartbeatType: 'answer',
            convertImagesToLinks: false,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: null,
            bindNavPrevention: true,
            postfix: "",
            imageUploader:
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            ,
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            );



            );













             

            draft saved


            draft discarded


















            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f46789%2fcheck-if-script-is-started-by-cron-rather-than-invoked-manually%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown

























            8 Answers
            8






            active

            oldest

            votes








            8 Answers
            8






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes








            up vote
            27
            down vote



            accepted










            I'm not aware that cron does anything to its environment by default that can be of use here, but there are a couple of things you could do to get the desired effect.



            1) Make a hard or soft link to the script file, so that, for example, myscript and myscript_via_cron point to the same file. You can then test the value of $0 inside the script when you want to conditionally run or omit certain parts of the code. Put the appropriate name in your crontab, and you're set.



            2) Add an option to the script, and set that option in the crontab invocation. For example, add an option -c, which tells the script to run or omit the appropriate parts of the code, and add -c to the command name in your crontab.



            And of course, cron can set arbitrary environment variables, so you could just put a line like RUN_BY_CRON="TRUE" in your crontab, and check its value in your script.






            share|improve this answer


















            • 4




              +1 for RUN_BY_CRON=true
              – cas
              Aug 31 '12 at 9:50










            • the answer by cas is working very well and can be used for anything else too
              – Deian
              Jun 30 '16 at 15:01














            up vote
            27
            down vote



            accepted










            I'm not aware that cron does anything to its environment by default that can be of use here, but there are a couple of things you could do to get the desired effect.



            1) Make a hard or soft link to the script file, so that, for example, myscript and myscript_via_cron point to the same file. You can then test the value of $0 inside the script when you want to conditionally run or omit certain parts of the code. Put the appropriate name in your crontab, and you're set.



            2) Add an option to the script, and set that option in the crontab invocation. For example, add an option -c, which tells the script to run or omit the appropriate parts of the code, and add -c to the command name in your crontab.



            And of course, cron can set arbitrary environment variables, so you could just put a line like RUN_BY_CRON="TRUE" in your crontab, and check its value in your script.






            share|improve this answer


















            • 4




              +1 for RUN_BY_CRON=true
              – cas
              Aug 31 '12 at 9:50










            • the answer by cas is working very well and can be used for anything else too
              – Deian
              Jun 30 '16 at 15:01












            up vote
            27
            down vote



            accepted







            up vote
            27
            down vote



            accepted






            I'm not aware that cron does anything to its environment by default that can be of use here, but there are a couple of things you could do to get the desired effect.



            1) Make a hard or soft link to the script file, so that, for example, myscript and myscript_via_cron point to the same file. You can then test the value of $0 inside the script when you want to conditionally run or omit certain parts of the code. Put the appropriate name in your crontab, and you're set.



            2) Add an option to the script, and set that option in the crontab invocation. For example, add an option -c, which tells the script to run or omit the appropriate parts of the code, and add -c to the command name in your crontab.



            And of course, cron can set arbitrary environment variables, so you could just put a line like RUN_BY_CRON="TRUE" in your crontab, and check its value in your script.






            share|improve this answer














            I'm not aware that cron does anything to its environment by default that can be of use here, but there are a couple of things you could do to get the desired effect.



            1) Make a hard or soft link to the script file, so that, for example, myscript and myscript_via_cron point to the same file. You can then test the value of $0 inside the script when you want to conditionally run or omit certain parts of the code. Put the appropriate name in your crontab, and you're set.



            2) Add an option to the script, and set that option in the crontab invocation. For example, add an option -c, which tells the script to run or omit the appropriate parts of the code, and add -c to the command name in your crontab.



            And of course, cron can set arbitrary environment variables, so you could just put a line like RUN_BY_CRON="TRUE" in your crontab, and check its value in your script.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Jul 21 '17 at 16:39









            Stéphane Chazelas

            295k54556898




            295k54556898










            answered Aug 31 '12 at 9:30









            D_Bye

            10.4k13126




            10.4k13126







            • 4




              +1 for RUN_BY_CRON=true
              – cas
              Aug 31 '12 at 9:50










            • the answer by cas is working very well and can be used for anything else too
              – Deian
              Jun 30 '16 at 15:01












            • 4




              +1 for RUN_BY_CRON=true
              – cas
              Aug 31 '12 at 9:50










            • the answer by cas is working very well and can be used for anything else too
              – Deian
              Jun 30 '16 at 15:01







            4




            4




            +1 for RUN_BY_CRON=true
            – cas
            Aug 31 '12 at 9:50




            +1 for RUN_BY_CRON=true
            – cas
            Aug 31 '12 at 9:50












            the answer by cas is working very well and can be used for anything else too
            – Deian
            Jun 30 '16 at 15:01




            the answer by cas is working very well and can be used for anything else too
            – Deian
            Jun 30 '16 at 15:01












            up vote
            18
            down vote













            Scripts run from cron are not run in interactive shells. Neither are startup scripts. The differentiation is that interactive shells have STDIN and STDOUT attached to a tty.



            Method 1: check if $- includes the i flag. i is set for interactive shells.



            case "$-" in
            *i*)
            interactive=1
            ;;
            *)
            not_interactive=1
            ;;
            esac


            Method 2: check is $PS1 is empty.



            if [ -z "$PS1" ]; then
            not_interactive=1
            else
            interactive=1
            fi


            reference: http://techdoc.kvindesland.no/linux/gnubooks/bash/bashref_54.html



            Method 3: test your tty. it's not as reliable, but for simple cron jobs you should be ok, as cron does not by default allocate a tty to a script.



            if [ -t 0 ]; then
            interactive=1
            else
            non_interactive=1
            fi


            Keep in mind that you can however force an interactive shell using -i, but you'd probably be aware if you were doing this...






            share|improve this answer


















            • 1




              Note that the $PS1 command does not work when checking if script is started by systemd or not. the $- one does
              – mveroone
              Nov 17 '15 at 10:08






            • 1




              Your Winnipeg University link is broken.
              – WinEunuuchs2Unix
              Dec 31 '16 at 4:07






            • 1




              @TimKennedy You're welcome.... from Edmonton :)
              – WinEunuuchs2Unix
              Jan 6 '17 at 4:20










            • 'case "$-" in' doesn't appear to work in bash scripts.
              – Hobadee
              May 17 '17 at 23:13










            • @Hobadee - every bash i have access to has $-, as do dash and ksh. even the restricted shells in Solaris have it. What platform are you trying to use it where it's not working? What does case "$-" in *i*) echo true ;; *) echo false ;; esac show you?
              – Tim Kennedy
              May 18 '17 at 15:51















            up vote
            18
            down vote













            Scripts run from cron are not run in interactive shells. Neither are startup scripts. The differentiation is that interactive shells have STDIN and STDOUT attached to a tty.



            Method 1: check if $- includes the i flag. i is set for interactive shells.



            case "$-" in
            *i*)
            interactive=1
            ;;
            *)
            not_interactive=1
            ;;
            esac


            Method 2: check is $PS1 is empty.



            if [ -z "$PS1" ]; then
            not_interactive=1
            else
            interactive=1
            fi


            reference: http://techdoc.kvindesland.no/linux/gnubooks/bash/bashref_54.html



            Method 3: test your tty. it's not as reliable, but for simple cron jobs you should be ok, as cron does not by default allocate a tty to a script.



            if [ -t 0 ]; then
            interactive=1
            else
            non_interactive=1
            fi


            Keep in mind that you can however force an interactive shell using -i, but you'd probably be aware if you were doing this...






            share|improve this answer


















            • 1




              Note that the $PS1 command does not work when checking if script is started by systemd or not. the $- one does
              – mveroone
              Nov 17 '15 at 10:08






            • 1




              Your Winnipeg University link is broken.
              – WinEunuuchs2Unix
              Dec 31 '16 at 4:07






            • 1




              @TimKennedy You're welcome.... from Edmonton :)
              – WinEunuuchs2Unix
              Jan 6 '17 at 4:20










            • 'case "$-" in' doesn't appear to work in bash scripts.
              – Hobadee
              May 17 '17 at 23:13










            • @Hobadee - every bash i have access to has $-, as do dash and ksh. even the restricted shells in Solaris have it. What platform are you trying to use it where it's not working? What does case "$-" in *i*) echo true ;; *) echo false ;; esac show you?
              – Tim Kennedy
              May 18 '17 at 15:51













            up vote
            18
            down vote










            up vote
            18
            down vote









            Scripts run from cron are not run in interactive shells. Neither are startup scripts. The differentiation is that interactive shells have STDIN and STDOUT attached to a tty.



            Method 1: check if $- includes the i flag. i is set for interactive shells.



            case "$-" in
            *i*)
            interactive=1
            ;;
            *)
            not_interactive=1
            ;;
            esac


            Method 2: check is $PS1 is empty.



            if [ -z "$PS1" ]; then
            not_interactive=1
            else
            interactive=1
            fi


            reference: http://techdoc.kvindesland.no/linux/gnubooks/bash/bashref_54.html



            Method 3: test your tty. it's not as reliable, but for simple cron jobs you should be ok, as cron does not by default allocate a tty to a script.



            if [ -t 0 ]; then
            interactive=1
            else
            non_interactive=1
            fi


            Keep in mind that you can however force an interactive shell using -i, but you'd probably be aware if you were doing this...






            share|improve this answer














            Scripts run from cron are not run in interactive shells. Neither are startup scripts. The differentiation is that interactive shells have STDIN and STDOUT attached to a tty.



            Method 1: check if $- includes the i flag. i is set for interactive shells.



            case "$-" in
            *i*)
            interactive=1
            ;;
            *)
            not_interactive=1
            ;;
            esac


            Method 2: check is $PS1 is empty.



            if [ -z "$PS1" ]; then
            not_interactive=1
            else
            interactive=1
            fi


            reference: http://techdoc.kvindesland.no/linux/gnubooks/bash/bashref_54.html



            Method 3: test your tty. it's not as reliable, but for simple cron jobs you should be ok, as cron does not by default allocate a tty to a script.



            if [ -t 0 ]; then
            interactive=1
            else
            non_interactive=1
            fi


            Keep in mind that you can however force an interactive shell using -i, but you'd probably be aware if you were doing this...







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Jan 6 '17 at 4:08

























            answered Aug 31 '12 at 11:50









            Tim Kennedy

            14.1k22950




            14.1k22950







            • 1




              Note that the $PS1 command does not work when checking if script is started by systemd or not. the $- one does
              – mveroone
              Nov 17 '15 at 10:08






            • 1




              Your Winnipeg University link is broken.
              – WinEunuuchs2Unix
              Dec 31 '16 at 4:07






            • 1




              @TimKennedy You're welcome.... from Edmonton :)
              – WinEunuuchs2Unix
              Jan 6 '17 at 4:20










            • 'case "$-" in' doesn't appear to work in bash scripts.
              – Hobadee
              May 17 '17 at 23:13










            • @Hobadee - every bash i have access to has $-, as do dash and ksh. even the restricted shells in Solaris have it. What platform are you trying to use it where it's not working? What does case "$-" in *i*) echo true ;; *) echo false ;; esac show you?
              – Tim Kennedy
              May 18 '17 at 15:51













            • 1




              Note that the $PS1 command does not work when checking if script is started by systemd or not. the $- one does
              – mveroone
              Nov 17 '15 at 10:08






            • 1




              Your Winnipeg University link is broken.
              – WinEunuuchs2Unix
              Dec 31 '16 at 4:07






            • 1




              @TimKennedy You're welcome.... from Edmonton :)
              – WinEunuuchs2Unix
              Jan 6 '17 at 4:20










            • 'case "$-" in' doesn't appear to work in bash scripts.
              – Hobadee
              May 17 '17 at 23:13










            • @Hobadee - every bash i have access to has $-, as do dash and ksh. even the restricted shells in Solaris have it. What platform are you trying to use it where it's not working? What does case "$-" in *i*) echo true ;; *) echo false ;; esac show you?
              – Tim Kennedy
              May 18 '17 at 15:51








            1




            1




            Note that the $PS1 command does not work when checking if script is started by systemd or not. the $- one does
            – mveroone
            Nov 17 '15 at 10:08




            Note that the $PS1 command does not work when checking if script is started by systemd or not. the $- one does
            – mveroone
            Nov 17 '15 at 10:08




            1




            1




            Your Winnipeg University link is broken.
            – WinEunuuchs2Unix
            Dec 31 '16 at 4:07




            Your Winnipeg University link is broken.
            – WinEunuuchs2Unix
            Dec 31 '16 at 4:07




            1




            1




            @TimKennedy You're welcome.... from Edmonton :)
            – WinEunuuchs2Unix
            Jan 6 '17 at 4:20




            @TimKennedy You're welcome.... from Edmonton :)
            – WinEunuuchs2Unix
            Jan 6 '17 at 4:20












            'case "$-" in' doesn't appear to work in bash scripts.
            – Hobadee
            May 17 '17 at 23:13




            'case "$-" in' doesn't appear to work in bash scripts.
            – Hobadee
            May 17 '17 at 23:13












            @Hobadee - every bash i have access to has $-, as do dash and ksh. even the restricted shells in Solaris have it. What platform are you trying to use it where it's not working? What does case "$-" in *i*) echo true ;; *) echo false ;; esac show you?
            – Tim Kennedy
            May 18 '17 at 15:51





            @Hobadee - every bash i have access to has $-, as do dash and ksh. even the restricted shells in Solaris have it. What platform are you trying to use it where it's not working? What does case "$-" in *i*) echo true ;; *) echo false ;; esac show you?
            – Tim Kennedy
            May 18 '17 at 15:51











            up vote
            5
            down vote













            First, get cron's PID, then get the current process's parent PID (PPID), and compare them:



            CRONPID=$(ps ho %p -C cron)
            PPID=$(ps ho %P -p $$)
            if [ $CRONPID -eq $PPID ] ; then echo Cron is our parent. ; fi


            If your script is started by another process that might have been started by cron, then you can walk your way back up the parent PIDs until you get to either $CRONPID or 1 (init's PID).



            something like this, maybe (Untested-But-It-Might-Work<TM>):



            PPID=$$ # start from current PID
            CRON_IS_PARENT=0
            CRONPID=$(ps ho %p -C cron)
            while [ $CRON_IS_PARENT -ne 1 ] && [ $PPID -ne 1 ] ; do
            PPID=$(ps ho %P -p $PPID)
            [ $CRONPID -eq $PPID ] && CRON_IS_PARENT=1
            done


            From Deian:
            This is a version tested on RedHat Linux



            # start from current PID
            MYPID=$$
            CRON_IS_PARENT=0
            # this might return a list of multiple PIDs
            CRONPIDS=$(ps ho %p -C crond)

            CPID=$MYPID
            while [ $CRON_IS_PARENT -ne 1 ] && [ $CPID -ne 1 ] ; do
            CPID_STR=$(ps ho %P -p $CPID)
            # the ParentPID came up as a string with leading spaces
            # this will convert it to int
            CPID=$(($CPID_STR))
            # now loop the CRON PIDs and compare them with the CPID
            for CRONPID in $CRONPIDS ; do
            [ $CRONPID -eq $CPID ] && CRON_IS_PARENT=1
            # we could leave earlier but it's okay like that too
            done
            done

            # now do whatever you want with the information
            if [ "$CRON_IS_PARENT" == "1" ]; then
            CRON_CALL="Y"
            else
            CRON_CALL="N"
            fi

            echo "CRON Call: $CRON_CALL"





            share|improve this answer






















            • that almost worked - Thank you!
              – Deian
              Jun 30 '16 at 14:50






            • 1




              On Solaris cron starts a shell and the shell runs the script, which itself starts another shell. So the parent pid in the script is not the pid of cron.
              – ceving
              Dec 15 '16 at 17:17














            up vote
            5
            down vote













            First, get cron's PID, then get the current process's parent PID (PPID), and compare them:



            CRONPID=$(ps ho %p -C cron)
            PPID=$(ps ho %P -p $$)
            if [ $CRONPID -eq $PPID ] ; then echo Cron is our parent. ; fi


            If your script is started by another process that might have been started by cron, then you can walk your way back up the parent PIDs until you get to either $CRONPID or 1 (init's PID).



            something like this, maybe (Untested-But-It-Might-Work<TM>):



            PPID=$$ # start from current PID
            CRON_IS_PARENT=0
            CRONPID=$(ps ho %p -C cron)
            while [ $CRON_IS_PARENT -ne 1 ] && [ $PPID -ne 1 ] ; do
            PPID=$(ps ho %P -p $PPID)
            [ $CRONPID -eq $PPID ] && CRON_IS_PARENT=1
            done


            From Deian:
            This is a version tested on RedHat Linux



            # start from current PID
            MYPID=$$
            CRON_IS_PARENT=0
            # this might return a list of multiple PIDs
            CRONPIDS=$(ps ho %p -C crond)

            CPID=$MYPID
            while [ $CRON_IS_PARENT -ne 1 ] && [ $CPID -ne 1 ] ; do
            CPID_STR=$(ps ho %P -p $CPID)
            # the ParentPID came up as a string with leading spaces
            # this will convert it to int
            CPID=$(($CPID_STR))
            # now loop the CRON PIDs and compare them with the CPID
            for CRONPID in $CRONPIDS ; do
            [ $CRONPID -eq $CPID ] && CRON_IS_PARENT=1
            # we could leave earlier but it's okay like that too
            done
            done

            # now do whatever you want with the information
            if [ "$CRON_IS_PARENT" == "1" ]; then
            CRON_CALL="Y"
            else
            CRON_CALL="N"
            fi

            echo "CRON Call: $CRON_CALL"





            share|improve this answer






















            • that almost worked - Thank you!
              – Deian
              Jun 30 '16 at 14:50






            • 1




              On Solaris cron starts a shell and the shell runs the script, which itself starts another shell. So the parent pid in the script is not the pid of cron.
              – ceving
              Dec 15 '16 at 17:17












            up vote
            5
            down vote










            up vote
            5
            down vote









            First, get cron's PID, then get the current process's parent PID (PPID), and compare them:



            CRONPID=$(ps ho %p -C cron)
            PPID=$(ps ho %P -p $$)
            if [ $CRONPID -eq $PPID ] ; then echo Cron is our parent. ; fi


            If your script is started by another process that might have been started by cron, then you can walk your way back up the parent PIDs until you get to either $CRONPID or 1 (init's PID).



            something like this, maybe (Untested-But-It-Might-Work<TM>):



            PPID=$$ # start from current PID
            CRON_IS_PARENT=0
            CRONPID=$(ps ho %p -C cron)
            while [ $CRON_IS_PARENT -ne 1 ] && [ $PPID -ne 1 ] ; do
            PPID=$(ps ho %P -p $PPID)
            [ $CRONPID -eq $PPID ] && CRON_IS_PARENT=1
            done


            From Deian:
            This is a version tested on RedHat Linux



            # start from current PID
            MYPID=$$
            CRON_IS_PARENT=0
            # this might return a list of multiple PIDs
            CRONPIDS=$(ps ho %p -C crond)

            CPID=$MYPID
            while [ $CRON_IS_PARENT -ne 1 ] && [ $CPID -ne 1 ] ; do
            CPID_STR=$(ps ho %P -p $CPID)
            # the ParentPID came up as a string with leading spaces
            # this will convert it to int
            CPID=$(($CPID_STR))
            # now loop the CRON PIDs and compare them with the CPID
            for CRONPID in $CRONPIDS ; do
            [ $CRONPID -eq $CPID ] && CRON_IS_PARENT=1
            # we could leave earlier but it's okay like that too
            done
            done

            # now do whatever you want with the information
            if [ "$CRON_IS_PARENT" == "1" ]; then
            CRON_CALL="Y"
            else
            CRON_CALL="N"
            fi

            echo "CRON Call: $CRON_CALL"





            share|improve this answer














            First, get cron's PID, then get the current process's parent PID (PPID), and compare them:



            CRONPID=$(ps ho %p -C cron)
            PPID=$(ps ho %P -p $$)
            if [ $CRONPID -eq $PPID ] ; then echo Cron is our parent. ; fi


            If your script is started by another process that might have been started by cron, then you can walk your way back up the parent PIDs until you get to either $CRONPID or 1 (init's PID).



            something like this, maybe (Untested-But-It-Might-Work<TM>):



            PPID=$$ # start from current PID
            CRON_IS_PARENT=0
            CRONPID=$(ps ho %p -C cron)
            while [ $CRON_IS_PARENT -ne 1 ] && [ $PPID -ne 1 ] ; do
            PPID=$(ps ho %P -p $PPID)
            [ $CRONPID -eq $PPID ] && CRON_IS_PARENT=1
            done


            From Deian:
            This is a version tested on RedHat Linux



            # start from current PID
            MYPID=$$
            CRON_IS_PARENT=0
            # this might return a list of multiple PIDs
            CRONPIDS=$(ps ho %p -C crond)

            CPID=$MYPID
            while [ $CRON_IS_PARENT -ne 1 ] && [ $CPID -ne 1 ] ; do
            CPID_STR=$(ps ho %P -p $CPID)
            # the ParentPID came up as a string with leading spaces
            # this will convert it to int
            CPID=$(($CPID_STR))
            # now loop the CRON PIDs and compare them with the CPID
            for CRONPID in $CRONPIDS ; do
            [ $CRONPID -eq $CPID ] && CRON_IS_PARENT=1
            # we could leave earlier but it's okay like that too
            done
            done

            # now do whatever you want with the information
            if [ "$CRON_IS_PARENT" == "1" ]; then
            CRON_CALL="Y"
            else
            CRON_CALL="N"
            fi

            echo "CRON Call: $CRON_CALL"






            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Jun 30 '16 at 14:59









            Deian

            1033




            1033










            answered Aug 31 '12 at 9:46









            cas

            38.3k44898




            38.3k44898











            • that almost worked - Thank you!
              – Deian
              Jun 30 '16 at 14:50






            • 1




              On Solaris cron starts a shell and the shell runs the script, which itself starts another shell. So the parent pid in the script is not the pid of cron.
              – ceving
              Dec 15 '16 at 17:17
















            • that almost worked - Thank you!
              – Deian
              Jun 30 '16 at 14:50






            • 1




              On Solaris cron starts a shell and the shell runs the script, which itself starts another shell. So the parent pid in the script is not the pid of cron.
              – ceving
              Dec 15 '16 at 17:17















            that almost worked - Thank you!
            – Deian
            Jun 30 '16 at 14:50




            that almost worked - Thank you!
            – Deian
            Jun 30 '16 at 14:50




            1




            1




            On Solaris cron starts a shell and the shell runs the script, which itself starts another shell. So the parent pid in the script is not the pid of cron.
            – ceving
            Dec 15 '16 at 17:17




            On Solaris cron starts a shell and the shell runs the script, which itself starts another shell. So the parent pid in the script is not the pid of cron.
            – ceving
            Dec 15 '16 at 17:17










            up vote
            2
            down vote













            If your script file is invoked by cron and it contains a shell in the first line like #!/bin/bash you need to find the parent-parent name for your purpose.



            1) cron is invoked at the given time in your crontab, executing a shell
            2) shell executes your script
            3) your script is running



            The parent PID is available in bash as variable $PPID. The ps command to get the parent PID of the parent PID is:



            PPPID=`ps h -o ppid= $PPID`


            but we need the name of the command, not the pid, so we call



            P_COMMAND=`ps h -o %c $PPPID`


            now we just need to test the result for "cron"



            if [ "$P_COMMAND" == "cron" ]; then
            RUNNING_FROM_CRON=1
            fi


            Now you can test anywhere in your script



            if [ "$RUNNING_FROM_CRON" == "1" ]; then
            ## do something when running from cron
            else
            ## do something when running from shell
            fi


            Good luck!






            share|improve this answer


























              up vote
              2
              down vote













              If your script file is invoked by cron and it contains a shell in the first line like #!/bin/bash you need to find the parent-parent name for your purpose.



              1) cron is invoked at the given time in your crontab, executing a shell
              2) shell executes your script
              3) your script is running



              The parent PID is available in bash as variable $PPID. The ps command to get the parent PID of the parent PID is:



              PPPID=`ps h -o ppid= $PPID`


              but we need the name of the command, not the pid, so we call



              P_COMMAND=`ps h -o %c $PPPID`


              now we just need to test the result for "cron"



              if [ "$P_COMMAND" == "cron" ]; then
              RUNNING_FROM_CRON=1
              fi


              Now you can test anywhere in your script



              if [ "$RUNNING_FROM_CRON" == "1" ]; then
              ## do something when running from cron
              else
              ## do something when running from shell
              fi


              Good luck!






              share|improve this answer
























                up vote
                2
                down vote










                up vote
                2
                down vote









                If your script file is invoked by cron and it contains a shell in the first line like #!/bin/bash you need to find the parent-parent name for your purpose.



                1) cron is invoked at the given time in your crontab, executing a shell
                2) shell executes your script
                3) your script is running



                The parent PID is available in bash as variable $PPID. The ps command to get the parent PID of the parent PID is:



                PPPID=`ps h -o ppid= $PPID`


                but we need the name of the command, not the pid, so we call



                P_COMMAND=`ps h -o %c $PPPID`


                now we just need to test the result for "cron"



                if [ "$P_COMMAND" == "cron" ]; then
                RUNNING_FROM_CRON=1
                fi


                Now you can test anywhere in your script



                if [ "$RUNNING_FROM_CRON" == "1" ]; then
                ## do something when running from cron
                else
                ## do something when running from shell
                fi


                Good luck!






                share|improve this answer














                If your script file is invoked by cron and it contains a shell in the first line like #!/bin/bash you need to find the parent-parent name for your purpose.



                1) cron is invoked at the given time in your crontab, executing a shell
                2) shell executes your script
                3) your script is running



                The parent PID is available in bash as variable $PPID. The ps command to get the parent PID of the parent PID is:



                PPPID=`ps h -o ppid= $PPID`


                but we need the name of the command, not the pid, so we call



                P_COMMAND=`ps h -o %c $PPPID`


                now we just need to test the result for "cron"



                if [ "$P_COMMAND" == "cron" ]; then
                RUNNING_FROM_CRON=1
                fi


                Now you can test anywhere in your script



                if [ "$RUNNING_FROM_CRON" == "1" ]; then
                ## do something when running from cron
                else
                ## do something when running from shell
                fi


                Good luck!







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Sep 9 '14 at 9:54









                Tejas

                1,79021839




                1,79021839










                answered Sep 9 '14 at 9:31









                Olray

                211




                211




















                    up vote
                    1
                    down vote













                    Works on FreeBSD or on Linux:



                    if [ "Z$(ps o comm="" -p $(ps o ppid="" -p $$))" == "Zcron" -o 
                    "Z$(ps o comm="" -p $(ps o ppid="" -p $(ps o ppid="" -p $$)))" == "Zcron" ]
                    then
                    echo "Called from cron"
                    else
                    echo "Not called from cron"
                    fi


                    You can go as far up the process tree as you wish.






                    share|improve this answer
























                      up vote
                      1
                      down vote













                      Works on FreeBSD or on Linux:



                      if [ "Z$(ps o comm="" -p $(ps o ppid="" -p $$))" == "Zcron" -o 
                      "Z$(ps o comm="" -p $(ps o ppid="" -p $(ps o ppid="" -p $$)))" == "Zcron" ]
                      then
                      echo "Called from cron"
                      else
                      echo "Not called from cron"
                      fi


                      You can go as far up the process tree as you wish.






                      share|improve this answer






















                        up vote
                        1
                        down vote










                        up vote
                        1
                        down vote









                        Works on FreeBSD or on Linux:



                        if [ "Z$(ps o comm="" -p $(ps o ppid="" -p $$))" == "Zcron" -o 
                        "Z$(ps o comm="" -p $(ps o ppid="" -p $(ps o ppid="" -p $$)))" == "Zcron" ]
                        then
                        echo "Called from cron"
                        else
                        echo "Not called from cron"
                        fi


                        You can go as far up the process tree as you wish.






                        share|improve this answer












                        Works on FreeBSD or on Linux:



                        if [ "Z$(ps o comm="" -p $(ps o ppid="" -p $$))" == "Zcron" -o 
                        "Z$(ps o comm="" -p $(ps o ppid="" -p $(ps o ppid="" -p $$)))" == "Zcron" ]
                        then
                        echo "Called from cron"
                        else
                        echo "Not called from cron"
                        fi


                        You can go as far up the process tree as you wish.







                        share|improve this answer












                        share|improve this answer



                        share|improve this answer










                        answered May 29 '13 at 17:05









                        Ted Rypma

                        111




                        111




















                            up vote
                            1
                            down vote













                            A generic solution to the question "is my output a terminal or am I running from a script" is:



                            ( : > /dev/tty) && dev_tty_good=y || dev_tty_good=n





                            share|improve this answer
























                              up vote
                              1
                              down vote













                              A generic solution to the question "is my output a terminal or am I running from a script" is:



                              ( : > /dev/tty) && dev_tty_good=y || dev_tty_good=n





                              share|improve this answer






















                                up vote
                                1
                                down vote










                                up vote
                                1
                                down vote









                                A generic solution to the question "is my output a terminal or am I running from a script" is:



                                ( : > /dev/tty) && dev_tty_good=y || dev_tty_good=n





                                share|improve this answer












                                A generic solution to the question "is my output a terminal or am I running from a script" is:



                                ( : > /dev/tty) && dev_tty_good=y || dev_tty_good=n






                                share|improve this answer












                                share|improve this answer



                                share|improve this answer










                                answered Jan 24 at 9:43









                                Stephen

                                111




                                111




















                                    up vote
                                    0
                                    down vote













                                    A simple echo $TERM | mail me@domain.com in cron showed me that on both Linux and AIX, cron seems to set $TERM to 'dumb'.



                                    Now theoretically there may still be actual dumb terminals around, but I suspect that for most occasions, that should suffice...






                                    share|improve this answer


























                                      up vote
                                      0
                                      down vote













                                      A simple echo $TERM | mail me@domain.com in cron showed me that on both Linux and AIX, cron seems to set $TERM to 'dumb'.



                                      Now theoretically there may still be actual dumb terminals around, but I suspect that for most occasions, that should suffice...






                                      share|improve this answer
























                                        up vote
                                        0
                                        down vote










                                        up vote
                                        0
                                        down vote









                                        A simple echo $TERM | mail me@domain.com in cron showed me that on both Linux and AIX, cron seems to set $TERM to 'dumb'.



                                        Now theoretically there may still be actual dumb terminals around, but I suspect that for most occasions, that should suffice...






                                        share|improve this answer














                                        A simple echo $TERM | mail me@domain.com in cron showed me that on both Linux and AIX, cron seems to set $TERM to 'dumb'.



                                        Now theoretically there may still be actual dumb terminals around, but I suspect that for most occasions, that should suffice...







                                        share|improve this answer














                                        share|improve this answer



                                        share|improve this answer








                                        edited Dec 15 '17 at 17:08









                                        Stephen Rauch

                                        3,308101328




                                        3,308101328










                                        answered Dec 15 '17 at 16:45









                                        vegivamp

                                        1




                                        1




















                                            up vote
                                            0
                                            down vote













                                            There is no authoritative answer, but the prompt ($PS1) and terminal ($TERM) variables are pretty decent here. Some systems set TERM=dumb while most leave it empty, so we'll just check for either:



                                            if [ "$TERM:-dumb$PS1" != "dumb" ]; then
                                            echo "This is not a cron job"
                                            fi


                                            The above code substitutes the word "dumb" when there is no value for $TERM. Therefore, the conditional fires when there is no $TERM or $TERM is set to "dumb" or if the $PS1 variable is not empty.



                                            I've tested this on Debian 9 (TERM=), CentOS 6.4 & 7.4 (TERM=dumb), and FreeBSD 7.3 (TERM=).






                                            share|improve this answer


























                                              up vote
                                              0
                                              down vote













                                              There is no authoritative answer, but the prompt ($PS1) and terminal ($TERM) variables are pretty decent here. Some systems set TERM=dumb while most leave it empty, so we'll just check for either:



                                              if [ "$TERM:-dumb$PS1" != "dumb" ]; then
                                              echo "This is not a cron job"
                                              fi


                                              The above code substitutes the word "dumb" when there is no value for $TERM. Therefore, the conditional fires when there is no $TERM or $TERM is set to "dumb" or if the $PS1 variable is not empty.



                                              I've tested this on Debian 9 (TERM=), CentOS 6.4 & 7.4 (TERM=dumb), and FreeBSD 7.3 (TERM=).






                                              share|improve this answer
























                                                up vote
                                                0
                                                down vote










                                                up vote
                                                0
                                                down vote









                                                There is no authoritative answer, but the prompt ($PS1) and terminal ($TERM) variables are pretty decent here. Some systems set TERM=dumb while most leave it empty, so we'll just check for either:



                                                if [ "$TERM:-dumb$PS1" != "dumb" ]; then
                                                echo "This is not a cron job"
                                                fi


                                                The above code substitutes the word "dumb" when there is no value for $TERM. Therefore, the conditional fires when there is no $TERM or $TERM is set to "dumb" or if the $PS1 variable is not empty.



                                                I've tested this on Debian 9 (TERM=), CentOS 6.4 & 7.4 (TERM=dumb), and FreeBSD 7.3 (TERM=).






                                                share|improve this answer














                                                There is no authoritative answer, but the prompt ($PS1) and terminal ($TERM) variables are pretty decent here. Some systems set TERM=dumb while most leave it empty, so we'll just check for either:



                                                if [ "$TERM:-dumb$PS1" != "dumb" ]; then
                                                echo "This is not a cron job"
                                                fi


                                                The above code substitutes the word "dumb" when there is no value for $TERM. Therefore, the conditional fires when there is no $TERM or $TERM is set to "dumb" or if the $PS1 variable is not empty.



                                                I've tested this on Debian 9 (TERM=), CentOS 6.4 & 7.4 (TERM=dumb), and FreeBSD 7.3 (TERM=).







                                                share|improve this answer














                                                share|improve this answer



                                                share|improve this answer








                                                edited Nov 21 at 23:47

























                                                answered Nov 21 at 23:33









                                                Adam Katz

                                                2,0931121




                                                2,0931121



























                                                     

                                                    draft saved


                                                    draft discarded















































                                                     


                                                    draft saved


                                                    draft discarded














                                                    StackExchange.ready(
                                                    function ()
                                                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f46789%2fcheck-if-script-is-started-by-cron-rather-than-invoked-manually%23new-answer', 'question_page');

                                                    );

                                                    Post as a guest















                                                    Required, but never shown





















































                                                    Required, but never shown














                                                    Required, but never shown












                                                    Required, but never shown







                                                    Required, but never shown

































                                                    Required, but never shown














                                                    Required, but never shown












                                                    Required, but never shown







                                                    Required, but never shown






                                                    Popular posts from this blog

                                                    How to check contact read email or not when send email to Individual?

                                                    Bahrain

                                                    Postfix configuration issue with fips on centos 7; mailgun relay