Can't use `source` from cron?

12,245

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.

Share:
12,245

Related videos on Youtube

Philip Kirkbride
Author by

Philip Kirkbride

Updated on September 18, 2022

Comments

  • Philip Kirkbride
    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
      jesse_b over 6 years
      What are you doing? Do you have a file in your root directory named source? I'm pretty sure it should just be source and not /source
    • jesse_b
      jesse_b over 6 years
      Also do you know you are creating a file in your root directory named env and not using the actual env command?
    • Philip Kirkbride
      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
      jesse_b over 6 years
      he'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
      terdon over 6 years
      @Jesse_b yes, but that has nothing to do with the command env. The command is being used to find bash in the current $PATH and the file /env has the variables that need to be sourced.
    • Philip Kirkbride
      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
      jesse_b over 6 years
      Understood. 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
      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
      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 of source was a mistake too.
    • terdon
      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
    Philip Kirkbride over 6 years
    I 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
    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
    Philip Kirkbride over 6 years
    sorry I spoke too soon and deleted my comment right after
  • terdon
    terdon over 6 years
    @PhilipKirkbride I know, but I wanted to explain why & will always be wrong here.
  • Philip Kirkbride
    Philip Kirkbride over 6 years
    The 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.htm‌​l The problem is out of the scope of this question, so I will mark as solved and maybe post something on their github.
  • terdon
    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' and export foo='bar'; bash -c 'echo $foo' to see what I mean.