In crontab, how do I know which shell it is using?

for example if I want to redirect output how do I know if I need to use &> or >& (bash vs csh)

  • 2
    Possible duplicate of How to change cron shell (sh to bash)?
    – vfbsilva
    Mar 14 '17 at 14:28
  • 1
    Incidentally, bash supports >&, so if this is the only difference you're worried about just use that form. It also has the advantage that it's a clear error in shells that do not support it, whereas &> may simply start the process in the background with no redirection and create a blank file.
    – Random832
    Mar 14 '17 at 15:28
  • 4
    In general, you can assume that all those system utilities use a POSIX sh, and that you cannot assume any features that are not specified in POSIX. Mar 14 '17 at 15:51

From crontab(5):

Several environment variables are set up automatically by the cron(8) daemon. SHELL is set to /bin/sh, and LOGNAME and HOME are set from the /etc/passwd line of the crontab´s owner. HOME and SHELL can be overridden by settings in the crontab; LOGNAME can not.

  • I wonder if there are cron daemons that don't allow setting environment variables in crontab..
    – ilkkachu
    Mar 14 '17 at 16:36

It depends what version of cron you have, and how it is configured, but usually it is /bin/sh. Often that is a symlink to something else though, but that is easy to find as you can simply run ls -l /bin/sh.

You could add a cron entry like:

* *    * * *    ps -p $$ > /tmp/shelltest

or (if editing /etc/crontab instead of adding an entry to a per-user crontab as done via crontab -e):

* *    * * *    username    ps -p $$ > /tmp/shelltest

which will tell you via output to /tmp/shelltest the filename of the shell. If your cron is properly setup to mail output to you then you can skip the >/tmp/shelltest to get the information by mail instead of it being dropped into a file.

To be a bit more trixy something like:

* *    * * *    ls -l /proc/`ps -p $$ | tail -n 1 | xargs | cut -f 1 -d \ `/exe > /tmp/shelltest

should tell you the exact file used. On a typical Debian system this will result in something like:

lrwxrwxrwx 1 dspillett dspillett 0 Mar 14 16:17 /proc/1356/exe -> /bin/dash

showing that cron is using dash as the default shell in this instance.

To break that command down:

  • ps -p $$ outputs details of the current process (well, ps's parent process) which will be the shell in this case.
  • tail -n 1 strips away the header row that ps includes
  • piping through xargs is a trick to trim off leading spaces from the line
  • the cut invocation takes the first field from the like where the deliter is spaces (it is absolutely vital that you include the space between the \ and the backtick)
  • wrapping that in backticks includes the output (which should be a process ID) in the outer command line which becomes...
  • ls -l /proc/9999/exe where "9999" is the process ID read from ps which lists the file used to create the process because in the '/proc' filesystem /proc/<pid>/exe is a link to the executable of the process identified by <pid>.
  • (there may be a more concise way to do the same thing, that was typed from memory, suggestions welcome via comments!)
  • ps -p $$ --no-headers -o '%P' shows the parent ID of the process whose value is in $$ Mar 16 '17 at 23:19

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.