BASH Shell Redirect stderr To stdout ( redirect stderr to a File )

How do I redirect stderr to stdout under bash? How do I redirect stderr to a file when using bash?

This page explains bash I/O redirection that you can use for redirect stderr and stdout to a file at the shell prompt or in your shell scripts. Bash and other modern Linux/Unix shell provide an I/O redirection facility. There are three default standard files (standard streams) open per process:

ADVERTISEMENTS

  • stdin – Get input from keyboard or program. In other words data going into a program.
  • stdout – Write information on screen or file.
  • stderr – Show error message on screen or file
Tutorial requirements
Operating system/appUnix or Linux with bash
Root privileges requiredNo
DifficultyEasy (rss)
Estimated completion time10m
Table of contents

Understanding I/O streams numbers

The Unix / Linux standard I/O streams with numbers:

HandleNameDescription
0 stdin Standard input
1 stdout Standard output
2 stderr Standard error

Redirecting output

Say you want to save output of the date command to a file. Try:
$ command > output.txt
$ date > today.txt

Use the cat command to view contain of today.txt file, run:
$ cat today.txt
How to redirect stderr To stdout in Bash
In above example, a file called ‘today.txt’ will be created and it will contain date (what you would see on the screen) if you type the command ‘date’ and execute it. Please note that above command also creates the file today.txty if not present, otherwise overwrites it. If you wish to add/append try the following syntax:
$ command1 >> filename
$ command2 >> filename
$ ls -l >> output.txt
$ date >> output.txt

In short we can redirect stdout to a file simply using the > or >> symbol.

Redirecting the standard error stream to a file

The following will redirect program error message to a file called error.log:
$ program-name 2> error.log
$ command1 2> error.log

For example, use the grep command for recursive search in the $HOME directory and redirect all errors (stderr) to a file name grep-errors.txt as follows:
$ grep -R 'MASTER' $HOME 2> /tmp/grep-errors.txt
$ cat /tmp/grep-errors.txt

Sample outputs:

grep: /home/vivek/.config/google-chrome/SingletonSocket: No such device or address
grep: /home/vivek/.config/google-chrome/SingletonCookie: No such file or directory
grep: /home/vivek/.config/google-chrome/SingletonLock: No such file or directory
grep: /home/vivek/.byobu/.ssh-agent: No such device or address

Redirecting the standard error (stderr) and stdout to file

Use the following syntax:
$ command-name &>file
We can als use the following syntax:
$ command > file-name 2>&1
We can write both stderr and stdout to two different files too. Let us try out our previous grep command example:
$ grep -R 'MASTER' $HOME 2> /tmp/grep-errors.txt 1> /tmp/grep-outputs.txt
$ cat /tmp/grep-outputs.txt

Redirecting stderr to stdout to a file or another command

Here is another useful example where both stderr and stdout sent to the more command instead of a file:
# find /usr/home -name .profile 2>&1 | more

Redirect stderr to stdout

Use the command as follows:
$ command-name 2>&1
$ command-name > file.txt 2>&1
## bash only ##
$ command2 &> filename
$ sudo find / -type f -iname ".env" &> /tmp/search.txt

Redirection takes from left to right. Hence, order matters. For example:
command-name 2>&1 > file.txt ## wrong ##
command-name > file.txt 2>&1 ## correct ##

How to redirect stderr to stdout in Bash script

A sample shell script used to update VM when created in the AWS/Linode server:

#!/usr/bin/env bash
# Author - nixCraft under GPL v2.x+
# Debian/Ubuntu Linux script for EC2 automation on first boot
# ------------------------------------------------------------
# My log file - Save stdout to $LOGFILE
LOGFILE="/root/logs.txt"
 
# My error file - Save stderr to $ERRFILE
ERRFILE="/root/errors.txt"
 
# Start it 
printf "Starting update process ... \n" 1>"${LOGFILE}"
 
