5

I have several questions related to non-interactive, non-login shells and cron jobs.

Q1. I have read that non-interactive, non-login shells only "load" $BASH_ENV. What does this exactly mean? Does it mean that I can point $BASH_ENV to a file, and that this file will be sourced?

Q2: Assuming that I have an entry in cron pointing to a Bash script with a Bash shebang, what environment variables and definitions can I assume my Bash script is loaded with?

Q3: If I add SHELL=/bin/bash to the top of my crontab, what exactly does this do? Does it mean that:

  1. cron itself runs in Bash?
  2. The commands specified in crontab are interpreted in Bash?
  3. The scripts that do not have shebangs in them, are run under $SHELL

something else?

Q4: How can I set BASH_ENV for cron jobs?

4

For Q1 & Q2, see here. Q3 is answered in the discussion of your other three questions below.

WRT $BASH_ENV, from man bash:

When bash is started non-interactively, to run a shell script, for example, it looks for the variable BASH_ENV in the environment, expands its value if it appears there, and uses the expanded value as the name of a file to read and execute.

So this could be a .profile type script. As to where or who set it, this depends on context -- generally it is not set, but it could have been by any ancestor of the current process. cron does not seem to make any special use of this, and AFAIK neither does init.

Does it mean that cron itself runs in Bash?

If by "in" you mean, is started from a shell, then this depends on the init system -- e.g., SysV executes shell scripts for services, so those services are always started via a shell.

But if by "in" you mean, "Is it thus a child of a shell process?", no. Like other daemons it runs as the leader of its own process group and its parent process is the init process (pid 1).

The consequences for cron's environment are probably immaterial, however. For more about the environment of start-up services, see the answer linked above regarding Q1 & Q2. WRT to cron specifically, according to man 5 crontab it also sets some environment variables that are inherited by any process it starts ($LOGNAME, $HOME, and $SHELL).

The commands specified in crontab are interpreted in Bash?

They're interpreted with sh or $SHELL; again from man 5 crontab:

The entire command portion of the line, up to a newline or a "%" character, will be executed by /bin/sh or by the shell specified in the SHELL variable of the cronfile. A "%" character in the command, unless escaped with a backslash (), will be changed into newline characters, and all data after the first % will be sent to the command as standard input.

The emphasized part anwsers Q3.

The scripts that do not have shebangs in them, are run using $SHELL

Executable scripts with or without shebangs are opened by $SHELL (or sh). The difference is, those with a shebang will then be handed to the appropriate interpreter (#!/bin/sh being another instance of the shell), whereas executable scripts (ones with the executable bit set that are reference as executables) without a shebang will simply fail, just as they would when run from the command line (unless you run them sh script.sh).

  • Thanks! What about BASH_ENV. Is it relevant for cron jobs? Who sets it? and what init file sets it, and what does it contain? Is it an environment variable, or a full environment (multiple variables)? – Amelio Vazquez-Reina May 19 '14 at 13:51
  • 1
    Added a couple of paragraphs about $BASH_ENV at the top. – goldilocks May 19 '14 at 13:56
  • Thanks, although I am still a bit confused. You said "As to where or who set BASH_ENV, this depends on context -- generally it is not set, but it could have been by any ancestor of the current process.", but then you said, "Is it thus a child of a shell process?", no. Like other daemons it runs as the leader of its own process group and its parent process is the init process (pid 1). This seems contradictory, can cron have a parent other than init? If init is the only possible parent, wouldn't BASH_ENV have to be set by init? If so, how exactly can one instruct init to do this? – Amelio Vazquez-Reina May 19 '14 at 14:50
  • 1
    A process that wasn't executed directly by init (e.g., one that was started by a shell script) can still end up with init as its parent via setsid() or being orphaned. In these cases, the process is adopted by the first process, pid 1, i.e., init. This adoption does not modify or add to its environment, so what counts in terms of inheritance is the initial parent. WRT having $BASH_ENV set by init, it could be (but again usually isn't). How depends on the specific init system and service, e.g. with SysV you could set it in the init script. – goldilocks May 20 '14 at 12:09

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.