However, when it is run from the cron, it always outputs SHELL=/bin/sh. Why is this?
This is because cron set SHELL
to /bin/sh
as this is the default program cron uses to run crontab entries. From man 5 crontab
:
Several environment variables are set up automatically by the cron(8) daemon. SHELL is set to /bin/sh...
And as already indicated by the answer of Evgeny Vereshchagin, that variable won't be modified by Bash later if it is already set.
How can I make cron apply the shebang?
Cron is already applying it for your own script, as you can see from the following example.
Let's say you have the following display_process_tree.sh
:
#!/bin/bash
pid=$$
depth=0
while
[ "$pid" -gt 0 ] &&
read -r ppid name < <(ps -o ppid= -o comm= -p "$pid")
do
eval $(echo printf '" %0.s"' {0..$depth})
if [[ -r /proc/$pid/exe ]]; then
echo -n "$name - "
readlink -f /proc/$pid/exe
else
echo $name
fi
pid=$ppid
depth=$((depth+1))
done
And a crontab like this:
* * * * * /path/to/display_process_tree.sh > /tmp/display_process_tree.log
Now, if you wait for the output to arrive to /tmp/display_process_tree.log
, you will find a process tree like the following:
display_process - /bin/bash
sh - /bin/dash
cron
cron
systemd
That shows that cron actually used /bin/sh
(linked to /bin/dash
in my system) to open a new /bin/bash
process for your script.
man 5 crontab
. cron sets environment variables SHELL, LOGNAME, HOME and PATH. – fd0 Jul 15 '15 at 18:45