【问题标题】:how to redirect output of multiple commands to one file如何将多个命令的输出重定向到一个文件
【发布时间】:2013-12-04 00:27:42
【问题描述】:

我有一个 bash 脚本,它有以下两个命令:

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

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

如何将两个命令的输出定向到同一个文件中。

【问题讨论】:

  • 请记住,如果两个命令都在后台运行,您无法预测两个命令的输出将如何在/some/file 中交错。

标签: bash io-redirection


【解决方案1】:

要么对>> 使用“附加”,要么使用大括号来包含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 来处理这一切的问题-我只解决了如何将两个命令的 I/O 重定向到一个文件的表面问题。

【讨论】:

  • 这些都不起作用。我也试过 { command1 ;命令 2 } > /some/file,但它不起作用
  • @user2864207,注意{ list of commands; inside braces; }的单行使用必须以分号结尾,如Jonathan最后一句话所示。
  • 您必须小心使用大括号表示法。我展示的将起作用。试图将它展平到一条线上(为什么 - 为什么要将两条单独的管道展平到一条线上?您不尊重可读性或可理解性吗?)需要您将{ 视为一个命令(后跟例如,一个空格)并且还将} 视为一个命令。在 } 之前必须有一个命令终止符——我使用了换行符,但 & 用于背景或 ; 也可以。
  • @JonathanLeffler 你能指出你上面描述的扁平化到一行的问题将在哪里更详细地解释吗?
  • @PiotrDobrogost:我不确定你在寻找什么额外的细节。任何标准的 shell 教科书都应该涵盖这个问题——它是 80 年代初期 Bourne shell 的一个方面,并被延续到 POSIX shell,因此是 Korn shell 和 Bash 的一部分。您可以研究shell language 的 POSIX 规范;你会发现它在那里编纂(但它并不容易阅读)。问题和评论中的例子哪方面不够清楚?
【解决方案2】:

请注意,您可以减少 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?
  • 如果您将整个事情作为背景 (>outputfile &),则 pid 将位于 $!
  • 是的,但是我的 ssh 在两个 for 循环中,$!没有给我正确的 pids
  • 可以直接获取:ssh_pid=$( pgrep -f "ssh host" )
【解决方案3】:

对此的最佳答案可能是删除ssh .... | grep ... 行,并修改另一个命令中的awk 脚本以添加您从grep 命令获得的功能...

这将消除任何作为额外副作用的交错问题。

【讨论】:

  • 我无法摆脱 ssh .. | grep 行。这就是脚本的全部意义
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-12
  • 1970-01-01
  • 1970-01-01
  • 2013-01-12
  • 1970-01-01
  • 2018-06-07
相关资源
最近更新 更多