sh command: exec 2>&1

后端 未结 6 666
名媛妹妹
名媛妹妹 2020-12-24 00:45

What will this command do?

exec 2>&1 
相关标签:
6条回答
  • 2020-12-24 01:13

    It ties standard error to standard out

    the 2 is stderr and 1 is stdout. When you run a program, you'll get the normal output in stdout, but any errors or warnings usually go to stderr. If you want to pipe all output to a file for example, it's useful to first combine stderr with stdout with 2>&1.

    0 讨论(0)
  • 2020-12-24 01:15

    Technically speaking it duplicates, or copies, stderr onto stdout.

    Usually you don't need the exec to perform this. A more typical use of exec with file descriptors is to indicate that you want to assign a file to an unused file descriptor, e.g.

    exec 35< my_input

    BTW Don't forget that the sequence of declaration when piping to a file is important, so

    ls > mydirlist 2>&1
    

    will work because it directs both stdout and stderr to the file mydirlist, whereas the command

    ls 2>&1 > mydirlist
    

    directs only stdout, and not stderr, to file mydirlist, because stderr was made a copy of stdout before stdout was redirected to mydirlist.

    Edit: It's the way that the shell works scanning from left to right. So read the second one as saying "copy stderr onto stdout" before it says "send stdout to mydirlist". Then read the first one as saying "send stdout to the file mydirlist" before it says "duplicate stderr onto that stdout I've set up". I know. It's totally not intuitive!

    0 讨论(0)
  • 2020-12-24 01:26

    Like @cma said, it puts stderr on stdout. The reason you might want this behavior is to use grep or any other utility to capture output that only appears on stderr. Or you might just want to save all the output, including stderr, to a file for later processing.

    0 讨论(0)
  • 2020-12-24 01:30

    One of the better articles I've seen on what "2>&1" does is Bash One-Liners Explained, Part III: All about redirections.

    But what the current answers on this question fail to provide is why you'd want to do this after a plain "exec". As the bash man page for the exec command explains: "If command is not specified, any redirections take effect in the current shell".

    I wrote a simple script called out-and-err.py that writes a line of output to stdout, and another line to stderr:

    #!/usr/bin/python
    import sys
    sys.stdout.write('this is stdout.\n')
    sys.stderr.write('this is stderr.\n')
    

    And then I wrapped that in a shell script called out-and-err.sh with an "exec 2>&1":

    #!/bin/bash
    exec 2>&1
    ./out-and-err.py
    

    If I run just the python script, stdout and stderr are separate:

    $ ./out-and-err.py 1> out 2> err
    $ cat out
    this is stdout.
    $ cat err
    the is stderr.
    

    But if I run the shell script, you can see that the exec takes care of stderr for everything after:

    $ ./out-and-err.sh 1> out 2> err
    $ cat out
    this is stdout.
    this is stderr.
    $ cat err
    $
    

    If your wrapping shell script does a lot more than just the one python command, and you need all output combined into stdout, doing the "exec 2>&1" will make that easy for you.

    0 讨论(0)
  • 2020-12-24 01:32

    One quite useful application of exec 2>&1 that I have come across is when you want to merge stderr and stdout for several commands separated by semicolons. My particular example happened when I was sending more than one command to popen in PHP and I wanted to see the errors interleaved like you would see if you typed the commands at a shell prompt:

    $ echo hi ; yikes ; echo there
    hi
    -bash: yikes: command not found
    there
    $ 
    

    The following does not merge stderr and stdout except for the last echo (which is pointless because the yikes causes the error):

    echo hi ; yikes ; echo there 2>&1
    

    I can get the merged output the "hard way" as follows:

    echo hi 2>&1; yikes 2>&1; echo there 2>&1
    

    It looks a lot cleaner and less error prone if you use exec:

    exec 2>&1 ; echo hi; echo yikes; echo there
    

    You get the stdout and stderr output nicely interleaved exactly as you would see on the terminal if you executed the three commands separated by a semicolon.

    0 讨论(0)
  • 2020-12-24 01:33

    These day I was suck at this problem too, but now I'm jump out from it. So, please allow me to explain what happen after you input exec 1>&2 in CLI.

    I want to destruct the problem piece by piece, so if you know the knowledge alread just skim it to save your time.

    • What is exec stands for:

    exec is a built-in command in Linux. Different from the tradition command which just fork a sub shell process, exec could change current shell process.

    • What is I/O redirection: Redirection is a feature in Linux. With this you can change the standard input/output devices. In Linux, there are three file descriptors by default. Handle Name Description 0 stdin Standard input 1 stdout Standard output 2 stderr Standard error

    • Let me see an example:

      1. open a new terminal
      2. Get the termianl process process ID $ pstree -p | grep 'term' | tr -d ' '
      3. Check the process file descriptor. $ sudo ls -l /proc/{pid}/fd bash $ pstree -p | grep -i 'terminal' | tr -d ' ' ||||-gnome-terminal-(6008)-+-bash(7641)-+-grep(8355) $ sudo ls -l /proc/7641/fd total 0 lrwx------ 1 alopex alopex 64 Oct 27 19:39 0 -> /dev/pts/3 lrwx------ 1 alopex alopex 64 Oct 27 19:39 1 -> /dev/pts/3 lrwx------ 1 alopex alopex 64 Oct 27 19:39 2 -> /dev/pts/3 lrwx------ 1 alopex alopex 64 Oct 27 19:39 255 -> /dev/pts/3 As you can see, the ls list the PID(6860) process file. First they all name by number(0, 1, 2), second they all link file link to /dev/pts/3, it means whatever standard input/output/error all will show up in pts3.
      4. Change the standard output to /tmp/stdout bash $ ls /tmp/stdout ls: cannot access '/tmp/stdout': No such file or directory $ exec 1>/tmp/stdout $ ls $ pwd $ echo "Are you ok" $ The command output was disappear at that time.
      5. Open a new terminal, to check the proc file bash $ sudo ls -l /proc/7641/fd total 0 lrwx------ 1 alopex alopex 64 Oct 27 19:39 0 -> /dev/pts/3 lrwx------ 1 alopex alopex 64 Oct 27 19:39 1 -> /tmp/stdout lrwx------ 1 alopex alopex 64 Oct 27 19:39 2 -> /dev/pts/3 lrwx------ 1 alopex alopex 64 Oct 27 19:39 255 -> /dev/pts/3 Obviously, we can notice that the 1(file descriptor) already change link to /tmp/stdout. As us except, the standard output transfer to /tmp/stdout
      6. Restore the redirection. bash $ exec 1>&2 $ cat /tmp/stdout a.sh /home/alopex Are you ok $ sudo ls -l /proc/7641/fd total 0 lrwx------ 1 alopex alopex 64 Oct 27 19:39 0 -> /dev/pts/3 lrwx------ 1 alopex alopex 64 Oct 27 19:39 1 -> /dev/pts/3 lrwx------ 1 alopex alopex 64 Oct 27 19:39 2 -> /dev/pts/3 lrwx------ 1 alopex alopex 64 Oct 27 19:39 255 -> /dev/pts/3 Again, the 1(file descriptor) link to the /dev/pts/3, we can see the output again.
    • Summary:

    • exec 1>&2 make the standard output ---> standard error
    0 讨论(0)
提交回复
热议问题