Check if script is started by cron, rather than invoked manually
Clash Royale CLAN TAG#URR8PPP
up vote
19
down vote
favorite
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
add a comment |
up vote
19
down vote
favorite
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
Why don't you just usps
?
– terdon♦
Aug 31 '12 at 9:20
see: serverfault.com/questions/146745/…
– Tim Kennedy
Aug 31 '12 at 11:25
@terdon: probably becauseps
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 toolps
can be.
– cas
Aug 31 '12 at 12:55
add a comment |
up vote
19
down vote
favorite
up vote
19
down vote
favorite
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
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
bash shell scripting cron
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 usps
?
– terdon♦
Aug 31 '12 at 9:20
see: serverfault.com/questions/146745/…
– Tim Kennedy
Aug 31 '12 at 11:25
@terdon: probably becauseps
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 toolps
can be.
– cas
Aug 31 '12 at 12:55
add a comment |
Why don't you just usps
?
– terdon♦
Aug 31 '12 at 9:20
see: serverfault.com/questions/146745/…
– Tim Kennedy
Aug 31 '12 at 11:25
@terdon: probably becauseps
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 toolps
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
add a comment |
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.
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
add a comment |
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...
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 - everybash
i have access to has $-, as dodash
andksh
. even the restricted shells in Solaris have it. What platform are you trying to use it where it's not working? What doescase "$-" in *i*) echo true ;; *) echo false ;; esac
show you?
– Tim Kennedy
May 18 '17 at 15:51
add a comment |
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"
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
add a comment |
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!
add a comment |
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.
add a comment |
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
add a comment |
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...
add a comment |
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=
).
add a comment |
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.
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
add a comment |
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.
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
add a comment |
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.
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.
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
add a comment |
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
add a comment |
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...
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 - everybash
i have access to has $-, as dodash
andksh
. even the restricted shells in Solaris have it. What platform are you trying to use it where it's not working? What doescase "$-" in *i*) echo true ;; *) echo false ;; esac
show you?
– Tim Kennedy
May 18 '17 at 15:51
add a comment |
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...
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 - everybash
i have access to has $-, as dodash
andksh
. even the restricted shells in Solaris have it. What platform are you trying to use it where it's not working? What doescase "$-" in *i*) echo true ;; *) echo false ;; esac
show you?
– Tim Kennedy
May 18 '17 at 15:51
add a comment |
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...
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...
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 - everybash
i have access to has $-, as dodash
andksh
. even the restricted shells in Solaris have it. What platform are you trying to use it where it's not working? What doescase "$-" in *i*) echo true ;; *) echo false ;; esac
show you?
– Tim Kennedy
May 18 '17 at 15:51
add a comment |
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 - everybash
i have access to has $-, as dodash
andksh
. even the restricted shells in Solaris have it. What platform are you trying to use it where it's not working? What doescase "$-" 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
add a comment |
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"
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
add a comment |
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"
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
add a comment |
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"
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"
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
add a comment |
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
add a comment |
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!
add a comment |
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!
add a comment |
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!
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!
edited Sep 9 '14 at 9:54
Tejas
1,79021839
1,79021839
answered Sep 9 '14 at 9:31
Olray
211
211
add a comment |
add a comment |
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.
add a comment |
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.
add a comment |
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.
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.
answered May 29 '13 at 17:05
Ted Rypma
111
111
add a comment |
add a comment |
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
add a comment |
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
add a comment |
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
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
answered Jan 24 at 9:43
Stephen
111
111
add a comment |
add a comment |
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...
add a comment |
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...
add a comment |
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...
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...
edited Dec 15 '17 at 17:08
Stephen Rauch
3,308101328
3,308101328
answered Dec 15 '17 at 16:45
vegivamp
1
1
add a comment |
add a comment |
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=
).
add a comment |
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=
).
add a comment |
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=
).
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=
).
edited Nov 21 at 23:47
answered Nov 21 at 23:33
Adam Katz
2,0931121
2,0931121
add a comment |
add a comment |
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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 toolps
can be.– cas
Aug 31 '12 at 12:55