views:

93

answers:

2

I have a bash script that performs several file operations. When any user runs this script, it executes successfully and outputs a few lines of text but when I try to cron it there are problems. It seems to run (I see an entry in cron log showing it was kicked off) but nothing happens, it doesn't output anything and doesn't do any of its file operations. It also doesn't appear in the running processes anywhere so it appears to be exiting out immediately.

After some troubleshooting I found that removing "set -e" resolved the issue, it now runs from the system cron without a problem. So it works, but I'd rather have set -e enabled so the script exits if there is an error. Does anyone know why "set -e" is causing my script to exit?

Thanks for the help,
Ryan

+3  A: 

When your script runs under cron, the environment variables and path may be set differently than when the script is run directly by a user. Perhaps that's why it behaves differently?

To test this: create a new script that does nothing but printenv and echo $PATH. Run this script manually, saving the output, then run it as a cron job, saving that output. Compare the two environments. I am sure you will find differences...an interactive login shell will have had its environment set up by sourcing a ".login", ".bash_profile", or similar script (depending on the user's shell). This generally will not happen in a cron job, which is usually the reason for a cron job behaving differently from running the same script in a login shell.

To fix this: At the top of the script, either explicitly set the environment variables and PATH to match the interactive environment, or source the user's ".bash_profile", ".login", or other setup script, depending on which shell they're using.

Jim Lewis
I agree Jim. Except the cron is run as a user that I can kick the script off with manually without a problem. Let's call it user1...If I open an ssh session and login as user1 then run /scripts/myscript.sh it works great but if I add the script as a daily process to user1's cron it never completes a run and no errors are generated. If I remove "set -e" from the top of my script, it then runs fine from cron and there are no errors to stdout or stderr although the standard script output shows up. I'm totally stumped on this...
SDGuero
@SDGuero: I have expanded my explanation of what's probably going on, with some additional troubleshooting advice. Hope this helps.
Jim Lewis
+2  A: 

With set -e, the script will stop at the first command which gives a non-zero exit status. This does not necessarily mean that you will see an error message.

Here is an example, using the false command which does nothing but exit with an error status.

Without set -e:

$ cat test.sh
#!/bin/sh

false
echo Hello

$ ./test.sh
Hello
$

But the same script with set -e exits without printing anything:

$ cat test2.sh
#!/bin/sh

set -e

false
echo Hello

$ ./test2.sh
$ 

Based on your observations, it sounds like your script is failing for some reason (presumably related to the different environment, as Jim Lewis suggested) before it generates any output.

To debug, add set -x to the top of the script (as well as set -e) to show commands as they are executed.

Matthew Slattery