0

I have a bash script set to copy a backup from a remote drive; and this script works fine if I run it from the terminal, i.e., $ ./getBackup; however, if I try to put it in my crontab, it doesn't work.

I've read through a bunch of questions/answers here, including

Maybe I missed something, but I think I've tried most of the suggestions offered in those, and just about everything else I could think of. I've tried to run it from my crontab, from the sudo crontab, from /etc/crontab; I've checked the env of the terminal (where the script manually works) and put that into the script for the cron job.

Any one have any ideas?

[edit to add] Several commenters asked for the code in question, so:

crontab:

30 9 * * * /home/opsmonitor/Documents/getBackup

getBackup

cd /home/opsmonitor/Documents/
OF=backup-$(date +%Y%m%d)
echo "Retrieving backup file $OF"
scp root@IP ADDRESS HERE://opt/backups/backupsbydate/$OF.tgz $OF.tgz

As I said, getBackup works fine from the command line; and run from the crontab, it doesn't do anything. (Now that I redirected the output to a file, the echo does print to that file.)

Since scp runs from the command line, I thought it was an env issue, but as I said, I added a lot of the env variables to the script--and it still runs fine from the command line and fails from the crontab.

Community
  • 1
  • 1
samedietc
  • 11
  • 2
  • 2
    Add your `cron` entry to the question. – heemayl May 04 '15 at 23:04
  • The contents of the `getBackup` script might be useful too. Have you added explicit error logging (to a file) to the script to attempt to see what is happening when cron runs it? – Etan Reisner May 04 '15 at 23:17
  • Even if OP made the environment variables right, there is the possibility that the script tries to do something with /dev/tty ... – Thomas Dickey May 04 '15 at 23:18
  • 1
    Cron typically runs jobs a) with a limited PATH, b) not as a login shell, c) do not source ~/.bashrc or ~/.cshrc, and d) with a PWD of $HOME. Therefore, a) make sure your PATH is correctly set, b) use full paths (not "./getBackup", and c) all other required environmental variables are correct. – RTLinuxSW May 04 '15 at 23:31
  • Since you've not shown us the script, it is going to be hard to diagnose what's going wrong. Have you run the script with `bash -x /path/to/getBackup >/tmp/getBackup 2>&1` in the crontab entry so that you get a record of what `bash` thinks is going on? Have you recorded the actual environment (current directory and environment variables are the crucial ones) when the job is run by `cron`? If not, you should do so. There's a very good chance that one of those explains the trouble. – Jonathan Leffler May 04 '15 at 23:42
  • Thanks for the comments. I added the cron and the getBackup bash script. (Or at least one version; I had another version where I set the path explicitly to include the home/opsmonitor/Documents directory). – samedietc May 06 '15 at 13:26
  • I also tried redirecting the output to a file to see what was happening, as recommended here and elsewhere: the echo was coming through loud and clear, but I wasn't getting any other response. No errors. – samedietc May 06 '15 at 13:29
  • I also recorded the env to a file when a script was run in the terminal vs. when a script was run by the cron. I attempted to explicitly set what looked like the important env variables, but no luck. – samedietc May 06 '15 at 13:29

1 Answers1

1

I test the environment aspect by running my program within a script that prunes out extra environment variables. Here is an example (noting that it actually leaves PATH alone — not precisely what you want):

#!/bin/sh
# $Id: noenv,v 1.3 2014/05/10 22:43:32 tom Exp $
# trim the environment to minimal (PATH may still be long...)
env | sed -e 's/=.*//' -e '/^[  ].*/d' | \
while true
do
    read value
    if test -z "$value" ; then
            # honor assignments to variables in the parameter list
            while test $# != 0
            do
                    case "x$1" in
                    *=*)
                            eval $1
                            name=`echo "$1"|sed -e 's/=.*//'`
                            export $name
                            shift 1
                            ;;
                    *)
                            break
                            ;;
                    esac
            done
            exec "$@"
            break
    fi
    case "$value" in
    HOME|PATH|USER|_|SHLVL|TMPDIR|LOGNAME)
            ;;
    *\ *|*\(*|*\)*|*\!*)
            #echo "...skipping $value"
            ;;
    *)
            #echo value:"$value"
            unset "$value"
            ;;
    esac
done

and calling that noenv, would do

noenv ./getBackup

However, if your program still works properly from the command-line, I would suspect that it attempts to use /dev/tty, etc., and fails if no terminal is found for that. It is the less frequent problem with cron, but noted e.g., in Linux: Difference between /dev/console , /dev/tty and /dev/tty0.

Community
  • 1
  • 1
Thomas Dickey
  • 51,086
  • 7
  • 70
  • 105