# All errors should go to error file 
apt-get -y update 2>"${ERRFILE}"
apt-get -y upgrade 2>>"${ERRFILE}"
printf "Rebooting cloudserver ... \n" 1>>"${LOGFILE}"
shutdown -r now 2>>"${ERRFILE}"

Our last example uses the exec command and FDs along with trap and custom bash functions:

#!/bin/bash
# Send both stdout/stderr to a /root/aws-ec2-debian.log file
# Works with Ubuntu Linux too.
# Use exec for FD and trap it using the trap
# See bash man page for more info
# Author:  nixCraft under GPL v2.x+
# ---------------------------------------------
exec 3>&1 4>&2
trap 'exec 2>&4 1>&3' 0 1 2 3
exec 1>/root/aws-ec2-debian.log 2>&1
 
# log message
log(){
	local m="$@"
	echo ""
	echo "*** ${m} ***"
	echo ""
}
 
log "$(date) @ $(hostname)"
## Install stuff ##
log "Updating up all packages"
export DEBIAN_FRONTEND=noninteractive
apt-get -y clean
apt-get -y update
apt-get -y upgrade
apt-get -y --purge autoremove
 
## Update sshd config ##
log "Configuring sshd_config"
sed -i'.BAK' -e 's/PermitRootLogin yes/PermitRootLogin no/g' -e 's/#PasswordAuthentication yes/PasswordAuthentication no/g'  /etc/ssh/sshd_config
 
## Hide process from other users ##
log "Update /proc/fstab to hide process from each other"
echo 'proc    /proc    proc    defaults,nosuid,nodev,noexec,relatime,hidepid=2     0     0' >> /etc/fstab
 
## Install LXD and stuff ##
log "Installing LXD/wireguard/vnstat and other packages on this box"
apt-get -y install lxd wireguard vnstat expect mariadb-server 
 
