Saya memiliki skrip shell berikut. Tujuannya adalah untuk melakukan perulangan melalui setiap baris dari file target (yang jalurnya adalah parameter input ke skrip) dan bekerja pada setiap baris. Sekarang, tampaknya hanya berfungsi dengan baris pertama di file target dan berhenti setelah baris itu diproses. Apakah ada yang salah dengan skrip saya?
#!/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"
Di do_work.sh
, saya menjalankan beberapa ssh
perintah.
bash
shell
ssh
while-loop
bcbishop.dll
sumber
sumber
source
dan hanya keluar atauexec
. Tetapi kode ini tidak terlihat asli, OP akan melihat bahwa gema memerlukan-e
untuk menampilkan umpan baris dengan benar ...do_work.sh
dijalankanssh
secara kebetulan?do_work.sh
sumbernya dan juga menjalankando.sh
denganset -x
untuk debug.Jawaban:
Masalahnya adalah
do_work.sh
menjalankanssh
perintah dan secara defaultssh
membaca dari stdin yang merupakan file input Anda. Akibatnya, Anda hanya melihat baris pertama diproses, karenassh
menggunakan sisa file dan loop sementara Anda berakhir.Untuk mencegah hal ini, berikan
-n
opsi kessh
perintah Anda untuk membuatnya dibaca/dev/null
alih-alih stdin.sumber
cat
. Anda akan mengira hewan pengerat khususnya akan waspada terhadap hal ini.while read host ; do $host do_something ; done < /etc/hosts
akan menghindarinya. Itu cukup menyelamatkan hidup, terima kasih!httpie
adalah perintah lain yang membaca STDIN secara default, dan akan mengalami perilaku yang sama saat dipanggil di dalam loop bash atau fish. Gunakanhttp --ignore-stdin
atau setel input standar/dev/null
seperti di atas.Secara lebih umum, solusi yang tidak spesifik
ssh
adalah dengan mengalihkan input standar untuk perintah apa pun yang mungkin menggunakanwhile
input loop.Penambahan
</dev/null
adalah poin krusial di sini (meskipun kutipan yang dikoreksi juga agak penting; lihat juga Kapan membungkus kutipan di sekitar variabel shell? ). Anda akan ingin menggunakanread -r
kecuali Anda secara khusus membutuhkan perilaku warisan yang sedikit aneh yang Anda dapatkan tanpa-r
.Jenis solusi lain yang agak spesifik
ssh
adalah memastikan setiapssh
perintah memiliki input standar yang terikat, misalnya dengan mengubahuntuk membaca perintah dari dokumen di sini, yang dengan mudah (untuk skenario khusus ini) mengikat input standar
ssh
untuk perintah:sumber
Opsi ssh -n mencegah pengecekan status keluar dari ssh saat menggunakan HEREdoc saat menyalurkan output ke program lain. Jadi penggunaan / dev / null sebagai stdin lebih disukai.
sumber
<<EOF
menimpa</dev/null
redirection. The<<
redirection setelahdone
salah.Ini terjadi pada saya karena saya telah
set -e
dangrep
dalam satu loop kembali tanpa output (yang memberikan kode kesalahan bukan nol).sumber