I have a relatively simple bash script that works great when invoked directly, but fails when run by cron. Why does this fail and how can I make it work via cron?

apt-get update -y
apt-get upgrade -y
apt-get install boinc-client -y

Once cron has attempted to run it, a manual invocation will result in this error:

dpkg was interrupted, you must manually run 'sudo dpkg --configure -a' to correct the problem.

But as long as it is executed the first time manually, it works just fine.


The usual answer to this type of question is that cron jobs are run in non-interactive, non-login shells, so most of your shell startup files (both the systemwide ones in /etc and your personal dotfiles in your home directory) are not sourced (read in and executed), because most shell startup files apply to login shells (the first shell you see when you log into the computer), or interactive shells (shells that are connected to terminals, ssh sessions, or terminal emulators because a user is interacting with them via said terminal).

So if you put a command in a cron job that actually depends on some environment setup (including PATH changes) that usually happens in places like /etc/profile, /etc/bashrc, ~/.profile, or ~/.bashrc, that setup won't happen for a cron job. The cron file format does allow you to specify environment variables for your jobs, so you might want to specify BASH_ENV or ENV to point it at a shell startup script to source. See the "Invocation" section of the bash(1) man page.

  • This environment related suggestion was exactly my problem. When I ran logrotate from the command line, it worked, but when I ran logrotate from the crontab, it didn't. I needed to specify the full path to the executable (ie. /usr/sbin/logrotate), since there was no PATH defined. – Mike Jul 5 '17 at 12:29

This doesn't qualify as an answer, but I can't comment. Suggestions:

  1. prepend the following to your bash script. The last line logged to mail output will be the failing command.

    set -x
    set -e
    • ensure you have sendmail (install a providing package such as postfix or esmtp)
    • install a mail reader (recommend mutt)
    • ensure the mail reaches you
      • via postfix (might be done by installer automatically): add root: my-user-name to /etc/aliases or /etc/postfix/aliases
      • via cron: add MAILTO="my-user-name" to the appropriate crontab file
  2. Verify the script will run in a different environment. Specify full path to apt-get (probably not the culprit since apt-get is known to have been found) and run it in a console (not terminal) outside of X. (some dpkg configure scripts require an X session).

    • modify the script to use absolute paths, ie /usr/bin/apt-get update -y (replace with the correct path)
    • switch to a console by pressing ctrl-alt-f1
    • switch to root user: sudo -i
    • start a non-login shell without an environment: env -i /bin/bash --noprofile --norc (replace with the correct path)
    • run the script: /my/full/path/to/cronscript. Does it work?
  3. Does the script have permission? Are you using the system crontab? (once again, probably not the culprit)

    • You've stated you are using the system crontab, so skipping this.
  4. Does apt-get require session support (consolekit or systemd). This is just a shot in the dark, however.

    • Don't know enough to be of assistance.
  • Sadly these answers are all way over my head. I don't work on linux normally so this is a rare thing for me to be dealing with. I can say that I'm using crontab as root, if that tells you anything. I've no idea how to log anything to anywhere, but wish I did as I suspect it would be useful in troubleshooting. Don't even know what to be searching for in order to go hunting on my own. – JVC Mar 6 '14 at 18:57

Managed to solve it with barely any understanding of what was going on. Turned out that even though I was running from root crontab, the apt-get commands still needed a sudo in front of them. Logically I had expected that not to be needed since the script was already executing "as root", but once I added sudo... everything worked exactly as expected.

  • That's totally unexpected and shouldn't affect anything, but I'm glad you got it to work. How many times did you try it without sudo before you figured this out? – Daniel H Mar 7 '14 at 1:05
  • I spent most of today beating my head against this. The script would run perfectly when instantiated from the command line manually, but would fail at some point when run from cron. Very weird since I was running it from root crontab already, which is why it took me so long to try adding sudo... the classic "it shouldn't need that so I'm not going to bother..." scenario. Finally, out of other ideas, I thought what the hell... and presto, it worked. Go figure! – JVC Mar 7 '14 at 1:51
  • I'd guess that this had something to do with the environment sudo sets vs. the environment cron sets. In any case, since this is what worked, it may help others who come across this page if you accept your own answer. That way, they'll either try that and it will work, or they'll move along more quickly if it's not actually the same problem they're having. – Daniel H Mar 7 '14 at 5:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.