J'ai le script shell suivant. Le but est de parcourir chaque ligne du fichier cible (dont le chemin est le paramètre d'entrée du script) et de travailler sur chaque ligne. Maintenant, il semble que cela ne fonctionne qu'avec la toute première ligne du fichier cible et s'arrête après le traitement de cette ligne. Y a-t-il un problème avec mon script?
#!/bin/bash
# SCRIPT: do.sh
# PURPOSE: loop thru the targets
FILENAME=$1
count=0
echo "proceed with $FILENAME"
while read LINE; do
let count++
echo "$count $LINE"
sh ./do_work.sh $LINE
done < $FILENAME
echo "\ntotal $count targets"
Dans do_work.sh
, j'exécute quelques ssh
commandes.
bash
shell
ssh
while-loop
bcbishop
la source
la source
source
et simplement quitter ouexec
. Mais ce code n'a pas l'air authentique, l'OP remarquerait que l'écho nécessite-e
d'afficher correctement ledo_work.sh
N'exécuterssh
par hasard?do_work.sh
source et exécuterdo.sh
avecset -x
pour déboguer.Réponses:
Le problème est que
do_work.sh
exécute desssh
commandes etssh
lit par défaut à partir de stdin qui est votre fichier d'entrée. En conséquence, vous ne voyez que la première ligne traitée, carssh
consomme le reste du fichier et votre boucle while se termine.Pour éviter cela, passez l'
-n
option à votressh
commande pour la faire lire à partir de la/dev/null
place de stdin.la source
cat
. On pourrait penser qu'un rongeur en particulier s'en méfierait.while read host ; do $host do_something ; done < /etc/hosts
l'éviterait. C'est tout à fait une bouée de sauvetage, merci!httpie
est une autre commande qui lit STDIN par défaut, et souffrira du même comportement lorsqu'elle sera appelée dans une boucle bash ou fish. Utilisezhttp --ignore-stdin
ou réglez l'entrée standard/dev/null
comme ci-dessus.Plus généralement, une solution de contournement qui n'est pas spécifique à
ssh
est de rediriger l'entrée standard pour toute commande qui pourrait autrement consommer l'while
entrée de la boucle.L'ajout de
</dev/null
est le point crucial ici (bien que les guillemets corrigés soient également quelque peu importants; voir aussi Quand enrouler les guillemets autour d'une variable shell? ). Vous voudrez l'utiliserread -r
sauf si vous avez spécifiquement besoin du comportement hérité légèrement étrange dont vous vous débarrassez-r
.Une autre solution de contournement qui est quelque peu spécifique
ssh
est de s'assurer que toutessh
commande a son entrée standard liée, par exemple en modifiantà la place, lire les commandes d'un document ici, ce qui, de manière pratique (pour ce scénario particulier), lie l'entrée standard de
ssh
pour les commandes:la source
L'option ssh -n empêche la vérification de l'état de sortie de ssh lors de l'utilisation de HEREdoc lors du transfert de la sortie vers un autre programme. L'utilisation de / dev / null comme stdin est donc préférable.
la source
<<EOF
remplace la</dev/null
redirection. La<<
redirection après ledone
est fausse.Cela m'arrivait parce que j'avais
set -e
et ungrep
dans une boucle revenait sans sortie (ce qui donne un code d'erreur non nul).la source