How to suppress stdout / stderr messages or redirect (save) output to a log file (tee) in Linux

Many times when working on a script we execute multiple commands which we do not want to be printed on STDOUT, and only the intended information be printed on the terminal.

Also there are times when our script fails to execute some function or command and throws ugly output to the terminal so it is always a good idea to keep your script and the executed output neat and tidy.

1. Suppress command output for successful scenarios

Suppose we want to restart a service in a script but we donot want anything to be printed on our terminal

By default if I restart a service for eg NTP
# service ntp restart
Shutting down network time protocol daemon (NTPD)                                     
done
Time synchronized with 10.43.18.200
Starting network time protocol daemon (NTPD)                                           done
But lets suppress the output message here
# service ntp restart > /dev/null

# echo $?
0
So our service was restarted successfully.

But what if the service restart failed
# service ntp restart
Time server configuration file, /etc/ntp.conf does not exist.                     skipped
Lets try to suppress this using the same way we did above
# service ntp restart > /dev/null
..skipped
Here you see this works only when we have a successful case but not when the command fails to execute.

2. Suppress command output for failure scenarios (STDERR)

Assuming the case is still as above where my ntp service fails to start
We have to use additional "2>&1" as shown below
# service ntp restart > /dev/null 2>&1
and as you see there is no output on the terminal

You can also use
# service ntp restart >& /dev/null

3. Redirect STDOUT message to a file

If you know your command will be successfully executed then you can use below syntax
# service ntp restart >> /tmp/logfile
So we have no output on our terminal, lets check the content of the logfile
# cat /tmp/logfile
Shutting down network time protocol daemon (NTPD)..done
Time synchronized with 10.43.18.200
Starting network time protocol daemon (NTPD)..done
It worked as expected but what if again the service restart failed?
# service ntp restart >> /tmp/logfile
..skipped
As you see again this is not able to completely append the output to the file
# cat /tmp/logfile
Time server configuration file, /etc/ntp.conf does not exist.
As you see the logile contains partial output of the command execution.

4. Redirect STDOUT and STDERR message to a file

# service ntp restart >> /tmp/logfile 2>&1
So now we don't have any message printed on the terminal and both STDOUT and STDERR message are stored in the logfile
# cat /tmp/logfile
Time server configuration file, /etc/ntp.conf does not exist...skipped
What if you have a script with 1000 lines and you want to store the output of most of your commands in that script, it would look very ugly to append every command with the above syntax.

So lets trim it to make it look better. I have created a small dummy script below with one positive usecase where service starts properly and a negative usecase for ntp service.
So all these must be recorded in our logfile /tmp/logfile

IMPORTANT NOTE:
0 to 9 are file descriptors in bash wherein

0 = STDIN
1 = STDOUT
2 = STDERR
3-9 = Are Free for custom usage hence in below example I am using "5" as my descriptor

# cat /tmp/script.sh
#!/bin/bash

LOGFILE=/tmp/logfile
[[ ! -f $LOGFILE ]] && touch $LOGFILE
exec 5>> $LOGFILE

service nfs restart  >&5 2>&5
echo >&5 2>&5
service ntp restart >&5 2>&5
echo >&5 2>&5
echo "Today's date is: `date`" >&5 2>&5
Lets execute this script
# /tmp/script.sh

# echo $?
0
So our script was executed successfully.
Check the content of our logfile
# cat /tmp/logfile
Shutting down NFS client services: idmapd..done
Starting NFS client services: sm-notify idmapd..done
Time server configuration file, /etc/ntp.conf does not exist...skipped

Today's date is: Sun Nov 19 15:48:34 IST 2017

5. Redirect the output to a file and also print the same on terminal

Here you can use "tee" command where "-a" means append

For eg:
# service ntp restart  2>&1 | tee -a /tmp/logfile
Time server configuration file, /etc/ntp.conf does not exist...skipped
As you see the output of the command was printed on the terminal and similar copy will be available in /tmp/logfile
# cat /tmp/logfile
Time server configuration file, /etc/ntp.conf does not exist.
This can also be used in a script as similar to I used above
# cat /tmp/script.sh
#!/bin/bash

LOGFILE=/tmp/logfile
[[ ! -f $LOGFILE ]] && touch $LOGFILE
exec 5>> $LOGFILE

function test {
service nfs restart
echo
service ntp restart
echo
echo "Today's date is: `date`"
}

test | tee -a $LOGFILE
If I execute this script, the output will be visible on screen also will be stored in our logfile
# /tmp/script.sh
Shutting down NFS client services: idmapd..done
Starting NFS client services: sm-notify idmapd..done

Time server configuration file, /etc/ntp.conf does not exist...skipped

Today's date is: Sun Nov 19 15:56:43 IST 2017
Validate the content with the STDOUT
# cat /tmp/logfile
Shutting down NFS client services: idmapd..done
Starting NFS client services: sm-notify idmapd..done

Time server configuration file, /etc/ntp.conf does not exist.
Today's date is: Sun Nov 19 15:56:43 IST 2017

I hope the article was useful.