SSH menyebabkan loop sementara berhenti

30

Saya akhirnya berhasil memecahkan masalah yang telah saya perjuangkan selama beberapa minggu. Saya menggunakan SSH dengan "kunci resmi" untuk menjalankan perintah dari jarak jauh. Semuanya baik-baik saja kecuali ketika saya melakukannya dalam loop sementara. Loop berakhir setelah menyelesaikan iterasi dengan perintah ssh.

Untuk waktu yang lama saya pikir ini adalah semacam keanehan ksh, tetapi saya sekarang menemukan bahwa bash sebenarnya berperilaku identik.

Program sampel kecil untuk mereproduksi masalah. Ini didistilasi dari implementasi yang lebih besar yang mengambil snapshot dan mereplikasi mereka di antara node dalam sebuah 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

(Perhatikan ada karakter TAB dalam ekspresi pencarian grep sesuai definisi perilaku opsi "-H" dari daftar zfs.)

Sampel saya memiliki beberapa sistem file ZFS untuk root di mana semua "zona" memiliki sistem file root pada dataset bernama mirip dengan

POOL / zona / app1zone
POOL / zona / group2 / app2zone

dll.

Loop di atas harus membuat snapshot untuk masing-masing set data yang dipilih, tetapi sebagai gantinya hanya beroperasi pada yang pertama dan kemudian keluar.

Bahwa program menemukan jumlah dataset yang tepat dapat dengan mudah dikonfirmasi dengan memeriksa file "/ tmp / actionlist" setelah skrip ada.

Jika perintah ssh digantikan oleh, misalnya, perintah gema, maka loop berulang melalui semua jalur input. Atau favorit saya - tambahkan "echo" ke perintah yang menyinggung.

Jika saya menggunakan for for sebagai ganti maka itu juga berfungsi, tetapi karena ukuran potensial dari daftar dataset ini dapat menyebabkan masalah dengan panjang baris perintah diperluas maksimum.

Saya sekarang 99,999% yakin bahwa hanya loop dengan perintah ssh di dalamnya memberi saya masalah!

Perhatikan bahwa iterasi di mana perintah ssh berjalan, selesai! Seolah-olah data yang dimasukkan ke loop sementara tiba-tiba hilang ... Jika beberapa baris input pertama tidak melakukan perintah ssh, maka loop berjalan hingga benar-benar menjalankan perintah SSH.

Di laptop saya di mana saya menguji ini saya memiliki dua Solaris 10 VM dengan hanya sekitar dua atau tiga dataset sampel, tetapi hal yang sama terjadi pada sistem SPARC besar di mana ini dimaksudkan untuk ditayangkan, dan ada banyak dataset.

Johan
sumber
7
SSH mungkin membaca dari input standar, memakan Anda actionlist. Cobalah untuk mengarahkan input standar ssh ke/dev/null
BatchyX
Saya akan mencobanya. Saya ingin menambahkan bahwa menempatkan ssh di bungkus tidak membantu ....
Johan
Anda benar. Bagaimana mungkin aku tidak melihatnya !?
Johan
@ BatchyX Saya pikir komentar Anda memenuhi syarat sebagai jawaban.
CVn
Saya setuju saya ingin "menerima" jawabannya jadi jika @BatchyX dapat memposting ulang dengan demikian saya akan melakukannya.
Johan

Jawaban:

43

SSH mungkin membaca dari input standar, memakan daftar tindakan Anda. Cobalah untuk mengarahkan input standar ssh ke / dev / null:

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

Sebagai aturan umum, ketika menjalankan perintah yang dapat mengganggu input standar di bawah while read-style loop, saya suka membungkus seluruh loop body menjadi braces:

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
BatchyX
sumber
3
Ganda dahsyat untuk pertama kali penggunaan khusus kurung kurawal ... yang saya miliki dalam 20 tahun penulisan tidak pernah menemui (paling tidak saya tidak bisa mengingatnya.) Dan untuk kesimpulan uuoc. FWIW (dan dalam pembelaan saya sendiri) saya terkadang membuat pengecualian dan menambahkan pernyataan kucing yang berlebihan untuk dibaca! Saya suka forum ini karena saya tiba-tiba belajar hal baru lagi! Khususnya saya ingin menambahkan arahan ke awal baris seperti kasus ini, tetapi di forum yang tampaknya membingungkan masalah ini, menyebabkan saya mendapatkan lebih sedikit tanggapan yang bermanfaat!
Johan
Saya telah mencoba mencari tahu perbedaan antara {...} dan (...) ksh man page mengatakan {...} adalah kata kunci khusus yang hanya dikenali pada awal baris perintah. Tapi ada perbedaan lain ... ( </tmp/file [ -z "$SOMEVAR" ] && awk '{print "X", $0}' )berbeda sama dengan kurung kurawal. Maksud saya dalam hal output yang dihasilkan, bukan tentang fakta bahwa kurung kurawal penutupan harus pada baris baru ...
Johan
5
Juga, ssh OpenSSH memiliki -nopsi yang membuatnya (secara efektif) membuka kembali stdin dari / dev / null.
Chris Johnsen
Adakah solusi untuk menggunakan sudodengan perintah di dalam loop?
bonh
Saya dulu menggunakan -n sejak berabad-abad dan pada beberapa titik kehilangan kebiasaan .... dan sekarang saya lagi tahu mengapa saya melakukannya, setelah beberapa saat dihabiskan menggali ...
Florian Heigl