16

I would like to get the following chain of commands as a cronjob:

* * * * * source activate myenv3 && cd ~/foo/bar && python sssb.py

It works in console, but I dont get any output from the cronjob.

I followed this suggestion, by replacing it with

* * * * * env > /tmp/env.output

to find out whether env is different. I couldn't find anything relevant besides PATH being different. So then I set up

PATH=myPath
* * * * * source activate myenv3 && cd ~/foo/bar && python sssb.py

and it still didn't work. Finally I replaced it with

PATH=myPath
* * * * * source activate myenv3 && cd ~/foo/bar && python sssb.py
* * * * * env > /tmp/env.output

and this time I didn't even get the env.output file. Hence I think there's something wrong with my syntax - but it looks exactly like the multi-command suggestions I found online.

What's going on here? If it's not obvious, what can I next to trace out the error?

PATH=/usr/local/anaconda2/envs/myenv3/bin:~/.conda:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games

out.err:

/bin/sh: 6: /usr/local/anaconda2/envs/myenv3/bin/activate: [[: not found
/bin/sh: 15: /usr/local/anaconda2/envs/myenv3/bin/activate: [[: not found
/bin/sh: 17: /usr/local/anaconda2/envs/myenv3/bin/activate: [[: not found
Only bash and zsh are supported
FooBar
  • 643

1 Answers1

25

In Ubuntu, by default, the cron daemon runs all the jobs using sh (dash) shell and dash does not have source builtin.

You need to use the POSIX way i.e. .:

* * * * * . activate myenv3 && cd ~/foo/bar && python sssb.py

Alternately, you can run the job as an argument to bash:

* * * * * "$(command -v bash)" -c 'source activate myenv3 && cd ~/foo/bar && python sssb.py'
heemayl
  • 91,753
  • Now I have a /tmp/env.output file again, but still no output from the main file. – FooBar Mar 31 '16 at 11:36
  • 1
    @FooBar what's the output of grep SHELL /tmp/env.output? Also run the first job as * * * * * ( . activate myenv3 && cd ~/foo/bar && python sssb.py ) >/tmp/out.err 2>&1 and check the contents of /tmp/out.err – heemayl Mar 31 '16 at 11:44
  • It says SHELL=/bin/sh. I'll paste the output of out.err and the actual PATH I pasted into the question. – FooBar Mar 31 '16 at 11:48
  • @FooBar Run the second entry I suggested I.e. the bash one, should work....the problem is you have [[ in the file, dash doesn't support that either.. – heemayl Mar 31 '16 at 12:02
  • That did the trick! – FooBar Mar 31 '16 at 12:38
  • 1
    +1 for your encapsulation using $(command -v bash) -c ' ... ' -- solves the whole tigaboo w/o getting into the (not so) messy details. – Cbhihe Apr 01 '16 at 07:47
  • If working with crontab (not sure about cron), another solution to this is to simply provide the SHELL and PATH variables at the start of the crontab file, as suggested here. Worked for me on Ubuntu 16.04. – n1k31t4 Oct 24 '17 at 11:48
  • @DexterMorgan That would obviously wok but has caveats -- unless you are sure about the values of PATH and SHELL, you should not do it as these would incur portability and security issues. – heemayl Oct 24 '17 at 12:13
  • 3
    The command -v part of "$(command -v bash)" -c '...' is pointless. Just do bash -c '...' – geirha Aug 27 '18 at 08:26
  • I do not understand why I can not use some variables with bash -c syntax. I've tried bash -c "sleep $(($RANDOM%30)) && mycommand.sh" : either $RANDOM variable or $(())syntax are not recognized, without any log trace – Damien C Sep 02 '21 at 12:33