要将标准输出重定向到 Bash 中的截断文件,我知道要使用:
cmd > file.txt
要在 Bash 中重定向标准输出,附加到文件,我知道使用:
cmd >> file.txt
要将标准输出和标准错误都重定向到截断的文件,我知道要使用:
cmd &> file.txt
如何重定向附加到文件的标准输出和标准错误?cmd &>> file.txt
对我不起作用。
cmd >>file.txt 2>&1
Bash 从左到右执行重定向,如下所示:
>>file.txt
:以附加模式打开file.txt
并重定向stdout
到那里。2>&1
:重定向stderr
到“stdout
当前要去的地方”。在这种情况下,这是一个以附加模式打开的文件。换句话说,&1
重用当前使用的文件描述符stdout
。有两种方法可以做到这一点,具体取决于您的 Bash 版本。
经典且可移植的(Bash pre-4)方式是:
cmd >> outfile 2>&1
从Bash 4开始的一种不可移植的方式是
cmd &>> outfile
(类似于&> outfile
)
为了获得良好的编码风格,您应该
如果您的脚本已经开始#!/bin/sh
(无论是否有意),那么 Bash 4 解决方案以及通常任何特定于 Bash 的代码都不是要走的路。
还要记住,Bash 4&>>
只是更短的语法——它没有引入任何新功能或类似的东西。
语法(除了其他重定向语法)在Bash 黑客 wiki中描述。
在 Bash 中,您还可以明确指定重定向到不同的文件:
cmd >log.out 2>log_error.out
附加将是:
cmd >>log.out 2>>log_error.out
这应该可以正常工作:
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
),但这种方法对我来说感觉更自然和易于理解:
此外,括号消除了任何顺序的歧义,特别是如果您想将标准输出和标准错误传递给另一个命令。
为了避免启动子shell,您可以使用花括号而不是括号来创建组命令:
{ cmd 2>&1; } >> file.txt
(请注意,终止 group 命令需要分号(或换行符)。)
您可以从脚本本身计划重定向:
#!/bin/bash
exec 1>>logfile.txt
exec 2>&1
/bin/ls -ld /tmp /tnt
运行它会创建/追加logfile.txt
,包含:
/bin/ls: cannot access '/tnt': No such file or directory
drwxrwxrwt 2 root root 4096 Apr 5 11:20 /tmp
您可以创建两个不同的日志文件,附加到一个整体日志并重新创建另一个最后一个日志:
#!/bin/bash
if [ -e last.log ] ;then
mv -f last.log last.old
fi
exec 1> >(tee -a overall.log /dev/tty >last.log)
exec 2>&1
ls -ld /tnt /tmp
运行此脚本将
last.log
已经存在,将它们重命名为(如果存在则last.old
覆盖)。last.old
last.log
.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.log
上次运行日志文件last.err
上次运行错误文件lastlog.old
以前的运行日志文件lasterr.old
上一次运行错误文件overall.log
附加的整体日志文件overall.err
附加的整体错误文件combined.log
附加了整体错误和日志组合文件。stdbuf
:如果你打算在交互式shell 中使用它,你必须告诉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.old
exec 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