log "Configuring mysql with mysql_secure_installation"
SECURE_MYSQL_EXEC=$(expect -c "
set timeout 10
spawn mysql_secure_installation
expect \"Enter current password for root (enter for none):\"
send \"$MYSQL\r\"
expect \"Change the root password?\"
send \"n\r\"
expect \"Remove anonymous users?\"
send \"y\r\"
expect \"Disallow root login remotely?\"
send \"y\r\"
expect \"Remove test database and access to it?\"
send \"y\r\"
expect \"Reload privilege tables now?\"
send \"y\r\"
expect eof
")
 
# log to file #
echo "   $SECURE_MYSQL_EXEC   "
# We no longer need expect 
apt-get -y remove expect
 
# Reboot the EC2 VM
log "END: Rebooting requested @ $(date) by $(hostname)"
reboot

Want both stderr and stdout to the terminal and a log file too?

Try the tee command as follows:
command1 2>&1 | tee filename
Here is how to use it insider shell script too:

#!/usr/bin/env bash
{
   command1
   command2 | do_something
} 2>&1 | tee /tmp/outputs.log

Conclusion

In this quick tutorial, you learned about three file descriptors, stdin, stdout, and stderr. We can use these Bash descriptors to redirect stdout/stderr to a file or vice versa. See bash man page here:

OperatorDescriptionExamples
command>filenameRedirect stdout to file “filename.”date > output.txt
command>>filenameRedirect and append stdout to file “filename.”ls -l >> dirs.txt
command 2>filenameRedirect stderr to file “filename.”du -ch /snaps/ 2> space.txt
command 2>>filenameRedirect and append stderr to file “filename.”awk '{ print $4}' input.txt 2>> data.txt
command &>filename
command >filename 2>&1
Redirect both stdout and stderr to file “filename.”grep -R foo /etc/ &>out.txt
command &>>filename
command >>filename 2>&1
Redirect both stdout and stderr append to file “filename.”whois domain &>>log.txt
🐧 Get the latest tutorials on SysAdmin, Linux/Unix, Open Source/DevOps topics:
CategoryList of Unix and Linux commands
File Managementcat
FirewallCentOS 8 OpenSUSE RHEL 8 Ubuntu 16.04 Ubuntu 18.04 Ubuntu 20.04
Network Utilitiesdig host ip nmap
OpenVPNCentOS 7 CentOS 8 Debian 10 Debian 8/9 Ubuntu 18.04 Ubuntu 20.04
Package Managerapk apt
Processes Managementbg chroot cron disown fg jobs killall kill pidof pstree pwdx time
Searchinggrep whereis which
User Informationgroups id lastcomm last lid/libuser-lid logname members users whoami who w
WireGuard VPNCentOS 8 Debian 10 Firewall Ubuntu 20.04

ADVERTISEMENTS
12 comments… add one
  • Sayed Ahmad Feb 12, 2012 @ 0:11

    What this mean?
    $ command > file-name 2>&1

    • Hesham M Jan 22, 2014 @ 15:34

      This means redirect stdout to file-name, with that in mind redirect stderr t stdout.
      This will lead to both stderr and stdout go to file-name.

  • Shane Hathaway Feb 24, 2012 @ 1:02

    Sayed: that line means execute the command while redirecting both stdout and stderr to a file given by file-name.

    • RudyD Apr 2, 2012 @ 12:47

      Greetings!

      A slightly more correct is:
      The output of the ‘command’ is redirected to a ‘file-name’ and the error chanel (that is the ‘2’ is redirected to a pointer (?) of the output (‘&1’).
      So stderr goes to the stdout and that goes to the file.

      • TodorMinchev May 14, 2013 @ 21:03

        RudyD
        +1
        :)

        • Daniel Aug 26, 2013 @ 19:22

          Actually it means “first redirect STDERR to STDOUT, so any errors printed out on STDERR should go to STDOUT. Then, execute ‘command’ and redirect its STDOUT to ‘file-name'” – keeping in mind that at this point STDOUT will also contain whatever is written to STDERR because of the earlier redirection.

          • Sekkuar Sep 2, 2013 @ 19:20

            Incorrect.
            There are two incorrect concepts in your answer.

            First is: the redirection happens from left to right. This means that the STDOUT is redirected first.
            (When you have > without a stream number, it actually have an implicit 1)
            And only after STDERR is redirected to “the same place STDOUT is pointing”, meaning, ‘file-name’

            Second wrong concept with your answer is: There are no connection between the descriptors. Changing STDOUT after STDERR had been redirected to STDOUT won’t change STDERR.
            It will make STDERR point to STDOUT and then change STDOUT to something else (without touching STDERR)
            Here is a more detailed tutorial covering both those misconceptions
            http://wiki.bash-hackers.org/howto/redirection_tutorial

  • iek Sep 24, 2012 @ 7:11

    I like the &>file one. but not for every stiuation.

  • Matt Kukowski Jan 29, 2014 @ 18:33

    In pre-bash4 days you HAD to do it this way:

    cat file > file.txt 2>&1

    now with bash 4 and greater versions… you can still do it the old way …but …

    cat file &> file.txt

    The above is bash4+ … some OLD distros may use prebash4 but I think they are alllong gone by now. Just something to keep in mind.

  • iamfrankenstein Jun 12, 2014 @ 20:35

    I really love: “command2>&1 | tee logfile.txt

    because tee log’s everything and prints to stdout . So you stil get to see everything! You can even combine sudo to downgrade to a log user account and add date’s subject and store it in a default log directory :)

  • Alejandro Apr 22, 2015 @ 16:41

    Hi! good explanation, I’d like to make a function on C that redirects STDIN and SDTOUT to an script, how can I do that, I mean, the exist a library’s on C to put terminal sintaxis on C?, how would you start to do it? I’m very lost with this. Thankyou!

  • AAA Dec 4, 2016 @ 14:15

    Kewl, thx

Leave a Reply

Your email address will not be published.

Use HTML <pre>...</pre>, <code>...</code> and <kbd>...</kbd> for code samples.