8

I have some commands, they are working under bash, but not as cronjob. To see, what cause the problem, i'm saving the output in a file, here my example:

51  *  *   *   *    source ~/.rvm/scripts/rvm >> stack.log 2>&1

The content of the log file is:

/bin/sh: 1: source: not found

That means, cron is using sh insead of bash. I've tried to change it in the /etc/crontab:

SHELL=/bin/bash

But this doesn't work. I've looked in the /etc/passwd and here i see, that the daemon is using sh as default shell. Both root and pi have bash as default shell.

root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
pi:x:1000:1000:,,,:/home/pi:/bin/bash

What should i do to change the default shell for cron? I wouldn't set /bin/bash for the daemon user in /etc/passwd...imho this is not a good idea.

edit:

ls -l /bin/sh
lrwxrwxrwx 1 root root 4 Mar 30  2012 /bin/sh -> dash

here the content of the /etc/crontab:

# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.

SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

# m h dom mon dow user  command
17 *    * * *   root    cd / && run-parts --report /etc/cron.hourly
25 6    * * *   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6    * * 7   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6    1 * *   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
#
1
  • 1
    Why do you want to source in crons environment? Simply running the ~/.rvm/scripts/rvm doesn't work? And you can have problems with using ~ in non-bash-environments.
    – macrojames
    Oct 10, 2012 at 10:07

4 Answers 4

4

The shell used is dash; a POSIX-compliant shell, which is designed to be much smaller and more stable than bash.

One could argue that you should be writing cron jobs to be POSIX-compliant. Alternatively, try encapsulating your logic into a script and prepending the shebang

#!/usr/bin/env bash
7
  • 2
    why #!/usr/bin/env bash and not #!/bin/bash? what is the difference?
    – cupakob
    Oct 10, 2012 at 8:13
  • 1
    IMHO not a lot. Strictly speaking, it allows bash to be stored elsewhere. Who would do that, I don't know! Oct 10, 2012 at 8:14
  • i've tried this also...i have an wrapper bash script, which call my command, but this also doesn't work. But i'm wandering, why the changes in the /etc/crontab doesn't make the swich to bash.
    – cupakob
    Oct 10, 2012 at 8:18
  • @cupakob Can you paste your entire /etc/crontab please? Oct 10, 2012 at 8:26
  • 1
    I think the problem is source is a builtin, which doesn't make sense to run in its own right. Oct 10, 2012 at 8:34
4

Most such cases (where script works in shell but not in cron) are because of environment variables that are different in script. In many case the problems is PATH variable. You could use full paths to all executables you are running in script or modify PATH in first line of your script.

To trace such issues, you could start from dumping environment variables aviable to your script by using env command, like this: /usr/bin/env >/tmp/env.txt

2
  • i don't have any environment variables in my script...and /bin/env doesn't exists.
    – cupakob
    Oct 10, 2012 at 8:09
  • 2
    No, you always have some enviroment variables in each shell. One example is PATH which was already mentioned. Try /usr/bin/env instead. Or use which env to check what is your full path to env util. Oct 10, 2012 at 8:10
3

Are you sure that sourcing your script into cron is absolutely what you want to do and, more importantly, necessary? I think that it's almost always a bad idea.

Moreover, when you're editing cron (as well as other tools that can be possibly launched by other users and/or other shells), try to take a step-by-step approach. For example, you can test your environment with something like this:

42  *  *   *   *    bash -c "echo home---$HOME---"   >> /tmp/cron-temp.log 2>&1
42  *  *   *   *    bash -c "echo shell---$SHELL---" >> /tmp/cron-temp.log 2>&1

or even:

42  *  *   *   *    bash -c "export"                 >> /tmp/cron-temp.log 2>&1

So you can have proof of your environment, etc.

To answer your question, I wouldn't change the shell for cron. I'd simply tell it to call bash and then let bash call your scripts.

3
  • the $SHELL was still 'sh' notwithstanding i have changed it in the /etc/crontab
    – cupakob
    Oct 10, 2012 at 21:06
  • 1
    Yes, it's also the default in my cron. As I said, I wouldn't change it. Just call your script through bash with bash -c "yourscript" and everything should be fine (don't source your script, you probably don't need it!)
    – Avio
    Oct 10, 2012 at 21:10
  • yes, this will work, but i want to know, why the default shell was not changed.
    – cupakob
    Oct 10, 2012 at 21:30
3

So....i have two solutions for my problem:

  1. Wrapper script over the bash command, which i'm calling at the moment as cronjob. The problem here - for every cronjob i need one wrapper, and this is not the best sollution for me.

  2. I've tried to call a ruby script as cronjob. This doesnt work, so i thought, i need to call 'rvm use 1.9.3' and for that i need first to call 'source ~/.rvm/scripts/rvm'. And here was my mistake. In my bash instance i have path to ruby, but not as cron. After i fixed this, everything is working fine and i can execute my ruby scripts als cronjob.

Alex Chamberlain helped me a lot and give me the most important hint(s). Thanks a lot for the help!!!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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