Everyone knows how to use redirection operators to send output of a script to a file. Simply use “>” or “>>” on command prompt after the script or application name and it does the magic of storing the output of the script to the file of choice. But what if one wants that their script shall create its own file and store the output there. In other words, self redirect of output.
Lets take a use case. Imagine you are developing a script that will bring up some applications when a system reboots. When it is run from command line it works fine but when it is run during system startup, it misbehaves. How do you troubleshoot? First response is to use “-x” to print how the script is triggering. But what we want is that when our startup script runs, all of its output (both stdout and stderr) stored in a file that we could use for troubleshooting later. For redirecting output of a startup script we have to use a wrapper script to trigger it and use redirection operator to store its output which is simply a workaround. Or, use the magic word “exec“.
Using “exec 1>stdout.log 2>stderr.log” does the magic. Here stdout.log and stderr.log are example filenames that can be changed to one’s liking. I prefer redirecting all output to only one file. Do not use the same filename with both 1 and 2, output will jumble up depending on how shell is buffering and flushing the data to the file. Use this variant instead “exec 1>stdout.log 2>&1“. This will guarantee that all the output will be stored in the order it was produced.
Now lets go back to a working example to fix our init.d OR rc.d problem. Following is a sample script. Because /tmp/passwd does not exist (usually), the ls command shall fail sending output to stderr. Execution of each line as displayed by “-x” would also go to stderr (try using “exec >mylog.log 2>myerr.log” and see its behavior).
#!/bin/bash -x # Redirect all stdout and stderr to mytest.log exec > mytest.log 2>&1 date echo "Hello world" ls -lart /tmp/passwd echo "What's up?"
When run it will output following.
unixite@sandbox:~/> ./mytest.sh + exec unixite@sandbox:~/> cat mytest.log + echo 'Hello world' Hello world + ls -lart /tmp/passwd ls: cannot access /tmp/passwd: No such file or directory + echo 'What'''s up?' What's up? unixite@sandbox:~/>
Per manpage of bash (from the Redirection section)
Note that the exec builtin command can make redirections take effect in the current shell.