26

I have a cron job that is running a script. When I run the script via an interactive shell (ssh'ed to bash) it works fine. When the script runs by itself via cron it fails.

My guess is that it is using some of the environmental variables set in the interactive shell. I'm going to troubleshoot the script and remove these.

After I make changes, I know I could queue up the script in cron to have it run as it would normally, but is there a way I can run the script from the command line, but tell it to run as it would from cron - i.e. in a non-interactive environment?

4
  • Related and thus possibly helpful: "How to get a clean environment in a ksh shell?" see especially @Gilles answer regarding unset.
    – sr_
    Commented Nov 3, 2011 at 13:16
  • 1
    From @sr_'s link, I looked up env, and you might want to try env -i ./my-script.sh. Also, are you getting an error message?
    – Kevin
    Commented Nov 3, 2011 at 14:12
  • What cron implementation are you using? Commented Nov 3, 2011 at 17:10
  • @kevin - i'll upvote that if you answer with it.
    – cwd
    Commented Dec 20, 2011 at 22:46

7 Answers 7

20

The main differences between running a command from cron and running on the command line are:

  • cron is probably using a different shell (generally /bin/sh);
  • cron is definitely running in a small environment (which ones depends on the cron implementation, so check the cron(8) or crontab(5) man page; generally there's just HOME, perhaps SHELL, perhaps LOGNAME, perhaps USER, and a small PATH);
  • cron treats the % character specially (it is turned into a newline);
  • cron jobs run without a terminal or graphical environment.

The following invocation will run the shell snippet pretty much as if it was invoked from cron. I assume the snippet doesn't contain the characters ' or %.

env - HOME="$HOME" USER="$USER" PATH=/usr/bin:/bin /bin/sh -c 'shell snippet' </dev/null >job.log 2>&1

See also executing a sh script from the cron, which might help solve your problem.

2
  • Hi @Giles - just thought of something - would running a script like sudo -u user /path/to/script also be a way to run it without any variables set?
    – cwd
    Commented Sep 17, 2012 at 19:57
  • @cwd No, usually not. sudo clears some variables and sets others to a known value, but that depends on how it's configured. It is often configured to retain locale settings and TERM, for example. Commented Sep 17, 2012 at 20:00
4

If you'd like to ignore some interactive questions provided by some script, you can try:

yes | your_command

Or yes "n" if you'd like to No all the questions.

Command:

yes -- be repetitively affirmative yes outputs expletive, or, by default, 'y', forever.

1
  • Never heard of yes til now! This is the only thing I could find that would make calls to gcloud truly non-interactive (if your token expired, it will prompt for reauthentication). Thanks!
    – dwanderson
    Commented Jul 27, 2024 at 18:37
4

To run your script in a non-interactive shell (not regarding the details of cron), you can do this via ssh.

Test if you really end up in a non-interactive shell:

> ssh someuser@somehost tty
not a tty

Execute the script in a non-interactive shell:

> ssh someuser@somehost /tmp/myscript.sh
1
  • 1
    This is the only method that created a non-interactive shell
    – joshlk
    Commented Sep 27, 2021 at 16:00
3

From @sr_'s link (How to get a clean environment in a ksh shell?), I looked up env, and you might want to try this:

env -i ./my-script.sh
2
  • This worked well for me although @Gilles answer is also really good.
    – cwd
    Commented Dec 20, 2011 at 23:29
  • @cwd: Doesn't work for me: echo -e '#!/bin/bash -i\necho interactive $-' > ~/test.sh && chmod +x ~/test.sh && env -i ~/test.sh outputs interactive himB.
    – Alix Axel
    Commented Nov 18, 2012 at 3:14
1

I would suggest you use absolute paths for your scripts when putting it in cron and using elsewhere and for any and all linux commands used in it, better declare them as variables and use it thereof!

1
  • yes. but of course.
    – cwd
    Commented Nov 3, 2011 at 15:44
0

Cron doesn't necessarily use the same shell you are using. check:

cat /etc/crontab |grep SHELL

To determine the shell and attempt execution of your script there - does it work? This is a common cause of issues for many people adding scripts to cron.

If this is the problem - you can add "bash" to the beginning of your script in cron to force this script to execute in bash. If this does not solve the issue, let me know and I'll dig a little deeper.

0

The answers here are useful for simulating other details of cron, but if you're specifically looking to simulate non-interactive execution, in most cases you're looking for setsid.

setsid <command> will run <command> independently, with no associated parent process or terminal, very closely simulating an environment where there was never a parent interactive terminal at all.

It won't isolate the command in many others ways though, so if you want to unset environment variables and so on (as in the other answers here) you'll want to simulate that too.

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.