结合bash中两个命令的输出


81

是否可以合并这两个命令的输出?

node ~/projects/trunk/index.js 
python ~/projects/trunk/run.py run

这两个命令都不退出,所以我不确定如何执行此操作。


3
如果程序没有完成,大概是它们连续写输出了吗?您想如何处理它们的输出?交错线,...?为什么要这样做?
vonbrand

2
node命令输出不多,但仍需要运行。python一个输出所有请求,我想捕获两个请求并在同一shell窗口中观看它们。
chovy

Answers:


108

您可以通过将两个命令分组在一起来组合两个命令{ }

{ command1 & command2; }

到目前为止,您可以将组重定向到文件(去年;之前}是必须的):

{ command1 & command2; } > new_file

如果要分开STDOUTSTDERR分成两个文件:

{ command1 & command2; } > STDOUT_file 2> STDERR_file

3
没关系,他们的程序没有完成。'tail -f'也不“完成”,但这仍然有效并且将两个程序的输出组合在一起。同样适用于两个以上的命令。^ c退出只会杀死分组的命令之一。不过,您必须手动杀死对方。
SuperMagic

5
好像你缺乏最后;之前},它是强制性的!
吉尔斯·奎诺

2
请注意:这不会保留整行!随着行的一部分分开并相互混合,您将获得不可靠的输出。您可以尝试使用此方法,{ yes {1..20} & yes {1..20}; } | grep -v '^1 2 3'如果没有断线,理想情况下不会打印任何内容。
antak

8
我宁愿用&&代替&command1 & command2-这将在后台运行command1并立即启动command2,从而并行运行两个命令并弄乱输出。 command1 && command2-这将运行command1(在前台),然后,如果command1成功,则运行command2。
DUzun

1
@DUzun OP表示没有命令退出,因此使用您的解决方案,第二条命令将永远不会运行
Zoey Hewll '18

50

更一般而言,可以使用子外壳程序或命令分组,并立即重定向整个组的输出。

码:

( command1 ; command2 ; command3 ) | cat

{ command1 ; command2 ; command3 ; } > outfile.txt

两者之间的主要区别在于,第一个拆分子进程,而第二个拆分在主shell上下文中运行。这可能对变量的设置和使用以及其他环境设置以及性能产生影响。

不要忘记,命令分组(和函数)中的右括号必须用分号或换行符与内容分开。这是因为"}"实际上它本身就是一个命令(关键字),必须将其视为一个。


2
从重定向( )也可以。
muru

2
}根本不是命令。这是保留字。同样适用{。我平时写这样的列表,像这样:{ command1;command2;} > outfile.txt。您可以在分号后添加空格,但这不是必需的。不过,后面的空格{ 必要的。
通配符

1
请注意:这不会保留整行!随着行的一部分分开并相互混合,您将获得不可靠的输出。您可以尝试使用此方法,( yes {1..20} & yes {1..20}; ) | grep -v '^1 2 3'如果没有断线,理想情况下不会打印任何内容。(H / t至@antak)。
Ole Tange's

3
有时,您只想在command1成功的情况下运行command2:( command1 && command2 && command3 ) | cat
DUzun

我更喜欢将圆括号()与大括号一起使用,{}它作为背景进度运行,然后您必须处理该大括号中的输出。也管道到猫`| cat`是比`> / dev / stdout`更好的替代品
DarkMukke

2

我最终还是这样做了,其他建议没有用,因为第二条命令被杀死或从未执行过。

alias app () {
    nohup python ~/projects/trunk/run.py run 1>/tmp/log 2>&1 &
    echo $! > /tmp/api.pid
    nohup node ~/projects/trunk/index.js 1>/tmp/log 2>&1 &
    echo $! > /tmp/client.pid
    tail -f /tmp/log
}

1
注意:如果两个进程试图“同时”写入文件,则可能会导致I / O错误。
Djizeus

2
可以指定2个不同的日志文件,并且可以这样做,tail -f *.log尽管我从未将2个不同的进程写入同一日志文件视为问题。
chovy

@chovy:您能在这里将您的问题作为问题写吗……这很有用
Abdennour TOUMI

1
请注意:这不会保留整行!随着行的一部分分开并相互混合,您将获得不可靠的输出。您可以使用command1 = yes {1..20}command2 = 尝试此操作,yes {1..20}并将组合的输出通过管道| grep -v '^1 2 3'传输,如果没有折断行,则理想情况下将不输出任何内容。(H / t至@antak)。
Ole Tange's

最重要的是,如果数据量很大,则磁盘可能已满。
奥莱·坦格

2

尝试这个:

paste $(node ~/projects/trunk/index.js) $(python ~/projects/trunk/run.py run) > outputfile

1
“粘贴”是做什么的?
chovy

@chovy,请参见此处:techrepublic.com/article/…不过, 不确定在这种情况下是否可以使用。
FixMaker

我认为粘贴在这里不合适,因为粘贴是为了使列彼此相邻
Bernhard

确实是@Bernhard。但是未在要求中指定
frogstarr78

@ frogstarr78我认为这不太可能是他想要的,但是您说的没错,未指定。
伯恩哈德

1

到目前为止,大多数解决方案都无法很好地处理分线问题。假设这些程序是:

cmd1() {
    perl -e 'while(1) { print "a"x3000_000,"\n"}'
}
export -f cmd1
cmd2() {
    perl -e 'while(1) { print "b"x3000_000,"\n"}'
}
export -f cmd2

当并行运行它们时,您希望输出具有as的完整行,然后是s的完整行b。您想要的是as和bs在同一行上混合(tr -s aba单个代替重复的s a,因此更容易看到发生了什么):

# This is bad - half lines are mixed
$ (cmd1 & cmd2 ) | tr -s ab
bababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababa
ababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababab

如果改为使用GNU Parallel,则可以使用as或bs 获得整洁的完整行,但绝不能混合使用:

$ parallel --line-buffer ::: cmd1 cmd2 | tr -s ab
a
a
b
b
b
b
a

较新版本的GNU Parallel甚至可以避免填满磁盘:上面的代码可以永久运行。


0

既然你已经在使用node,你可能想尝试同时

同时运行多个命令。喜欢npm run watch-js & npm run watch-less但更好。


0

对于将多个BASH命令输出组合到一行的特殊情况,以下是依次运行每个命令,删除其输出之间的所有换行符的方法。

(echo 'ab' && echo 'cd' && echo 'ef') | tr -d '\n'
>>> abcdef

作为一个实际示例,下面的代码将在两个固定字节串之间嵌入ASCII消息(在这种情况下,形成打印命令)

#   hex prefix           encode a message as hex    hex suffix    | strip newline | hex to binary | (then, for example, send the binary over a TCP connection)
(echo '1b40' && echo "Test print #1" | xxd -p && echo '1d564103') | tr -d '\n'    | xxd -r -p     | nc -N 192.168.192.168 9100

(注意:此方法仅在命令退出时有效。有关从不退出的命令中组合标准输出的信息,请参见其他答案。)


(1)请显示第二条命令的(预期)输出。(2)请说明OP将如何使用此技术来解决他的问题。
斯科特

1)第二个命令的输出是非ASCII二进制,因此显示它不会有用。2)OP可能会在2013年至今解决他的特定问题。现在,这个问题实际上是组合多个Bash命令的stdout的参考,因此,我相信一种将它们组合在一行上的技术是在这里提到的有用的“食谱”(因为我来这里是为了寻找它,却找不到它)。
路加福音
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.