要将标准输出重定向到Bash中的截断文件,我知道使用:
cmd > file.txt
要在Bash中重定向标准输出,附加到文件中,我知道使用:
cmd >> file.txt
要将标准输出和标准误差重定向到截断文件,我知道使用:
cmd &> file.txt
如何重定向附加到文件的标准输出和标准错误?cmd &>> file.txt对我不起作用。
cmd &>> file.txt
cmd >>file.txt 2>&1
Bash执行从左到右的重定向,如下所示:
>>file.txt
file.txt
stdout
2>&1
stderr
&1
有两种方法可以做到这一点,具体取决于您的Bash版本。
经典和便携(Bash pre-4)的方法是:
cmd >> outfile 2>&1
一个不可移植的方式,从bash4开始
cmd &>> outfile
(模拟到&> outfile)
&> outfile
对于良好的编码风格,您应该
如果您的脚本已经以#!/bin/sh开头(无论是否有意),那么Bash 4解决方案以及通常任何特定于Bash的代码都不是可行的方法。
#!/bin/sh
还要记住,Bash 4&>>只是更短的语法——它没有引入任何新功能或类似的东西。
&>>
语法(除了其他重定向语法)在bash黑客wiki中描述。
在Bash 4(以及z shell(zsh)4.3.11)中:
zsh
刚开箱。
在Bash中,您还可以显式指定重定向到不同的文件:
cmd >log.out 2>log_error.out
追加将是:
cmd >>log.out 2>>log_error.out
试试这个:
You_command 1> output.log 2>&1
您对&> x.file的使用在Bash 4中确实有效。对不起:(
&> x.file
0,1,2,…,9是bash中的文件描述符。
0代表标准输入,1代表标准输出,2代表标准误差。3~9可用于任何其他临时用途。
任何文件描述符都可以通过使用运算符>或>>(追加)重定向到其他文件描述符或文件。
>
>>
用法:<file_descriptor>><文件名|&file_descriptor>
请参阅第20章. I/O重定向中的引用。
这应该工作得很好:
your_command 2>&1 | tee -a file.txt
它将所有日志存储在file.txt中,并将它们转储到终端中。
另一种方法:
如果使用旧版本的Bash,其中&>>不可用,您还可以执行以下操作:
(cmd 2>&1) >> file.txt
这会产生一个子shell,因此它的效率低于传统的cmd >> file.txt 2>&1方法,因此它不适用于需要修改当前shell的命令(例如cd,pushd),但这种方法对我来说更自然,更容易理解:
cmd >> file.txt 2>&1
cd
pushd
此外,括号消除了顺序的任何歧义,特别是如果您想将标准输出和标准错误管道传输到另一个命令。
为了避免启动子shell,您可以使用花括号而不是括号来创建组命令:
{ cmd 2>&1; } >> file.txt
(请注意,需要分号(或换行符)来终止组命令。)
您可以从脚本本身计划重定向:
#!/bin/bash exec 1>>logfile.txtexec 2>&1 /bin/ls -ld /tmp /tnt
运行它将创建/appendlogfile.txt,包含:
logfile.txt
/bin/ls: cannot access '/tnt': No such file or directorydrwxrwxrwt 2 root root 4096 Apr 5 11:20 /tmp
您可以创建两个不同的日志文件,附加到一个总体日志并重新创建另一个最后日志:
#!/bin/bash if [ -e last.log ] ;thenmv -f last.log last.oldfiexec 1> >(tee -a overall.log /dev/tty >last.log)exec 2>&1 ls -ld /tnt /tmp
运行此脚本将
last.log
last.old
overall.log
#!/bin/bash [ -e last.err ] && mv -f last.err lasterr.old[ -e last.log ] && mv -f last.log lastlog.old exec 2> >(tee -a overall.err combined.log /dev/tty >last.err)exec 1> >(tee -a overall.log combined.log /dev/tty >last.log) ls -ld /tnt /tmp
所以你有
last.err
lastlog.old
lasterr.old
overall.err
combined.log
stdbuf
如果你打算在互动 shell中使用它,你必须告诉tee不要缓冲他的输入/输出:
tee
# Source this to multi-log your session[ -e last.err ] && mv -f last.err lasterr.old[ -e last.log ] && mv -f last.log lastlog.oldexec 2> >(exec stdbuf -i0 -o0 tee -a overall.err combined.log /dev/tty >last.err)exec 1> >(exec stdbuf -i0 -o0 tee -a overall.log combined.log /dev/tty >last.log)
来源这个,你可以试试:
ls -ld /tnt /tmp
exec
使用$(...)或<(...)运行forks是通过运行subshell完成的,它将在另一个subshell(subsubshell)中执行二进制文件。exec命令告诉shell脚本中没有其他命令要运行,因此二进制(stdbuf ... tee)将作为$(...)0执行,在$(...)1(无需保留更多内存来运行另一个子进程)。
$(...)
<(...)
forks
stdbuf ... tee
从bash的手册页(man -P'less +/^\ *exec\ ' bash):
bash
man -P'less +/^\ *exec\ ' bash
exec [-cl] [-a name] [command [arguments]]If command is specified, it replaces theshell. No new process is created....
这不是真正的需要,但减少了系统占用空间。
来自stdbuf的手册页:
NAMEstdbuf - Run COMMAND, with modified bufferingoperations for its standard streams.
这将告诉系统对tee命令使用无缓冲I/O。因此,当一些输入到来时,所有产出将立即成为更新。
如果您关心两个流的内容顺序,请参阅@ed-morton对类似问题的回答,这里。