Is it possible to combine output from these two commands?
node ~/projects/trunk/index.js
python ~/projects/trunk/run.py run
Neither command exits so I'm not sure how to do this.
Is it possible to combine output from these two commands?
node ~/projects/trunk/index.js
python ~/projects/trunk/run.py run
Neither command exits so I'm not sure how to do this.
You can combine two commands by grouping it with { }
:
{ command1 & command2; }
so far, you can redirect the group to a file (last ;
before }
is mandatory), and the space between the open and closing bracket too.
{ command1 & command2; } > new_file
if you want to separate STDOUT
and STDERR
in two files :
{ command1 & command2; } > STDOUT_file 2> STDERR_file
If you don't want to run the first command in the background, use this form :
{ command1; command2; }
or
{ command1 && command2; }
to run the second command only if the first is a success
cat
and grep --line-buffered
. also, SuperMagic's statement was true for me, ^c only killed one of the commands, rest stayed bg'd.
– Mike D
Mar 27 '16 at 11:26
{ yes {1..20} & yes {1..20}; } | grep -v '^1 2 3'
which ideally won't print anything if lines aren't broken.
– antak
Jan 17 '17 at 01:41
&&
instead of &
!
command1 & command2
- this runs command1 in background and starts command2 immediately, thus running both commands in parallel and messing up the output.
command1 && command2
- this runs command1 (in foreground) and then, if command1 succedded, runs command2.
command1
and command2
are just placeholders - replace them with real commands that produce some output.
As an example: { echo 123 && echo 321; } > /tmp/test
– DUzun
Jun 01 '18 at 05:19
{ yes && echo no }
will never print "no"
– Zoey Hewll
Jun 01 '18 at 05:42
{ yes; echo no; }
in this case will output 'no' after you press Ctrl+C. { yes & no; }
will scrumble output of yes
with 'no', and most likely 'no' would be on its own line. The right tool for the right task.
– DUzun
Jun 02 '18 at 06:32
More generally, it's possible to use either a subshell or command grouping, and redirect the output of the whole group at once.
Code:
( command1 ; command2 ; command3 ) | cat
{ command1 ; command2 ; command3 ; } > outfile.txt
The main difference between the two is that the first one splits of a child process, while the second one operates in the context of the main shell. This can have consequences regarding the setting and use of variables and other environment settings, as well as performance.
Don't forget that the closing bracket in command grouping (and functions) must be separated from the contents by either a semicolon or a newline. This is because "}"
is actually a command (keyword) of its own, and must be treated like one.
}
isn't a command at all. It's a reserved word. Same goes for {
. I usually write such lists like so: { command1;command2;} > outfile.txt
. You can add spaces after the semicolons but it's not necessary. The space after {
is necessary, though.
– Wildcard
May 06 '16 at 02:45
( yes {1..20} & yes {1..20}; ) | grep -v '^1 2 3'
which ideally won't print anything if lines aren't broken. (H/t to @antak).
– Ole Tange
Nov 15 '17 at 07:36
( command1 && command2 && command3 ) | cat
– DUzun
Apr 05 '18 at 11:08
()
as with the curly brackets {}
it runs as a background progress and then you have to deal with the output from that.
Also pipe to cat | cat
is a nicer alternative then > /dev/stdout
– DarkMukke
Jun 19 '18 at 10:36
Most of the solutions so far deal badly with the partial line problem. Assume for a second that the programs are:
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
When running those in parallel you want the output to have full lines of a
s followed by full lines of b
s. What you do not want is a
s and b
s mixing on the same line (tr -s ab
replaces repeating a
s with a single a
, so it is easier to see what happens):
# This is bad - half lines are mixed
$ (cmd1 & cmd2 ) | tr -s ab
bababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababa
ababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababab
If you instead use GNU Parallel, you get nice clean full lines with either a
s or b
s but never mixed:
$ parallel --line-buffer ::: cmd1 cmd2 | tr -s ab
a
a
b
b
b
b
a
Newer versions of GNU Parallel even avoids filling up your disk: The above can run forever.
Seriously!? Imagine if every utility did this
– peter karasev
Mar 30 '22 at 23:29
For the special case of combining multiple BASH command outputs onto one line, here's a recipe to run each command in turn, removing any newlines between their outputs.
(echo 'ab' && echo 'cd' && echo 'ef') | tr -d '\n'
>>> abcdef
As a real-world example, the code below will embed an ASCII message between two fixed strings of bytes (forming a print command, in this case)
# 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
(Note: this method only works if the commands exit. For combining stdout from commands that don't exit, see other answers.)
The accepted answer’s output might not come in the right order, do not use it if your sources are async (e.g. cat
or curl
)
Use this instead:
cat <(command1) <(command2) <(command3) > output.txt
Real life example:
cat \
<(curl https://stackoverflow.com/humans.txt) \
<(echo -e "\n\nDownloaded from https://stackoverflow.com") \
> output.md
Produces
There's a bunch of humans behind Stack Overflow and the network of Stack Exchange sites. If you'd like to join us check out https://stackoverflow.com/company/work-here
Downloaded from https://stackoverflow.com
I ended up doing this, the other suggestions did not work, as the 2nd command was either killed or never executed.
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
}
tail -f *.log
although I've never seen this as a problem with 2 different processes writing to the same log file.
– chovy
Nov 16 '16 at 20:25
yes {1..20}
command2 = yes {1..20}
and pipe the combined output through | grep -v '^1 2 3'
which ideally won't print anything if lines aren't broken. (H/t to @antak).
– Ole Tange
Nov 15 '17 at 07:38
Since you're already using node
, you may want to try concurrently
Run multiple commands concurrently. Like
npm run watch-js & npm run watch-less
but better.
Parallel vs Serial execution: It is important to highlight the two different solutions:
Proof / example for (1) vs (2):
$ (echo p1;sleep 6;echo p1-end) && (echo p2;sleep 6;echo p2-end)
p1
p1-end
p2
p2-end
$ (echo p1;sleep 6;echo p1-end) & (echo p2;sleep 6;echo p2-end)
[1] 104629
p1
p2
p1-end
p2-end
Try this:
paste $(node ~/projects/trunk/index.js) $(python ~/projects/trunk/run.py run) > outputfile