bash sh 命令:exec 2>&1
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1216922/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
sh command: exec 2>&1
提问by
What will this command do?
这个命令会做什么?
exec 2>&1
采纳答案by Rob Wells
Technically speaking it duplicates, or copies, stderr onto stdout.
从技术上讲,它会将 stderr 复制或复制到 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 来执行此操作。exec 与文件描述符的更典型用法是指示您要将文件分配给未使用的文件描述符,例如
exec 35< my_input
BTW Don't forget that the sequence of declaration when piping to a file is important, so
BTW 不要忘记管道到文件时的声明顺序很重要,所以
ls > mydirlist 2>&1
will work because it directs both stdout and stderr to the file mydirlist, whereas the command
会起作用,因为它将 stdout 和 stderr 都指向文件 mydirlist,而命令
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.
仅将 stdout 而不是 stderr 定向到文件 mydirlist,因为在将 stdout 重定向到 mydirlist 之前,stderr 已成为 stdout 的副本。
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!
编辑:这是外壳从左到右扫描的工作方式。因此,在说“将标准输出发送到 mydirlist”之前,将第二个读为“将标准错误复制到标准输出”。然后将第一个读为“将标准输出发送到文件 mydirlist”,然后再读为“将标准错误复制到我设置的标准输出上”。我知道。完全不直观!
回答by Brian Taylor
One of the better articles I've seen on what "2>&1" does is Bash One-Liners Explained, Part III: All about redirections.
我看过的关于 "2>&1" 的更好的文章之一是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".
但是这个问题的当前答案未能提供的是为什么你想在一个简单的“exec”之后这样做。正如 exec 命令的 bash 手册页所解释的那样:“如果未指定命令,则任何重定向都将在当前 shell 中生效”。
I wrote a simple script called out-and-err.py
that writes a line of output to stdout, and another line to stderr:
我编写了一个名为的简单脚本out-and-err.py
,将一行输出写入 stdout,另一行写入 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":
然后我将它包装在一个名为 out-and-err.sh 的 shell 脚本中,并带有“exec 2>&1”:
#!/bin/bash
exec 2>&1
./out-and-err.py
If I run just the python script, stdout and stderr are separate:
如果我只运行 python 脚本,stdout 和 stderr 是分开的:
$ ./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:
但是,如果我运行 shell 脚本,您可以看到 exec 会处理以下所有内容的 stderr:
$ ./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.
如果您的包装 shell 脚本不仅仅是一个 python 命令,并且您需要将所有输出组合到标准输出中,那么执行“exec 2>&1”将使您轻松完成。
回答by Charles Ma
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
.
的2
是stderr和1
为stdout。当您运行程序时,您将在 stdout 中获得正常输出,但任何错误或警告通常都会转到 stderr。例如,如果要将所有输出通过管道传输到文件,首先将 stderr 与 stdout 与2>&1
.
回答by Mark Rushakoff
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.
就像@cma 所说,它将 stderr 放在 stdout 上。您可能想要此行为的原因是使用 grep 或任何其他实用程序来捕获仅出现在 stderr 上的输出。或者您可能只想将所有输出(包括 stderr)保存到一个文件中以供以后处理。
回答by Alopex
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.
这些天我也被这个问题搞得一团糟,但现在我摆脱了它。所以,请允许我解释一下您exec 1>&2
在 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
代表什么:
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.
exec
是 Linux 中的内置命令。不同于传统的命令只是fork一个子shell进程,exec
可以改变当前的shell进程。
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:
- open a new terminal
- Get the termianl process process ID
$ pstree -p | grep 'term' | tr -d ' '
- 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, thels
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. - 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. - 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 - 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
什么是 I/O 重定向:重定向是 Linux 中的一项功能。有了这个,您可以更改标准输入/输出设备。在 Linux 中,默认情况下有三个文件描述符。
Handle Name Description 0 stdin Standard input 1 stdout Standard output 2 stderr Standard error
让我看一个例子:
- 打开一个新终端
- 获取终端进程进程ID
$ pstree -p | grep 'term' | tr -d ' '
- 检查进程文件描述符。
$ 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
如您所见,ls
列出了 PID(6860) 进程文件。首先,它们都以数字命名(0, 1, 2),其次它们都将文件链接到 /dev/pts/3,这意味着无论标准输入/输出/错误都将显示在 pts3 中。 - 将标准输出更改为 /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" $
那时命令输出消失了。 - 打开一个新终端,检查 proc 文件
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
显然,我们可以注意到 1(文件描述符)已经将链接更改为 /tmp/stdout。除了我们之外,标准输出传输到 /tmp/stdout - 恢复重定向。
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
再次,1(文件描述符)链接到 /dev/pts/3,我们可以再次看到输出。
概括:
exec 1>&2
制作标准输出 ---> 标准错误
回答by drchuck
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:
exec 2>&1
我遇到的一个非常有用的应用程序是当您想要合并stderr
并stdout
使用分号分隔的多个命令时。我的特定示例发生在我popen
在 PHP 中发送多个命令时,我希望看到交错的错误,就像您在 shell 提示符下键入命令时看到的那样:
$ 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):
以下不合并stderr
,stdout
除了最后一个echo
(这是毫无意义的,因为yikes
会导致错误):
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
:
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.
你得到的stdout
与stderr
输出很好地交织完全按照自己的终端上看到,如果你执行的三个命令分离一个分号。