2014-04-23 7 views
0

Y at-il une différence entre:Pipe un script dans bash?

$ bash ~/script.sh 

et:

$ cat ~/script.sh | bash 

Ils semblent se comporter un peu différemment, et je ne peux pas comprendre tout à fait ce qui se passe. Mon script.sh contient plusieurs lignes de bash, mais il semble s'interrompre tôt quand je le redirige vers bash (mais court quand j'écris le script directement).

Quelle est la différence dans l'exécution du script de ces deux manières?

De plus, lorsque j'utilise <, le comportement est le même que le premier exemple (runs à la fin):

bash <(~/script.sh) 

Le script est le long des lignes de

set -eux 
ssh CLUSTER_0_SERVER_0 "do_something" || ssh CLUSTER_0_SERVER_1 "do_something" 
ssh CLUSTER_1_SERVER_0 "do_something" || ssh CLUSTER_1_SERVER_1 "do_something" 
+0

Veuillez également fournir le contenu du fichier 'script.sh'. –

+0

Le script est assez simple, fait un 'set -eux' puis quelques lignes de' ssh CLUSTER_0_SERVER_0 "do_something" || ssh CLUSTER_0_SERVER_1 "faire_quelque chose" 'et ensuite pour un autre ensemble de machines' ssh CLUSTER_1_SERVER_0 "faire_quelquechose" || ssh CLUSTER_1_SERVER_1 "do_squechose" 'etc (fondamentalement, il ssh est dans un groupe de clusters et essaye d'exécuter do_something sur une machine dans chaque cluster jusqu'à un succès, alors il devrait passer au cluster suivant). J'ai été troublé par la différence de comportement entre l'exécution directe et la redirection du script vers bash sur son stdin. –

+3

'bash <(foo.sh)' est ** entièrement ** différent de 'bash

Répondre

2

Vos moyens de exécuter le même script sont tous différents dans sémantique.

Voir par exemple ce script simple:

#!/bin/bash 
echo $$ 
ssh 127.0.0.1 
echo $$ 

Son exécution sera directement exécuter toutes les lignes à l'intérieur et les deux echo invocations imprimeront le même PID: tout est un processus qui exécute les commandes dans le script , un par un. L'exécution par cat ./script.sh | bash crée deux processus différents au début: un pour faire le cat et un pour bash. Cependant, lorsque l'interpréteur bash lit et exécute la commande ssh vous obtenez une erreur (si le ssh n'est pas configuré pour ne pas imprimer):

Pseudo-terminal will not be allocated because stdin is not a terminal 

et vous obtenez une connexion à la machine et il quitte immédiatement, tue le processus en cours. Ainsi, la seconde valeur est un PID différent. Dans votre cas, vous avez deux commandes ssh liées par un opérateur conditionnel. Cependant, puisque après le premier l'interpréteur est tué il n'y a aucun moyen que la deuxième commande soit exécutée. C'est pourquoi seules les commandes *_SERVER_0ssh seront exécutées.

Le troisième cas fonctionne mais seulement par erreur. La construction <(cmd) signifie l'exécution de cmd et la transmission de sa sortie en tant qu'argument de fichier à l'appelant. Dans votre cas, le script n'imprime rien, c'est pourquoi vous ne voyez aucune erreur. L'exécution du script exemple, vous obtiendrez des erreurs telles que:

/dev/fd/63: line 1: 29355: command not found 

Le quatrième cas (suggéré dans les commentaires) bash < script est la même chose que cat script | bash.

Le bon moyen d'exécuter des scripts bash est par bash script ou ./script (et tralala). Si vous souhaitez exécuter les instructions dans le même processus, vous pouvez également utiliser . script (source) Tous les autres peuvent fonctionner ou non, en fonction de certains effets secondaires chanceux (en général, ils ne devraient pas fonctionner).

+1

ou '. ./script', qui est "propre" mais a une sémantique différente. – rici

+0

Oui, mais je ne l'ai pas mentionné juste à cause de la sémantique différente. –