如何将多个命令的输出重定向到一个文件?

23

我有一个包含以下两个命令的Bash脚本:

ssh host tail -f /some/file | awk ..... > /some/file &

ssh host tail -f /some/file | grep .... > /some/file &

我该如何将这两个命令的输出都重定向到同一个文件中?


2
请记住,如果两个命令都在后台运行,您无法预测来自这两个命令的输出将如何交错在“/some/file”中。 - chepner
3个回答

42

要么使用带有>>的'append',要么使用大括号来包含I/O重定向,或者(偶尔)使用exec

ssh host tail -f /some/file | awk ..... >  /some/file &
ssh host tail -f /some/file | grep .... >> /some/file &
或:
{
ssh host tail -f /some/file | awk ..... &
ssh host tail -f /some/file | grep .... &
} > /some/file
或者:
exec > /some/file
ssh host tail -f /some/file | awk ..... &
ssh host tail -f /some/file | grep .... &

exec执行后,整个脚本的标准输出都会被重定向到/some/file。我很少使用这种技术,通常我改用{ ...; }技术。

注意:在使用花括号时必须小心。我展示的方法可以工作。试图将其压缩成一行需要您将{视为一个命令(例如后跟一个空格),并将}视为另一个命令。在}之前必须有命令终止符-我使用了一个换行符,但是可以使用一个&代表后台或者;代表命令终止符。

因此:

{ command1;  command2;  } >/some/file
{ command1 & command2 & } >/some/file

我还没有解决你为什么在一个远程文件上运行两个独立的tail -f操作,以及为什么不使用awk强大的超级grep来处理所有这些问题——我只解决了如何将两个命令的输入/输出重定向到一个文件的表面问题。


什么都不起作用。我还尝试过 { command1 ; command 2 } > /some/file,但它也不起作用。 - user2864207
3
请注意,使用 { 命令列表;在括号内;} 的单行用法必须以分号结束,正如Jonathan最后一句所示。 - glenn jackman
你必须小心使用括号符号。我展示的代码可以工作。试图将其压缩到一行中(为什么-为什么要将两个独立的管道压缩到一行中?你不尊重可读性或可理解性吗?)需要将 {} 视为一个命令(例如后面加上一个空格)并且在 } 之前添加命令终止符。我使用换行符作为命令终止符,但是 & 用于后台运行或 ; 也可以。 - Jonathan Leffler
1
@PiotrDobrogost:我不确定您需要什么额外的细节。任何标准的Shell教材都应该涵盖这个问题——这是Bourne Shell在80年代早期的一个方面,并延续到了POSIX Shell,因此也是Korn Shell和Bash的一部分。您可以研究shell语言的POSIX规范;您会发现它在那里被编码(但这不是一个容易阅读的文档)。问题和评论中的哪个方面不够清晰? - Jonathan Leffler
1
作为一个新手,这教会了我很多东西。感谢你的帮助。 - Ender Che
显示剩余4条评论

18

请注意,您可以减少SSH调用的次数:

{  ssh host tail -f /some/file | 
     tee >(awk ...) >(grep ...) >/dev/null
} > /some/file &

例子:

{ echo foobar | tee >(sed 's/foo/FOO/') >(sed 's/bar/BAR/') > /dev/null; } > outputfile
cat outputfile 
fooBAR
FOObar

我该如何获取这个进程的 PID? - user2864207
如果你将整个进程放到后台(>outputfile &),pid 将会在 $! 中。 - glenn jackman
是的,但我的ssh在两个for循环内部,$!无法给我正确的进程ID。 - user2864207
你可以直接获取它:ssh_pid=$( pgrep -f "ssh host" ) - glenn jackman

2
最好的解决方法可能是去掉ssh .... | grep ...这一行,并修改另一个命令中的awk脚本,添加你从grep命令获取的功能...这将作为额外的副作用消除任何交错问题。

我无法摆脱ssh.. | grep行。这就是脚本的全部意义。 - user2864207

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接