GNU/Linux >> Linux Esercitazione >  >> Linux

Ssh provoca l'interruzione del loop?

Sono finalmente riuscito a ridurre un problema con cui ho lottato per alcune settimane. Uso SSH con "chiavi autorizzate" per eseguire comandi in remoto. Tutto va 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 si comporta in effetti in modo identico.

Un piccolo programma di esempio per riprodurre il problema. Questo è distillato da un'implementazione più ampia che acquisisce snapshot e li 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'opzione "-H" dell'elenco zfs.)

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

PISCINA/zone/app1zone
PISCINA/zone/gruppo2/app2zone

ecc.

Il ciclo sopra dovrebbe creare un'istantanea per ciascuno dei set di dati selezionati, ma invece opera solo sul primo e poi 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 è presente.

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

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

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

Nota che l'iterazione in cui viene eseguito il comando ssh viene completata! È come se i dati inseriti nel ciclo while venissero improvvisamente persi... Se le prime righe di input non eseguono un comando ssh, il ciclo continua finché non esegue effettivamente il comando SSH.

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

Correlati:come modificare la shell cron (da sh a bash)?

Risposta accettata:

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

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

Come regola generale, quando si eseguono comandi che possono interferire con l'input standard sotto un while read -style loop, mi piace avvolgere l'intero corpo del loop 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

Linux
  1. Passaggio di variabili nel comando ssh remoto

  2. linux esegue il comando da remoto

  3. Usando e in Bash mentre il ciclo

  4. SSH - Come includere il comando -t nel file ~/.ssh/config

  5. Bash Loop - Come interrompere il ciclo quando premo Control-C all'interno di un comando?

Bash mentre Loop

Comando SSH

Come passare la password al comando SSH in Linux

Il ciclo while negli script della shell

Esempi di Bash For Loop e While Loop

Eseguendo un comando di lunga durata su ssh