Can't use `source` from cron?
First of all, the command's (well, shell builtin's) name is source
. Unless you have written a script called source
and put it in /
, you want source
and not /source
.
The next issue is that cron
usually uses whatever you have as /bin/sh
and source
is a bashism (or other such more complex shells). The portable, POSIX-compliant command for sourcing a file is .
. So, try that instead of source
:
*/3 * * * * root /usr/bin/env bash & . /env & aws s3 ls >> /test 2>&1
Also, I don't quite understand what that is supposed to be doing. What's the point of starting a bash session and sending it to the background? If you want to use bash to run the subsequent commands, you'd need:
*/3 * * * * root /usr/bin/env bash -c '. /env && aws s3 ls' >> /test 2>&1
I also changed the &
to &&
since sourcing in the background is pointless as far as I can see.
Related videos on Youtube
Philip Kirkbride
Updated on September 18, 2022Comments
-
Philip Kirkbride over 1 year
I'm setting up a docker container which requires a cronjob to do a backup using
awscli
.I'm having a problem with the cron job being able to access the environment variables of the docker container. As I work around on startup I print all environment variables to a file
printenv > /env
.When I try to use
source
from the cron job (I have tried both directly in crontab and in a script called by crontab) it doesn't seem to work.I made a simplified version of my project to demonstrate the issue (including
rsyslog
for logging):Dockerfile:
FROM debian:jessie # Install aws and cron RUN apt-get -yqq update RUN apt-get install -yqq awscli cron rsyslog # Create cron job ADD crontab /etc/cron.d/hello-cron RUN chmod 0644 /etc/cron.d/hello-cron # Output environment variables to file # Then start cron and watch log CMD printenv > /env && cron && service rsyslog start && tail -F /var/log/*
crontab:
# Every 3 minutes try to source /env and run `aws s3 ls`. */3 * * * * root /usr/bin/env bash & source /env & aws s3 ls >> /test 2>&1
When I start the container I can see
/env
was created with my variables but it never gets sourced.-
jesse_b over 6 yearsWhat are you doing? Do you have a file in your root directory named
source
? I'm pretty sure it should just besource
and not/source
-
jesse_b over 6 yearsAlso do you know you are creating a file in your root directory named
env
and not using the actualenv
command? -
Philip Kirkbride over 6 years@Jesse_b Cron doesn't have access to my environment variables so I'm outputting them to a file on startup and sourcing them in the cronjob.
-
jesse_b over 6 yearshe's creating it with this line:
printenv > /env
and if it already exists he's overwriting it. I don't see much of an issue with creating such file but the fact that it is being created in the root directory makes it seem like an oversight. -
terdon over 6 years@Jesse_b yes, but that has nothing to do with the command
env
. The command is being used to findbash
in the current$PATH
and the file/env
has the variables that need to be sourced. -
Philip Kirkbride over 6 years@Jesse_b this is a simplification of my actual project to demonstrate the problem in the shortest possible script. My actual script is longer. Using
/env
saves space. -
jesse_b over 6 yearsUnderstood. In that case it's still seems unnecessary, but also how am I the only person that takes issue with these files being saved in
/
? -
terdon over 6 years@Jesse_b "My actual script is longer. Using /env saves space". The files could be at
/some/random/path/here/env
for all we know, this is just an example. -
jesse_b over 6 years@terdon, I read that...don't see how it changes anything I said though...The way I originally read this script was as if someone was doing this:
cat $file | /grep 'string'
it's not unreasonable to ask if a slash in front of a well known command name is a mistake. Especially since the slash in front ofsource
was a mistake too. -
terdon over 6 years@Jesse_b the file isn't actually stored in
/
so there is no issue to be taken with files being saved in/
, because no files are being saved in/
. Using/env
in the question saves space since it avoids needing to write out a long path. We have no idea where the files actually are and that's not really relevant to the main issue of the question anyway.
-
-
Philip Kirkbride over 6 yearsI tried your original and suggestion and it didn't work. I'm going to re-build with your update and see if that works.
-
terdon over 6 years@PhilipKirkbride if you mean the first one with
root /usr/bin/env bash &
, then that won't work, no. You're just sending a bash instance to the background. If the second one also fails, please explain exactly how it fails since "doesn't work" isn't very informative. -
Philip Kirkbride over 6 yearssorry I spoke too soon and deleted my comment right after
-
terdon over 6 years@PhilipKirkbride I know, but I wanted to explain why
&
will always be wrong here. -
Philip Kirkbride over 6 yearsThe issue is actually that despite my environment variables being set, (I switched the aws command to
echo $AWS_DEFAULT_REGION >> /test
to confirm),awscli
doesn't seem to see them. Though normally it works in the main terminal of Docker and recommends authenticating via environment variables docs.aws.amazon.com/cli/latest/userguide/cli-environment.html The problem is out of the scope of this question, so I will mark as solved and maybe post something on their github. -
terdon over 6 years@PhilipKirkbride they are set, but are they exported? That's a big difference. That you can see the variable when you echo it doesn't mean that child processes inherit it. Compare
foo='bar'; bash -c 'echo $foo'
andexport foo='bar'; bash -c 'echo $foo'
to see what I mean.