如何将 stderr 重定向到文件

And*_*ria 538 command-line redirect

使用 nohup 将命令在后台运行时,某些内容会出现在终端中。

cp: error reading ‘/mnt/tt/file.txt’: Input/output error
cp: failed to extend ‘/mnt/tt/file.txt’: Input/output error
Run Code Online (Sandbox Code Playgroud)

我想将该内容保存到文件中。

ter*_*don 914

Linux(和其他操作系统)中有两个主要的输出流,标准输出(stdout)和标准错误(stderr)。错误消息,就像你显示的那样,被打印为标准错误。经典重定向运算符 ( command > file) 仅重定向标准输出,因此终端上仍会显示标准错误。要重定向 stderr,您有几个选择:

  1. 将 stdout 重定向到一个文件,将 stderr 重定向到另一个文件:

    command > out 2>error
    
    Run Code Online (Sandbox Code Playgroud)
  2. 将 stdout 重定向到文件 ( >out),然后将 stderr 重定向到 stdout ( 2>&1):

    command >out 2>&1
    
    Run Code Online (Sandbox Code Playgroud)
  3. 既重定向到一个文件中(这是不是所有的炮弹支持,bashzsh支持它,例如,但shksh没有):

    command &> out
    
    Run Code Online (Sandbox Code Playgroud)

有关各种控制和重定向运算符的更多信息,请参见此处

  • @AndréM.Faria 是的。但是最后两个命令是等效的,它们会将错误和输出发送到同一个文件。 (3认同)
  • 我无法 &> 在 sh 中工作,只能在 bash 中工作。Cron 用户要小心,请改用 2>&1。 (3认同)
  • 正如您提供的链接,我可以使用 |& 而不是 2>&1 它们是等效的,谢谢您的时间。 (2认同)

Ser*_*nyy 28

首先要注意的是,根据您的目的和外壳,有几种方法,因此这需要对多个方面略有了解。此外,某些命令,如timestrace写入输出到默认标准错误,并且可以或可以不以该命令提供重定向特定的方法

重定向背后的基本理论是,一个由 shell 产生的进程(假设它是一个外部命令而不是 shell 内置的)是通过fork()execve()系统调用创建的,在此之前,另一个系统调用dup2()会在execve()发生之前执行必要的重定向。从这个意义上说,重定向是从父 shell 继承的。在m&>nm>n.txt通知有关如何执行壳open()dup2()系统调用(另见如何输入重定向的作品是什么重定向和管道之间的区别,以及什么在输出重定向确实与准确平均值

外壳重定向

最典型的,是通过2>类似Bourne壳,如dash(其被链接到/bin/sh)和bash; 第一个是默认的和 POSIX 兼容的 shell,另一个是大多数用户用于交互式会话的。它们在语法和功能上有所不同,但幸运的是,错误流重定向的工作原理相同(&>非标准重定向除外)。在 csh 及其衍生产品的情况下,stderr 重定向在那里不太适用。

让我们回到2>部分。需要注意的两个关键事项:>表示重定向操作符,我们打开一个文件,2整数表示 stderr 文件描述符;事实上,这正是 shell 语言的 POSIX 标准在第 2.7 节中定义重定向的方式:

[n]redir-op word
Run Code Online (Sandbox Code Playgroud)

对于简单的>重定向,1整数隐含为stdout,即echo Hello World > /dev/null与 相同echo Hello World 1>/dev/null。请注意,整数或重定向运算符不能被引用,否则 shell 不会将它们识别为这样,而是将其视为文本字符串。至于间距,整数紧邻重定向运算符很重要,但文件可以紧挨重定向运算符,也可以不,即,command 2>/dev/null并且command 2> /dev/null会正常工作。

shell 中典型命令的稍微简化的语法是

 command [arg1] [arg2]  2> /dev/null
Run Code Online (Sandbox Code Playgroud)

这里的技巧是重定向可以出现在任何地方。这既2> command [arg1]command 2> [arg1]有效。请注意,对于bashshell,存在&>同时重定向 stdout 和 stderr 流的方法,但同样 - 它是特定于 bash 的,如果您正在努力实现脚本的可移植性,它可能不起作用。另请参阅Ubuntu Wiki&> 和 2>&1 之间的区别是什么

注:>重定向操作截断文件并将其覆盖,如果该文件存在。该2>>可用于附加stderr到文件中。

如果您可能注意到,>用于单个命令。对于脚本,我们可以像 in 一样从外部重定向整个脚本的 stderr 流,myscript.sh 2> /dev/null或者我们可以使用exec 内置。exec 内置函数可以为整个 shell 会话重新连接流,可以这么说,无论是交互方式还是通过脚本。就像是

#!/bin/sh
exec 2> ./my_log_file.txt
stat /etc/non_existing_file
Run Code Online (Sandbox Code Playgroud)

在此示例中,日志文件应显示stat: cannot stat '/etc/non_existing_file': No such file or directory.

还有一种方法是通过函数。正如kopciuszek在他的回答中指出的那样,我们可以编写带有已附加重定向的函数声明,即

some_function(){
    command1
    command2
} 2> my_log_file.txt
Run Code Online (Sandbox Code Playgroud)

专门写入 stderr 的命令

默认情况下,诸如time和 之类的命令strace将其输出写入 stderr。在time命令的情况下,唯一可行的选择是重定向整个命令的输出,即

time echo foo 2>&1 > file.txt
Run Code Online (Sandbox Code Playgroud)

或者,如果您想分离输出(如相关帖子所示),可以重定向同步列表或子shell :

{ time sleep 1 2> sleep.stderr ; } 2> time.txt
Run Code Online (Sandbox Code Playgroud)

其他命令,例如stracedialog提供重定向标准错误的方法。strace具有-o <filename.txt>允许指定应写入输出的文件名的选项。还有一个选项可以为strace看到的每个子进程编写一个文本文件。该dialog命令将文本用户界面写入标准输出但输出到标准错误,因此为了将其输出保存到变量(因为var=$(...)管道只接收标准错误)我们需要交换文件描述符

result=$(dialog --inputbox test 0 0 2>&1 1>/dev/tty);
Run Code Online (Sandbox Code Playgroud)

但此外,还有--output-fd标志,我们也可以使用。还有命名管道的方法。我建议阅读有关该dialog命令的链接帖子,以全面描述正在发生的事情。


归档时间:

查看次数:

989443 次

最近记录:

6 年 前