要将标准输出重定向到Bash中的截断文件,我知道要使用:
cmd > file.txt
要重定向Bash中的标准输出,将其附加到文件,我知道要使用:
cmd >> file.txt
要将标准输出和标准错误重定向到截断的文件,我知道可以使用:
cmd &> file.txt
如何将标准输出和标准错误附加重定向到文件?cmd&>>file.txt对我不起作用。
要将标准输出重定向到Bash中的截断文件,我知道要使用:
cmd > file.txt
要重定向Bash中的标准输出,将其附加到文件,我知道要使用:
cmd >> file.txt
要将标准输出和标准错误重定向到截断的文件,我知道可以使用:
cmd &> file.txt
如何将标准输出和标准错误附加重定向到文件?cmd&>>file.txt对我不起作用。
当前回答
在Bash 4(以及Z外壳(zsh)4.3.11)中:
cmd &>> outfile
只是开箱即用。
其他回答
在Bash中,您还可以明确指定指向不同文件的重定向:
cmd >log.out 2>log_error.out
附录应为:
cmd >>log.out 2>>log_error.out
cmd >>file.txt 2>&1
Bash从左到右执行重定向,如下所示:
>>file.txt:以追加模式打开file.txt并将stdout重定向到那里。2> &1:将stderr重定向到“stdout当前所在位置”。在本例中,这是一个以追加模式打开的文件。换句话说,&1重用stdout当前使用的文件描述符。
这应该很好:
your_command 2>&1 | tee -a file.txt
它会将所有日志存储在file.txt中,并将其转储到终端中。
有两种方法可以做到这一点,具体取决于您的Bash版本。
经典的便携(Bash pre-4)方式是:
cmd >> outfile 2>&1
从Bash 4开始的一个不可移植的方法是
cmd &>> outfile
(模拟输出文件)
为了获得良好的编码风格,您应该
决定是否需要考虑可移植性(然后使用经典方法)决定是否需要考虑Bash pre-4的可移植性(然后使用经典方法)无论使用哪种语法,都不要在同一个脚本中更改它(混淆!)
如果脚本已经以#/bin/sh(无论是否有意),那么Bash 4解决方案以及任何Bash特定的代码都是不可行的。
还要记住,Bash 4&>>只是一个较短的语法,它没有引入任何新功能或类似的东西。
该语法(除其他重定向语法外)在Bash hackers wiki中进行了描述。
脚本本身的重定向
您可以从脚本本身计划重定向:
#!/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
Or
#!/bin/bash
exec 1>>logfile.txt
exec 2>>errfile.txt
/bin/ls -ld /tmp /tnt
创建或将标准输出附加到logfile.txt,并创建或将错误输出附加到errfile.txt。
记录到许多不同的文件
您可以创建两个不同的日志文件,附加到一个整体日志,然后重新创建另一个最后的日志:
#!/bin/bash
if [ -e lastlog.txt ] ;then
mv -f lastlog.txt lastlog.old
fi
exec 1> >(tee -a overall.log /dev/tty >lastlog.txt)
exec 2>&1
ls -ld /tnt /tmp
运行此脚本将
如果lastlog.txt已经存在,请将其重命名为lastlog.old(如果存在,则覆盖lastlog.ord)。创建新的lastlog.txt。将所有内容追加到overall.log将所有内容输出到终端。
简单日志和组合日志
#!/bin/bash
[ -e lastlog.txt ] && mv -f lastlog.txt lastlog.old
[ -e lasterr.txt ] && mv -f lasterr.txt lasterr.old
exec 1> >(tee -a overall.log combined.log /dev/tty >lastlog.txt)
exec 2> >(tee -a overall.err combined.log /dev/tty >lasterr.txt)
ls -ld /tnt /tmp
所以你有
lastlog.txt上次运行日志文件lasterr.txt上次运行错误文件lastlog.old上次运行日志文件lasterr.old上次运行错误文件overall.log附加的总体日志文件overall.err附加的总体错误文件combined.log附加了总体错误和日志组合文件。仍输出到终端
对于交互式会话,请使用stdbuf:
关于Fonic的评论,经过一些测试,我不得不同意:对于tee,stdbuf是无用的。但是
如果您计划在*interactive*shell中使用此选项,则必须告诉“tee”不要缓冲他的输入/输出:#源代码以多日志记录会话[-e lasterr.txt]&&mv-f lasterr.txt lasterr.old[-e lastlog.txt]&&mv-f lastlog.txt lastlog.oldexec 2>>(exec stdbuf-i0-o tee-a overall.err combined.log/dev/tty>lasterr.txt)exec 1>(exec stdbuf-i0-o tee-a overall.log combined.log/dev/tty>lastlog.txt)一旦找到了这个,您可以尝试:ls-ld/tnt/tmp
更复杂的样本
从我关于如何将Unix时间戳转换为日期字符串的3个备注中
我使用了更复杂的命令来实时解析和重新组装squid的日志:由于每一行都以UNIX EPOCH开头,以毫秒为单位,所以我将这一行拆分为第一个点,在EPOCH SECONDS之前添加@符号将它们传递给date-f-+%f\%T,然后使用paste-d重新组合date的输出和带有点的行的其余部分。。
exec {datesfd}<> <(:)
tail -f /var/log/squid/access.log |
tee >(
exec sed -u 's/^\([0-9]\+\)\..*/@\1/'|
stdbuf -o0 date -f - +%F\ %T >&$datesfd
) |
sed -u 's/^[0-9]\+\.//' |
paste -d . /dev/fd/$datesfd -
带日期,需要stdbuf。。。
有关exec和stdbuf命令的一些解释:
使用$(…)或<(…)运行fork是通过运行subshell来完成的,它将在另一个subshell(subshell)中执行二进制文件。exec命令告诉shell脚本中没有其他命令要运行,因此二进制(stdbuf…tee)将作为替换进程在同一级别执行(不需要为运行另一个子进程保留更多内存)。从bash的手册页(man-P'less+/^\*exec\'bash):exec[-cl][-a名称][命令[参数]]如果指定了命令,它将替换壳未创建新流程。。。。这不是真正需要的,但可以减少系统占用空间。从stdbuf的手册页:名称stdbuf-使用修改的缓冲运行COMMAND其标准流的操作。这将告诉系统对tee命令使用无缓冲I/O。因此,当一些输入即将到来时,所有输出都将立即更新。