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

cp: error reading ‘/mnt/tt/file.txt’: Input/output error
cp: failed to extend ‘/mnt/tt/file.txt’: Input/output error


我要将内容保存到文件中。 br />

评论

@terdon这是一个更具体的问题,它在Google搜索中正确显​​示了更具体的问题,这是一件好事。

@nroose是的,它会不断显示,不会改变。但是,任何新的答案都应该针对更笼统的问题。

#1 楼

Linux(和其他OS)中有两个主要输出流,标准输出(stdout)和标准错误(stderr)。错误消息(如您​​显示的错误消息)将打印为标准错误。传统的重定向操作符(command > file)仅重定向标准输出,因此标准错误仍显示在终端上。要同时重定向stderr,您有几种选择:



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

command > out 2>error



将stdout重定向到文件(>out),然后将stderr重定向到stdout(2>&1):

command >out 2>&1



将两个文件都重定向到一个文件(例如,并非所有的外壳程序都支持此文件,例如bashzsh不支持该文件,但shksh不支持该文件):

command &> out



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

评论


因此hashdeep -rXvvl -j 30 -k checksums.txt / mnt / app / >> result_hashdeep.txt 2> error_hashdeep.txt&或hashdeep -rXvvl -j 30 -k checksums.txt / mnt / app / >> result_hashdeep.txt 2>&1或hashdeep -rXvvl -j 30 -k checksums.txt / mnt / app /&> result_mixed.txt

–AndréM. Faria
15年5月18日在12:59



@AndréM.Faria是的。但是最后两个命令是等效的,它们会将错误和输出都发送到同一文件。

– terdon
15年5月18日在13:17

如您提供的链接中所示,我可以使用|&代替2>&1,它们等效,谢谢您的宝贵时间。

–AndréM. Faria
15年5月18日在13:38

@rohith我知道这是一个死灵,但是,您可以执行命令| sudo -S tee文件> / dev / null 2>&1

–寻宝者
18-10-11在21:58



我无法在&sh中工作,只能使用bash。 Cron用户要当心,请改用2>&1。

–迈克·麦凯(Mike McKay)
19年3月3日在11:41

#2 楼

首先要注意的是,有两种方法取决于您的目的和外壳,因此这需要对多个方面有一点了解。此外,某些命令(例如timestrace)默认情况下会将输出写入stderr,并且可能会或可能不会提供特定于该命令的重定向方法。

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

外壳重定向

最典型的方法是在类似Bourne的外壳中通过2>进行操作,例如dash(与/bin/sh链接)和bash;第一个是默认的且兼容POSIX的外壳,另一个是大多数用户用于交互式会话的外壳。它们的语法和功能不同,但是幸运的是,错误流重定向的工作原理相同(&>非标准版本除外)。如果使用csh及其派生类,则stderr重定向在此处无法正常工作。

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

[n]redir-op word


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

shell中典型命令的语法略为简化。

 command [arg1] [arg2]  2> /dev/null


这里的窍门是重定向可以出现在任何地方。即2> command [arg1]command 2> [arg1]均有效。请注意,对于bash shell,存在一种同时重定向stdout和stderr流的&>方法,但同样-它是bash专用的,并且如果您正在争取脚本的可移植性,则可能不起作用。另请参见Ubuntu Wiki和&>和2>&1之间有什么区别。

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

如果您可能会注意到,>仅用于一个命令。对于脚本,我们可以像在myscript.sh 2> /dev/null中那样从外部重定向整个脚本的stderr流,也可以使用内置的exec。可以说,内置的exec可以重新交互整个Shell会话的流,无论是交互方式还是通过脚本。类似于

#!/bin/sh
exec 2> ./my_log_file.txt
stat /etc/non_existing_file


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

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

some_function(){
    command1
    command2
} 2> my_log_file.txt


专门写到stderr的命令

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

time echo foo 2>&1 > file.txt


或者,如果您要重定向同步列表或子Shell,则可以分隔输出(如相关文章中所示):

{ time sleep 1 2> sleep.stderr ; } 2> time.txt


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

result=$(dialog --inputbox test 0 0 2>&1 1>/dev/tty);


但除此之外,还有--output-fd标志,我们也可以使用。还有命名管道的方法。我建议阅读有关dialog命令的链接文章,以全面了解正在发生的事情。