web-dev-qa-db-fra.com

Combinez la sortie de deux commandes dans bash

Est-il possible de combiner la sortie de ces deux commandes?

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

Aucune des commandes ne se termine donc je ne sais pas comment procéder.

98
chovy

J'ai fini par faire cela, les autres suggestions n'ont pas fonctionné, car le 2e commandement a été tué ou n'a jamais été exécuté.

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
}
2
chovy

Vous pouvez combiner deux commandes en les regroupant avec { }:

{ command1 & command2; }

jusqu'à présent, vous pouvez rediriger le groupe vers un fichier (dernier ; avant } est obligatoire):

{ command1 & command2; } > new_file

si vous souhaitez séparer STDOUT et STDERRen deux fichiers:

{ command1 & command2; } > STDOUT_file 2> STDERR_file
124
Gilles Quenot

Plus généralement, il est possible d'utiliser un sous-shell ou un groupe de commandes et de rediriger la sortie de l'ensemble du groupe à la fois.

Code:

( command1 ; command2 ; command3 ) | cat

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

La principale différence entre les deux est que le premier fractionne un processus enfant, tandis que le second fonctionne dans le contexte du shell principal. Cela peut avoir des conséquences sur la définition et l'utilisation de variables et d'autres paramètres d'environnement, ainsi que sur les performances.

N'oubliez pas que la parenthèse fermante dans le groupe de commandes (et les fonctions) doit être séparée du contenu par un point-virgule ou une nouvelle ligne. Ceci est dû au fait "}" est en fait une commande (mot-clé) qui lui est propre et doit être traité comme tel.

56
j9s

Jusqu'à présent, la plupart des solutions traitent mal le problème des lignes partielles. Supposons une seconde que les programmes sont:

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

Lorsque vous les exécutez en parallèle, vous voulez que la sortie ait des lignes complètes de as suivies de lignes complètes de bs. Ce que vous faites pas voulez, c'est que as et bs se mélangent sur la même ligne (tr -s ab remplace la répétition de as par un seul a, il est donc plus facile de voir ce qui se passe):

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

Si vous utilisez à la place GNU Parallel, vous obtenez de belles lignes complètes propres avec as ou bs mais jamais mélangées:

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

Les nouvelles versions de GNU Parallel évitent même de remplir votre disque: ce qui précède peut fonctionner indéfiniment.

3
Ole Tange

Essaye ça:

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

Pour le cas particulier de la combinaison de plusieurs sorties de commande BASH sur une seule ligne, voici une recette pour exécuter chaque commande tour à tour, en supprimant toutes les nouvelles lignes entre leurs sorties.

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

Comme exemple réel, le code ci-dessous incorporera un ASCII entre deux chaînes d'octets fixes (formant une commande d'impression, dans ce cas))

#   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

(Remarque: cette méthode ne fonctionne que si les commandes se terminent. Pour combiner stdout à partir de commandes qui ne se terminent pas, voir les autres réponses.)

2
Luke

Puisque vous utilisez déjà node, vous voudrez peut-être essayer simultanément

Exécutez plusieurs commandes simultanément. Comme npm run watch-js & npm run watch-less mais mieux.

0
Tamlyn