(bash) Skrip A, tunggu skrip B, tapi tidak proses anaknya

9

Jadi saya punya scriptA yang tidak:

ssh server1 -- scriptB &
ssh server2 -- scriptB &
ssh server3 -- scriptB &
wait
otherstuffhappens

ScriptB melakukan:

rsync -av /important/stuff/. remoteserver:/remote/dir/.
rsync -av /not/so/important/stuff/. remoteserver:/remote/dir/. &
exit

Hasil yang saya inginkan adalah scriptA akan menunggu semua instance dari scriptB selesai sebelum melanjutkan, yang saat ini terjadi, namun itu juga menunggu rsyncs latar belakang dari hal-hal yang tidak begitu penting. Ini adalah file yang lebih besar yang tidak ingin saya tunggu.

Saya telah membaca Perbedaan antara nohup, ditolak, & & dan mencoba berbagai kombinasi, tetapi saya tidak mendapatkan hasil yang saya cari.

Pada titik ini saya sangat bingung. Bantuan apa pun akan dihargai!

Apoc
sumber

Jawaban:

15

Masalahnya di sini adalah bahwa sshdmenunggu end-of-file pada pipa itu sedang membaca stdout perintah (bukan stderr untuk beberapa alasan, setidaknya dengan versi yang saya uji) dari. Dan pekerjaan latar belakang mewarisi fd ke pipa itu.

Jadi, untuk mengatasinya, arahkan output dari rsyncperintah latar belakang itu ke beberapa file atau /dev/nulljika Anda tidak peduli. Anda juga harus mengarahkan ulang stderr, karena walaupun sshd tidak menunggu pipa yang sesuai, setelah sshdkeluar, pipa tersebut akan rusak sehingga rsyncakan terbunuh jika mencoba menulis pada stderr.

Begitu:

rsync ... > /dev/null 2>&1 &

Membandingkan:

$ time ssh localhost 'sleep 2 &'
ssh localhost 'sleep 2 &'  0.05s user 0.00s system 2% cpu 2.365 total
$ time ssh localhost 'sleep 2 > /dev/null &'
ssh localhost 'sleep 2 > /dev/null &'  0.04s user 0.00s system 12% cpu 0.349 total

Dan:

$ ssh localhost '(sleep 1; ls /x; echo "$?" > out) > /dev/null &'; sleep 2; cat out
141  # ls by killed with SIGPIPE upon writing the error message
$ ssh localhost '(sleep 1; ls /x; echo "$?" > out) > /dev/null 2>&1 &'; sleep 2; cat out
2    # ls exited normally after writing the error on /dev/null instead
     # of a broken pipe
Stéphane Chazelas
sumber
4

Tulis skrip yang merupakan induk dari keduanya, maka Anda dapat dengan mudah mengontrol keduanya . Atau buat saluran komunikasi antara kedua saluran .

Untuk secara khusus mengabaikan pekerjaan latar belakang tertentu Anda dapat menangkap PID ( $!adalah PID pekerjaan latar belakang terakhir) dan wait $pidhanya menunggu pekerjaan itu selesai.

l0b0
sumber
3

The -fbendera untuk sshperbaikan masalah. Diuji pada:

#!/bin/sh -e
echo $$_script__begin
( echo sleeping; sleep 2; echo slept )&
echo $$_script__end

Ketika saya menjalankannya ssh localhost ./script, ia menunggu sampai sleptmuncul. Dengan -fbendera, ia keluar pada echo $$_script__enddan sleptkemudian muncul di latar belakang setelah sshperintah telah kembali.

PSkocik
sumber
2

Ini adalah masalah yang diketahui dari server OpenSSH, yang dideskripsikan dan didiskusikan di hulu bugzilla # 2071 . Dalam bug, ada beberapa solusi yang diusulkan baik di sisi OpenSSH, tetapi juga untuk skrip.

Jika Anda ingin menunggu untuk output dari script, Anda harus menambahkan waitsebelum exitdari scriptBjuga.

Jika Anda tidak peduli dengan hasilnya, gunakan beberapa variasi nohupdan pengalihan IO ke /dev/null, yang akan menyelesaikan masalah dengan cara yang sama.

Jakuje
sumber
1

Anda bisa mencoba ini. $!adalah variabel shell default yang berisi ID proses dari pipeline / proses latar belakang yang paling baru dieksekusi

command1 &
lpid1=$!

command2 &
lpid2=$!

command3 &
lpid=$!

wait $lpid1  # waits for only the process with PID lpid1  to complete. 

Anda perlu memanfaatkan ini sesuai skrip Anda dengan menggunakan exportvariabel dll

Kaushik Nayak
sumber
1

B hanya perlu menunggu proses latar belakangnya sendiri:

rsync -av /important/stuff/. remoteserver:/remote/dir/.
rsync -av /not/so/important/stuff/. remoteserver:/remote/dir/. &
wait
exit
Jared Lovell
sumber
Pada titik itu Anda mungkin juga tidak menjalankan rsync kedua di latar belakang dan menghindari menggunakan waitsepenuhnya. Meskipun saya menduga apa yang ingin dilakukan OP adalah menjalankan kedua rsyncproses secara paralel, yang berarti latar belakang keduanya (dengan &) dan kemudian menggunakan wait. Bagaimanapun, saya setuju bahwa ini adalah cara paling mudah untuk memperbaiki masalah ini dan saya akan memilih berdasarkan informasi dalam pertanyaan.
David Z