SSH provoca l'arresto del ciclo while


30

Sono finalmente riuscito a ridurre un problema con cui ho lottato per alcune settimane. Uso SSH con "chiavi autorizzate" per eseguire comandi da remoto. Va tutto bene tranne quando lo faccio in un ciclo while. Il ciclo termina dopo aver completato qualsiasi iterazione con un comando ssh.

Per molto tempo ho pensato che fosse una specie di stranezza ksh, ma ora ho scoperto che bash in effetti si comporta in modo identico.

Un piccolo programma di esempio per riprodurre il problema. Questo è distillato da un'implementazione più ampia che prende istantanee e le replica tra i nodi in un cluster.

#!/bin/bash

set -x

IDTAG=".*zone"
MARKER="mark-$(date +%Y.%m.%d.%H.%M.%S)"
REMOTE_HOST=sol10-target
ZFSPARENT=rpool

ssh $REMOTE_HOST zfs list -t filesystem -rHo name,mounted $ZFSPARENT | grep "/$IDTAG    " > /tmp/actionlist

#for RMT_FILESYSTEM in $(cat /tmp/actionlist)
cat /tmp/actionlist | while read RMT_FILESYSTEM ISMOUNTED
do
   echo ${RMT_FILESYSTEM}@${MARKER}
   [ "$ISMOUNTED" = "yes" ] && ssh $REMOTE_HOST zfs snapshot -r ${RMT_FILESYSTEM}@${MARKER}
   echo Remote Command Return Code: $?
done

(Nota che c'è un carattere TAB nell'espressione di ricerca grep secondo la definizione del comportamento dell'elenco "-H" dell'elenco zfs.)

Il mio esempio ha alcuni filesystem ZFS per il root in cui tutte le "zone" hanno il loro file system root su un set di dati chiamato simile a

POOL / zone / app1zone
POOL / zone / gruppo2 / app2zone

eccetera.

Il ciclo precedente dovrebbe creare un'istantanea per ciascuno dei set di dati selezionati, ma al suo posto funziona solo sul primo e quindi esce.

Che il programma trovi il giusto numero di set di dati può essere facilmente confermato controllando il file "/ tmp / actionlist" dopo che lo script esiste.

Se il comando ssh viene sostituito, ad esempio, da un comando echo, il ciclo scorre attraverso tutte le righe di input. O il mio preferito - anteponi "echo" al comando offensivo.

Se uso invece un ciclo for, allora funziona anche, ma a causa delle dimensioni potenziali dell'elenco di set di dati ciò potrebbe causare problemi con la lunghezza massima della riga di comando estesa.

Ora sono sicuro al 99,999% che solo quei loop con comandi ssh in essi mi danno problemi!

Si noti che l'iterazione in cui viene eseguito il comando ssh, completa! È come se i dati inseriti nel ciclo while si perdessero improvvisamente ... Se le prime poche righe di input non eseguono un comando ssh, il ciclo continua fino a quando non esegue effettivamente il comando SSH.

Sul mio laptop su cui sto testando questo ho due VM Solaris 10 con solo circa due o tre set di dati di esempio, ma lo stesso sta accadendo sui grandi sistemi SPARC in cui questo dovrebbe funzionare, e ci sono molti set di dati.


7
SSH potrebbe leggere dall'input standard, divorando il tuo actionlist. Prova a reindirizzare l'input standard di ssh su/dev/null
BatchyX il

Ci proverò. Voglio aggiungere che mettere ssh in un wrapper non aiuta ....
Johan,

Hai ragione. Come potrei non vederlo !?
Johan,

@BatchyX Penso che il tuo commento si qualifichi come una risposta.
un CVn il

Sono d'accordo che vorrei "accettare" la risposta, quindi se @BatchyX potrebbe ripubblicarla come tale, lo farò.
Johan,

Risposte:


43

SSH potrebbe leggere dall'input standard, divorando la tua lista di azioni. Prova a reindirizzare l'input standard di ssh su / dev / null:

ssh $REMOTE_HOST zfs snapshot -r ${RMT_FILESYSTEM}@${MARKER} </dev/null

Come regola generale, quando eseguo comandi che possono interferire con l'input standard in un while readciclo stile, mi piace avvolgere l'intero corpo del ciclo tra parentesi graffe:

cat /tmp/uuoc | while read RMT_FILESYSTEM ISMOUNTED
do {
    echo ${RMT_FILESYSTEM}@${MARKER}
    [ "$ISMOUNTED" = "yes" ] && ssh $REMOTE_HOST zfs snapshot -r ${RMT_FILESYSTEM}@${MARKER}
    echo Remote Command Return Code: $?
} < /dev/null; done

3
Doppio fantastico per primo l'uso specifico delle parentesi graffe ... che non ho mai incontrato in 20 anni di sceneggiatura (almeno non che io possa ricordare.) E per l'inferenza uuoc. FWIW (e per mia difesa) a volte faccio un'eccezione e aggiungo dichiarazioni di gatti ridondanti per motivi di leggibilità! Adoro questo forum perché improvvisamente sto imparando di nuovo cose nuove! In particolare mi piace aggiungere reindirizzamenti all'inizio di righe come questo caso, ma su forum che sembrano confondere la questione, facendomi ottenere meno risposte utili!
Johan,

Ho cercato di capire la differenza tra {...} e (...) la pagina man di ksh dice che {...} sono parole chiave speciali riconosciute solo all'inizio di una riga di comando. Ma c'è un'altra differenza ... si ( </tmp/file [ -z "$SOMEVAR" ] && awk '{print "X", $0}' )differenzia per le parentesi graffe. Voglio dire in termini di produzione prodotta, non per il fatto che la parentesi graffa di chiusura deve essere su una nuova linea ...
Johan

5
Inoltre, di OpenSSH ssh ha l' -nopzione che rende (efficace) riavviare la stdin da / dev / null.
Chris Johnsen,

Qualche soluzione alternativa da utilizzare sudocon il comando all'interno del ciclo?
bonh,

Usavo -n da secoli e ad un certo punto ho perso l'abitudine .... e ora so di nuovo perché l'ho fatto, dopo un po 'di tempo a scavare ...
Florian Heigl il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.