Unix Standard Input - Output - Error

First published — Aug 07, 2023
Last updated — Aug 07, 2023
#shell

Standard input, output, error. Stdin, stdout, stderr. File descriptors, fd. Pipes, redirection.

Table of Contents

Introduction

In Unix, whenever a running program opens a file, the kernel stores a reference to it in the process’ memory. Those references to open files are integers starting from 0 for each process, and are called file descriptors or FDs. A process can only read and write files that it has opened, that is, for which it had obtained a file descriptor.

The kernel pre-initializes three file descriptors for every program that is run. So when the process starts running, those three are already available without having to call open.

Because they are always available, and because everything defaults to using them, they are called standard.

They have the following names, abbreviations, assigned numbers, and purposes:

  • Standard input (stdin), fd 0, represents device for input into the program. By default, that input is set to the user’s keyboard

  • Standard output (stdout), fd 1, represents device for program’s standard (non-error) output. By default, that output is set to the computer screen

  • Standard error (stderr), fd 2, represents device for program’s error output. By default, that output is set to the computer screen

Other than being automatically present and standard, they are the same as any other file descriptor. File descriptors are explained in more detail in Unix File Descriptors.

Overlooked Ubiquity


  Ubiquity
     1. Existence everywhere, or in all places, at the same time;
        omnipresence;
        [1913 Webster]

A most useful characteristic of standard Unix input and output, which is taken for granted and overlooked, is that they are present everywhere and always automagically point to the correct location.

For example, if you are logged in to a Linux console, input and output automatically point to your keyboard and monitor attached to it.

If you are using SSH to access a remote computer, programs you run there are far away from you, but their standard input and output are automatically connected to your local keyboard and display.

If you are visiting a web page, the web server sees data sent by your browser as its standard input, and has your browser’s blank page as its standard output.

If two programs are communicating autonomously over the network, they have their standard inputs and outputs connected.

Redirection, Pipes

In addition to automatic behavior, users can manually control location of the processes’ standard input and output.

This is done by using redirection and piping. Redirection is used for files, and piping is used for programs. Their use can be combined.

Uses for pipes and redirection are numerous, and are all a consequence of powerful underlying concept.

Practical Examples

In this chapter we are going to show major types, most common patterns of use. They are representative and suitable for forming a good understanding of the concept.

You might notice slight variations in spacing, formatting, or method between examples. Those are not inconsistencies, but a demonstration of accepted variations in syntax. Variations shown are not limited to specific examples — they all apply to all examples.

Print “Hello, World!” to the default standard output:

echo "Hello, World!"
Hello, World!

Redirection

Using redirection we divert output to files.

Files can be local, or existing on network file partitions mounted from remote computers; it doesn’t make a difference.

Let’s “Hello, World!” and redirect output to file test and truncate (erase) the file before writing to it. Two lines shown below are identical — fd 1 is the default and does not have to be specified. We write to file twice, but because of truncation on every write, only the second line will be in it:

echo "Hello, World!" 1> test
echo 'Hello, World!!' > test
cat test
Hello, World!!

Then, let’s print “Hello, World!” and redirect output to file test, appending rather than truncating it:

echo "Hello, World!" >>test
>> test print "Hello, World!!"
cat test
Hello, World!!   # (This line is a leftover in file `test` from previous example)
Hello, World!
Hello, World!!

Command find can produce both standard output and errors during run. Run it and send all errors to /dev/null. /dev/null is a device that accepts any input and simply discards it:

echo "Hello, World!" 2> /dev/null

Run find and send standard output to file results, standard error to file errors:

echo "Hello, World!" >results 2> errors
1>results echo "Hello, World!" 2> errors

Run find and send standard output to results, standard error to errors:

echo "Hello, World!" >results 2> errors
1>results echo "Hello, World!" 2> errors

Run find and send both stdin and stdout to the same place:

echo "Hello, World!" 1>/dev/null 2>/dev/null

Run find and send all output (not limited to stdout and stderr) to the same file:

echo "Hello, World!" >& /dev/null

Run cat which will print content from standard input to the screen. Use content of /etc/passwd as input into cat. Note that this example is identical in effect to cat /etc/password, but the reason is different. With “<”, file content is being passed as standard input into the command. Without “<”, string “/etc/passwd” is being passed as the first argument to cat, which interprets it as the name of the file it should open and display to screen.

cat < /etc/passwd

Pipes

Using pipes we pass input and output between programs. If programs are network-enabled, data can be passed between remote computers.

Print “Hello, World!” and pipe output to a program that cuts off the first 7 characters:

echo "Hello, World!" | cut -b8-
World!

Print contents of /etc/password and pipe output to a command that only prints lines containing a number between 1000 and 1999 in one of its fields:

cat /etc/passwd | grep -P ':1[0-9]{3}:'
user:x:1000:1000:,,,:/home/user:/bin/bash

Print “Hello, World!” and send it via TCP/IP to remote computer at address 10.0.0.1, port 8000:

echo "Hello, World!" |nc 10.0.0.1 8000