175

I have a script that works when I run it from the command line, but when I schedule it with cron I get errors that it cannot find files or commands. My question is twofold:

  1. When I schedule a cron job using crontab -e, does it use my user ID as the basis for its permissions? Or does it use a cron user ID of some sort and its related permissions?

  2. When a cron job is launched, what is the working directory? Is it the directory where I specify the script to run, or a different directory?

Here is my cron job:

15 7 * * * /home/xxxx/Documents/Scripts/email_ip_script.sh

Here is the actual script:

vIP_ADDR="`curl automation.whatismyip.com/n09230945.asp`"
echo "$vIP_ADDR"
sed "s/IPADDR/$vIP_ADDR/g" template.txt > emailmsg.txt
ssmtp XXXXX@gmail.com < emailmsg.txt

Here are the errors I get when I view the mail message produced by cron:

sed: can't read template.txt: No such file or directory
/home/xxxx/Documents/Scripts/email_ip_script.sh: line 15: ssmtp: command not found

It cannot find the template.txt but it resides in the same directory as the script. It also cannot run ssmtp, but I can as my user. What am I missing to get this to work properly?

167

Add cd /home/xxxx/Documents/Scripts/ if you want your job to run in that directory. There's no reason why cron would change to that particular directory. Cron runs your commands in your home directory.

As for ssmtp, it might not be in your default PATH. Cron's default path is implementation-dependent, so check your man page, but in all likelihood ssmtp is in /usr/sbin which is not in your default PATH, only root's.

PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin
15 7 * * * cd /home/xxxx/Documents/Scripts && ./email_ip_script.sh
  • @Giles - Thanks, would cron have it's own PATH or can I check my user's PATH? I set ssmtp up to have it's own user and wheel permission thinking it would allow anyone to use it (including cron). If it helps Im on CENTOS 6.2 – ProfessionalAmateur May 18 '12 at 15:51
  • 3
    @ProfessionalAmateur Your problem isn't that you aren't allowed to use ssmtp, but that your cron job doesn't find any executable called ssmtp because it's not in your PATH. There's no such thing as “your user's PATH”; this is a per-process setting, not a per-user setting. You can set the path for all your cron jobs by putting a PATH=… line in your crontab. – Gilles 'SO- stop being evil' May 19 '12 at 8:45
  • I had to add MAILTO='XXXX@gmail.com' as well to get it working along with PATH setup. Wierd but it worked for me. – mac Jun 8 '14 at 9:56
  • For ssmtp one can use; ´which ssmtp´ ... – Fredrick Gauss Nov 9 '17 at 10:40
  • @FredrickGauss Make that type ssmtp – Gilles 'SO- stop being evil' Nov 9 '17 at 21:54
22

If your cronjob is a bash script, the following will CD to the location of your script (assuming that you're using absolute path in your cron definition):

cd "$(dirname "$0")";
15

To answer question 1: if you run crontab -e as your own user the jobs will be scheduled in that user's crontab and will thus run with the permissions of that user.

But you need to consider that the jobs will run in a non-interactive shell meaning that the $PATH might be different from the one you have when running the script from the command line.

It is best to always use full paths in scripts, especially if you plan to schedule them via at/cron etc.

I would also recommend using full paths to all files to avoid exactly the problems you see.

To prevent race conditions and other security issues you should also use mktemp to make sure the file you read is not modified by anything outside your script.

So I'd change the script to something like:

vIP_ADDR="`curl automation.whatismyip.com/n09230945.asp`"
echo "$vIP_ADDR"
mail_msg=`/bin/mktemp`
/bin/sed "s/IPADDR/$vIP_ADDR/g" /home/xxxx/Documents/Scripts/template.txt > $mailmsg
/path/to/ssmtp XXXXX@gmail.com < $mailmsg
/bin/rm $mailmsg
7

cron runs each user's scheduled jobs as that user. This should be enough for us to work out that it runs your scripts relative to your home directory.

If you need it to run from a different location, simply use cd in your script to go to that location.

ssmtp is probably not in cron's default PATH (it is set to be very narrow by design on most platforms). You can either specify the full path to ssmtp in your script, or you can explicitly set PATH in a) your crontab file, which will be available to all your scripts, or b) in each script.

3

Check this thread how you can easily find out cron's environment, it is much less than you are used to in an interactive shell. Best is to assume nothing been set and explicitly set it yourself.

1

The default working directory for cron in executing the job is the home directory, typically /home/your-user-name.

Adopting @Kusalananda excellent comment.

  • 1
    No. It depends on where the system keeps the home directories. /home is far from universal. – Kusalananda Mar 6 '18 at 9:31
  • 1
    @Kusalananda The LSB standard says /home. – peterh says reinstate Monica Mar 6 '18 at 10:25
  • 1
    @peterh Well, macOS uses /Users and historical Unices use /usr, and even on Linux, a system user's home directory may well be somewhere under /var or elsewhere. – Kusalananda Mar 6 '18 at 10:37
  • 1
    @Kusalananda It is right. – peterh says reinstate Monica Mar 6 '18 at 10:38
  • Thanks, you're the only person that actually answered this question :) – OwN May 8 at 21:23
0

Some people have hinted or linked at it but the best way to find out since I can't find it in the man docs for my distro is just add this to a cron

* * * * * echo $PATH > /tmp/lolcronjobs

In my case ubuntu defaults to only using /usr/bin:/bin which caused a few issues.

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.