9

I write a lot of non-interactive scripts where I would like all output to go to a log file and have nothing appear on-screen.

To solve this, I've been using:

#!/bin/bash

exec &> logfile
echo "Step One:"
/some/command/one
echo "Step Two:"
/some/command/two

I want to make sure this is a sane method.

Are there any significant drawbacks or issues I'm going to encounter if I move forward with this methodology? If so, what are they and how best can they be mitigated (including by changing my methodology).

1
  • 1
    What you wrote is a common programming pattern. Only - even though you target it specifically for bash - I'd use the portable syntax for &> . The little typing overhead should be tolerable since you need that code only in one place.
    – Janis
    Feb 11, 2015 at 0:58

1 Answer 1

14

Redirection of command output to a log file

Redirecting all command output (including error messages) to a log file is standard practice for non-interactive shell scripts.   It’s particularly useful to have a record of command output for scripts that are run by cron or triggered by some other external event, and there are no downsides in such use-cases.

Many of my shell scripts include the following lines near the start:

exec 1>>"$logfile"
exec 2>&1

The order that these redirection commands is important. The first exec command redirects all writes to the stdout (1) stream to append (>>) to the log file. The second command redirects all writes to the stderr (2) stream to the same file descriptor that stdout (1) currently points to. Using only one file descriptor for accessing a file ensures that the writes happen in the desired order.

If using Bash, you can combine these commands into a single construct that does the same thing:

exec &>>"$logfile"

If you want the log file to be cleared of previous entries each time the script is run, use only a single > redirection operator (over-writes the previous contents):

exec &>"$logfile"

Use of the exec builtin for input/output redirection is specified by the POSIX definition for the Shell Command Language, and the exec builtin is available in any POSIX compatible shell.

Redirection while running an interactive shell

You can experiment with redirecting standard output to a file while in a temporary/disposable interactive shell session. After running exec 1>outfile, all future commands print their output to outfile instead of to the terminal.

You can also experiment with redirecting standard error in an interactive shell session, but it can make the interactive shell session very hard to work with.

After running exec 2>errorfile, the standard error produced by any further commands is written to the redirected error file – as expected. However, the problem is that from now on, the shell (Bash in this case) prints its prompt to this file and any text typed as a command is also redirected to this file.  Some shells (such as Bash) also echo characters received by stdin to stderr.  In others, such as dash, for the rest of the shell session, you’re essentially working blind, as nothing at all is sent to the terminal.  This obviously makes it very difficult to continue interacting with the shell.

As Orion points out and Scott says, you can store references to the default stdout and stderr file descriptors before trying any such experiments using exec 3>&1 and exec 4>&2 respectively.  When you’ve finished your experiments, you can restore printing to standard error by running exec 2>&4 and restore printing to standard output with exec 1>&3.

For interactive use, I’d advise redirecting standard out and standard error streams on a command-by-command basis: >> outfile 2>&1 command with arguments.

3
  • 2
    If you are afraid of "dropping" the file descriptors, you can always save them. Use 3>&1, 4>&2 and then you can always go 1>&3, 2>&4 when you want them back.
    – orion
    Feb 11, 2015 at 10:45
  • Anthony, can you elaborate more on how you might lose your shell session?
    – Rob
    Feb 11, 2015 at 21:47
  • 2
    I've updated my answer to explain how redirecting stderr makes it very difficult to continue interacting with the shell. I've also incorporated the tip for storing file descriptors (thanks, @orion). Feb 12, 2015 at 9:52

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .