Script shell menunggu perintah latar belakang

12

Saya sedang menulis skrip, tetapi ada sesuatu yang saya butuhkan sehingga saya tidak dapat menemukan cara untuk melakukannya ...

Saya perlu membuat perintah di latar belakang "command1 &" dan kemudian di suatu tempat dalam skrip saya harus menunggu sampai selesai sebelum saya melakukan command2. Pada dasarnya, saya membutuhkan ini:

CATATAN: setiap perintah berjalan di direktori tertentu! pada akhir while loop my command1 menciptakan 4 direktori, di mana di masing-masing menjalankan proses tertentu sehingga total proses yang berjalan adalah 4

a=1

while [$a -lt 4 ]

     . command1
   #Generates 1 Process  

     a= `export $a +1`
done

   #Wait until the 4 process end and then run the command2 

    . command2

Saya telah melihat sesuatu tentang waitperintah dengan nomor proses pid, tetapi itu tidak berhasil juga.

Joao Macau
sumber
Apakah Anda mengendalikan command1? Bisakah Anda memodifikasinya sehingga mengembalikan PID dari 4 proses?
terdon
Iya! Saya sudah memilikinya :)
Joao Macau
Saya telah memperbarui jawaban saya sesuai dengan itu. Katakan apakah itu cocok dengan harapan Anda.
Laurent C.
Q ini terkait dengan yang ini: unix.stackexchange.com/questions/100801/… . Satu-satunya perbedaan adalah Anda perlu mendapatkan PID dari proses latar belakang. Anda dapat menggunakan $!variabel untuk mendapatkan ini, meneruskannya ke waitperintah seperti yang saya tunjukkan di sana. $!berisi PID latar belakang terakhir, sementara $$berisi PID proses proses terakhir.
slm
3
Oke, sekarang skrip Anda tidak masuk akal sama sekali. Ada kesalahan sintaksis dan keanehan di sekitar. Bisakah Anda menunjukkan kepada kami skrip yang sebenarnya ? Mengapa Anda mencari perintah? Kenapa tidak dieksekusi saja?
terdon

Jawaban:

22

Anda dapat menggunakan perintah wait PIDuntuk menunggu proses berakhir.

Anda juga dapat mengambil PID dari perintah terakhir dengan $!

Dalam kasus Anda, sesuatu seperti ini akan bekerja:

command1 & #run command1 in background
PID=$! #catch the last PID, here from command1
command2 #run command2 while command1 is running in background
wait $PID #wait for command1, in background, to end
command3 #execute once command1 ended

Mengikuti hasil edit Anda, karena Anda memiliki beberapa PID dan Anda mengetahuinya, Anda dapat melakukannya:

command1 & #run command1 in background
PID1=xxxxx
PID2=yyyyy
PID3=xxyyy
PID4=yyxxx
command2 #run command2 while command1 is running in background
wait $PID1 $PID2 $PID3 $PID4 #wait for the four processes of command1, in background, to end
command3 #execute once command1 ended
Laurent C.
sumber
Mengikuti suntingan Anda, jika Anda tahu PID dibuat (xxxxx, yyyyy, xxyyy, yyxxx), Anda dapat menggunakan wait juga, dengan daftar PID untuk menunggu (lihat man). Jika Anda tidak mengenal mereka, mungkin Anda dapat mengumpulkan mereka menjadi command1 (apa command1? Script Anda sendiri?)
Laurent C.
Mungkin yang terbaik untuk memastikan mereka dikelompokkan dengan benar sejak awal. Lihat jawaban saya untuk ide bagaimana hal itu dapat dilakukan.
mikeserv
4

Cara paling bersih untuk melakukan ini adalah dengan comamnd1mengembalikan PID Anda dari proses yang diluncurkan dan menggunakannya waitpada masing-masing seperti yang disarankan oleh jawaban @ LaurentC .

Pendekatan lain akan seperti ini:

## Create a log file
logfile=$(mktemp)

## Run your command and have it print into the log file
## when it's finsihed.
command1 && echo 1 > $logfile &

## Wait for it. The [ ! -s $logfile ] is true while the file is 
## empty. The -s means "check that the file is NOT empty" so ! -s
## means the opposite, check that the file IS empty. So, since
## the command above will print into the file as soon as it's finished
## this loop will run as long as  the previous command si runnning.
while [ ! -s $logfile ]; do sleep 1; done

## continue
command2
terdon
sumber
maaf tapi masih tidak berfungsi .. Saya akan meningkatkan pertanyaan saya sekali lagi!
Joao Macau
0

Jika Anda menggunakan metode berikut, Anda mungkin tidak perlu "tunggu semua proses" khusus setelah loop sementara. Loop akan menunggu arus command1untuk menyelesaikan sebelum siklus kembali ke atas. Harap berhati-hati dengan saran apa pun. Perhatikan, satu-satunya hal yang saya lakukan adalah menambah & wait $!akhir Anda command1.

a=1
while [$a -lt 4 ]
     . command1  & wait $!
   #Generates 1 Process  
     a= `export $a +1`
done
Marius M
sumber