Linux uses 3 standard channels of communication: Standard input (channel 0), standard output (channel 1) and standard error (channel 2). Understanding how these channels work can allow you to perform very complex tasks at the command line. Channel 0Our standard input channel will generally take input from the keyboard. A lot of times we don't notice this because most programs are fed files to work with. However, some programs are designed to only work with channel 0 such as the tr command. If you run the following command, any input you provide containing lower case characters will be converted to uppercase. Once you're done press, ctrl+c to interrupt the process and go back to the command line.
$ tr a-z A-Z
here is my text (hit Enter)
HERE IS MY TEXT
tr will only work with the standard input channel and we can see our direct communication with the program. Channel 1The standard output channel will send regular output from a program to the terminal. For example, the date command will print the current date and time to the terminal using channel 1.
$ date
Tue Sep 15 09:37:50 MDT 2015
Most output will be sent using channel 1 and unless told otherwise, will print to the terminal. Channel 2The standard error channel is reserved for warnings and error messages. Most programs will observe this standard, so you can expect any error messages using this channel. For example, let's try to run the useradd command as a non root user.
$ useradd bob
bash: useradd: Permission denied.
This message is sent out using channel 2 and unless told otherwise, will print to the terminal. RedirectionRedirection allow us to control where input is coming from or where output is going to. Let's first look at controlling channel 0 (standard input). When we looked at the tr command, we noted that you can't point it at a file. Instead, information has to be passed through channel 0. We can redirect the contents of a file to channel 0 using the less than symbol <. Your host name will be different from what you see in my output.
$ tr a-z A-Z < /etc/hostname
DEMOVM.THE-STEVE.COM
The contents of the file /etc/hostname (which contains our system's hostname) were sent to channel 0 and processed as if I had typed it out to the tr command.We can also control where out output is going. Perhaps you need to save the output into a file instead of printing it to the screen. For this we can use the greater than symbol >. If the file does not exist, it will be created for you.
$ tr a-z A-Z < /etc/hostname > /tmp/modifiedhostname
$ cat /tmp/modifiedhostname
DEMOVM.THE-STEVE.COM
Notice nothing prints out to the screen. Instead of being sent to the terminal, the output was instead redirected to the file /tmp/modifiedhostname. When you redirect to channel 1, only error messages will print to the screen. Running the cat command, we can see the contents of the file.To redirect channel 2, we'll have to specify which channel we are working with. So, let's go back and look at out useradd command.
$ useradd bob > /tmp/errormessage
bash: useradd: Permission denied.
$ cat /tmp/errormessage
Notice the error message printed to the screen and the file we created is empty. By default, the greater than symbol only specifies channel 1. To select a specific channel, you can put the channel number first.
$ useradd bob 2> /tmp/errormessage
$ cat /tmp/errormessage
bash: useradd: Permission denied.
When redirecting output, be aware that, by default the contents of a file will be overwritten. When you type a command and press Enter, redirection is run before the command executes. A single greater than symbol will have the contents of a file overwritten before it ever executes. If you'd like to append to the bottom of a file, you can use two greater than symbols >> or 2>> (for channel 2). If the file does not exist, it will be created and if the file does exist, the content will be added to the bottom of the file.
$ date > /tmp/date
$ cat /tmp/date
Tue Sep 15 09:57:32 MDT 2015
$ date > /tmp/date
$ cat /tmp/date
Tue Sep 15 09:58:02 MDT 2015
$ date >> /tmp/date
$ cat /tmp/date
Tue Sep 15 09:58:02 MDT 2015
Tue Sep 15 09:58:42 MDT 2015
PipesWhen you pipe programs together, you're sending information from channel 1 of the first program to channel 0 of the second program. So, the output of program 1 is the input of program 2. For example:
$ cat /tmp/date
Tue Sep 15 09:58:02 MDT 2015
Tue Sep 15 09:58:42 MDT 2015
$ cat /tmp/date | grep 42
Tue Sep 15 09:58:42 MDT 2015
While you'll probably never use the cat command and pipe it into grep, it illustrates this point perfectly. We took the output of the cat command, used it as the input for the grep command and searched for the string '42'. Let's add a 3rd program and manipulate the data further.
$ cat /tmp/date | grep 42 | tr a-z A-Z
TUE SEP 15 09:58:42 MDT 2015
We're now using the output from grep as the input for the tr command and we've converted the lower case characters the upper case. Pipes allow you to perform very complex tasks very elegantly from the command line. Just remember, we're only sending standard output down the pipe line, so error messages will not get passed on. You can do that quite easily though, but we can save that for another lesson.