1

Is it true to conclude that there are 4 types of stream output we can reference to a file in Linux, if we don't want them to appear in the CLI after executing their command?

Possible references to a file:

  1. All stream output
  2. Only stderr
  3. Only stdout (including stdout's final result).
  4. stdout and stderr (excluding stdout's final result).

Notes:

An example for number 4 might be find / -type f -name php.ini 2>/dev/null. As I understand, with this command we get no stderr, and no stdout (besides the stdout's final result which in this case is the file we searched for, if it was found).

  • 5
    When you use 2>/dev/null, you are redirecting only stderr. Bash never redirects a stream only partially. – zondo Apr 10 '17 at 2:40
  • In addition to the corrections already given, I would like to point out that this is not “in Linux” this is a Unix or Gnu thing (it is done in the shell). Linux is just the kernel (and before someone points out that the kernel is involver, note this is true for everything that the computer does). – ctrl-alt-delor Apr 10 '17 at 11:35
  • This is a very oddly worded question. What do you mean by “reference”?  Do you mean “redirect”?  And what do you mean by “stdout’s final result”?  As Kusalananda says in his answer, this is not a standard Unix/Linux/bash phrase; if you Google it (in quotes), you will find this question and nothing else.  If you’re going to make up terms, you should define them. … (Cont’d) – G-Man Says 'Reinstate Monica' Apr 13 '17 at 5:49
  • (Cont’d) …  As zondo commented, the example command you give, find / -type f -name php.ini 2>/dev/null, is an illustration of option 2: only stderr is being redirected. All the stdout from that command goes to the screen (or whatever the shell’s stdout is). Reiterating and reinforcing what zondo said, there is no concept in the shell of sending the last line of a “stream” one place and the rest someplace else (although this can be done with complicated constructs involving other programs). – G-Man Says 'Reinstate Monica' Apr 13 '17 at 5:50
  • Yes - redirect. I exampled the "stdou's final result" but the answers clarified that in the end. – JohnDoea Apr 13 '17 at 5:55
4

There are two output streams connected to each process on a Unix system: standard output (stdout, file-descriptor 1) and standard error (stderr, file-descriptor 2). These may be redirected independent of each other. Standard input uses file-descriptor 0.

  • To redirect standard output to the file file, use >file or the more explicit 1>file. Replace file by /dev/null to discard the data.
  • To redirect standard error to the file file, use 2>file.
  • To redirect standard error to wherever standard output is going, use 2>&1.
  • To redirect standard output to wherever standard error is going, use 1>&2.

There is no concept "the final result" of a stream or process. I suppose whatever is sent to standard output may be taken as the "result" of a process, unless it also outputs data to some file it opens by itself or has other side-effects (like unlinking a file from a directory, in the case of rm, or handling a number of network connections, in the case of sshd). A process also returns an exit status (zero for "success" and non-zero for "failure") which could be seen as "the result" of that process, but this is not necessarily related to the output streams of the process.

Streams may also be redirected in append mode, in which means that if the redirection is to a file, that file will not initially be truncated, and any data on the stream will be appended to the end of the file. One does this by using >>file instead of >file.

In the note in the question, the command

find / -type f -name php.ini 2>/dev/null

is given. This redirects (discards) only standard error. The standard output stream is not redirected at all and will therefore be visible, in its entirety, in the console or terminal. If it was an intermediate part of a pipeline, the standard output stream would be fed into the standard input of the next command in the pipeline.

So to conclude, I'd say that there are two (not four) output streams. These may be redirected independently in various ways, which includes discarding their contents.

  • 1
    There is a small return value, an number. It is used to indicate success (0), or failure (another number). It is not displayed on the screen. – ctrl-alt-delor Nov 24 '18 at 11:28
  • @ctrl-alt-delor Did some rewriting just now. – Kusalananda Nov 24 '18 at 11:56
3

Every process can use, by convention, three standard file descriptors. These file descriptors are available as streams: stdin, stdout, and stderr.

By default, when you start a process from a shell (CLI) the first is connected to the input of your terminal (or terminal emulator like xterm), and the other two are connected to the output of your terminal.

You can instruct the shell to redirect them elsewhere, for example to /dev/null (where they just get swallowed up). And you can do that independently for stdout and stderr. So for this case, there are indeed four possibilities:

command 
command > /dev/null
command 2> /dev/null
command > /dev/null 2> /dev/null

But nothing prevents you from redirecting either or both elsewhere:

command > /tmp/myout 2> /tmp/myerr

In that case, you will also get no output in your terminal, but you can read it later in the files /tmp/myout and /tmp/myerr.

  • The "terminal" is not the same as the "shell". It's the shell that sets up the redirections. The terminal has no concept of them. The terminal may also run a program which is not a shell at all, e.g. with xterm -e mutt. – Kusalananda Apr 10 '17 at 10:00
  • @Kusalananda: That's exactly why I wrote terminal. Stdin, stdout, stderr are connected to the terminal, both when you invoke a command from the shell , and when you do xterm -e mutt etc. They are never connected to the shell. The shell can set up redirections upon invoking commands using the syntax examples given (but actually all programs can do that when invoking other programs). – dirkt Apr 10 '17 at 10:55
  • @dirkt: Kusalananda is right; you are confusing the issue by artificially narrowing the scope of your statement, and then using nomenclature that is correct only in that narrowed context.  The user could run cmd1 > out1; cmd2 in a script run by cron (or, perhaps, by system startup, a daemon, or by ssh without the -t option), and both programs would have stdin and stderr connected to the stdin and stderr, respectively, of the shell, and cmd2 would have stdout connected to the stdout of the shell, with no terminal being involved. … (Cont’d) – G-Man Says 'Reinstate Monica' Apr 13 '17 at 5:52
  • (Cont’d) …  If a process gets stdin, stdout and/or stderr connected to a terminal, it’s because it inherited that file descriptor/stream from the shell that started it (or, potentially, by some more obscure and less common mechanism).  The CLI case is a special case of the general case, and should be handled as such. – G-Man Says 'Reinstate Monica' Apr 13 '17 at 5:52
0

The situation is simpler, and more complicated, than your question would suggest.  To paraphrase what Kusalananda says in his answer, there are two standard (conventional) I/O streams (file descriptors) that are conventionally configured and used for output: stdout (file descriptor 1) and stderr (file descriptor 2).  Our canonical question, What are the shell's control and redirection operators?, discusses how to redirect them.  Naïvely, we can enumerate five distinct combinations:

╔══════════════════════════════╦═════════════════════════════════════════════╗
║                              ║                   stderr                    ║
║                              ╟─────────────────────┬───────────────────────╢
║                              ║       default       │                       ║
║                              ║ (same as the shell) │       redirected      ║
╠════════╤═════════════════════╬═════════════════════╦═══════════════════════╣
║        │       default       ║                     ║                       ║
║        │ (same as the shell) ║          1          ║           2           ║
║        ├─────────────────────╠═════════════════════╬═══════════════════════╣
║ stdout │                     ║                     ║ 4. redirected         ║
║        │                     ║                     ║    to the same file   ║
║        │      redirected     ║          3          ╟───────────────────────╢
║        │                     ║                     ║ 5. redirected         ║
║        │                     ║                     ║    to different files ║
╚════════╧═════════════════════╩═════════════════════╩═══════════════════════╝

but if you count /dev/null as being different from a file, and append mode as a special case, and read-write mode as being different from write-only mode, and pipes as being different from files, then the number of combinations increases exponentially.  However, as stated repeatedly, “stdout’s final result” is not a standard Unix/Linux/bash phrase.

Only two?

The other answers (perhaps wisely) restricted themselves to stdout and stderr (file descriptors 1 and 2).  I (recklessly?) believe that a complete answer to this question should address the fact that other file descriptors are available — up to hundreds, thousands, or even over a million.  For example, if you run a command like diff file1 file2, the diff program will open file1 and file2, and the kernel will probably assign file descriptors 3 and 4.  The difference is that only file descriptors 0, 1 and 2 are pre-defined.  Redirecting file descriptors higher than 2 is discussed in the following places:

For example, see this example of a high file descriptor:

$ cat canine.c
#include <stdio.h>
#include <string.h>

main()
{
        int     i, len;
        char    msg[] = "Hello, dog.\n";

        len = strlen(msg);
        i = write(17, msg, len);
        if (i == len)
                printf("Success!  i = %d = len\n", i);
        else if (i == -1)
            {
                printf("Error!  i = %d (len = %d)\n", i, len);
                perror("");
            }
        else
                printf("Unexpected result: i = %d, len = %d\n", i, len);
}

$ make canine
cc     canine.c   -o canine

$ ./canine
Error!  i = -1 (len = 12)
Bad file descriptor

$ ./canine 17> animal
Success!  i = 12 = len

$ ls -l
total 70
-rw-r--r-- 1 myusername mygroupname    12 Apr 12 13:36 animal
-rwxr-xr-x 1 myusername mygroupname 67067 Apr 12 13:36 canine
-rw-r--r-- 1 myusername mygroupname   358 Apr 12 13:36 canine.c

$ cat animal
Hello, dog.

Warning: I’m not sure that the above will work for all versions of all shells.

Standard programs don’t write to file descriptors higher than 2 (unless they got that file descriptor from the kernel by opening a file, making a network connection, or something like that).  But, if you have a (non-standard) program that does that, you can redirect those file descriptors.

And, if you have a mere 100 file descriptors, and you consider only whether each one is redirected or not, you have over a nonillion (1,000,000,000,000,000,000,000,000,000,000) possible combinations.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.