menjeda skrip bash hingga perintah sebelumnya selesai


20

Saya memiliki skrip bash yang terlihat seperti berikut:

##script
#!/bin/bash
rm data*
rm logfile*
for i in {1..30}
do
## append a & if you want to run it parallel;
nohup Rscript --vanilla main.R 10 100 $i &> logfile"$i" &
done

Saya ingin membuat yang lain untuk loop setelah yang pertama untuk melanjutkan selama 30. Misalnya

##script
#!/bin/bash
rm data*
rm logfile*
for i in {1..30}
do
## append a & if you want to run it parallel;
nohup Rscript --vanilla main.R 10 100 $i &> logfile"$i" &

for i in {31..60}
do
## append a & if you want to run it parallel;
nohup Rscript --vanilla main.R 10 100 $i &> logfile"$i" &
done

Saya ingin set pekerjaan pertama selesai sebelum memulai set baru. Tetapi karena nohupitu tampaknya mereka semua berjalan secara bersamaan.

Saya punya nohupkarena saya login ke server saya dari jauh dan memulai pekerjaan di sana dan kemudian menutup pesta saya. Apakah ada solusi alternatif?


1
Cari manual untuk waitbuiltin.
Satō Katsura

Jawaban:


22

Anda akan ingin menggunakan waitperintah untuk melakukan ini untuk Anda. Anda dapat menangkap semua ID proses anak-anak dan menunggu mereka secara khusus, atau jika mereka adalah satu-satunya proses latar belakang yang dibuat skrip Anda, Anda dapat memanggil waittanpa argumen. Sebagai contoh:

#!/bin/bash
# run two processes in the background and wait for them to finish

nohup sleep 3 &
nohup sleep 10 &

echo "This will wait until both are done"
date
wait
date
echo "Done"

6

Beberapa poin:

  • Jika tujuan Anda nohupadalah untuk mencegah keluarnya shell jarak jauh dari membunuh proses pekerja Anda, Anda harus menggunakan nohupscript itu sendiri, bukan pada proses pekerja individu yang dibuatnya.

  • Seperti yang dijelaskan di sini , nohuphanya mencegah proses dari menerima SIGHUP dan dari berinteraksi dengan terminal, tetapi tidak memutuskan hubungan antara shell dan proses anaknya.

  • Karena poin di atas, dengan atau tanpa nohup, sederhana waitantara dua forloop akan menyebabkan yang kedua fordieksekusi hanya setelah semua proses anak dimulai oleh yang pertama fortelah keluar.

  • Dengan sederhana wait:

    semua proses anak yang sedang aktif menunggu, dan status kembalinya adalah nol.

  • Jika Anda perlu menjalankan yang kedua forhanya jika tidak ada kesalahan di yang pertama, maka Anda harus menyimpan masing-masing PID pekerja $!, dan meneruskannya ke wait:

    pids=
    for ...
        worker ... &
        pids+=" $!"
    done
    wait $pids || { echo "there were errors" >&2; exit 1; }

Mungkin ada pekerjaan lain yang berjalan di server. Jadi saya hanya ingin menunggu batch saya .. mereka adalah skrip R sehingga dijalankan di bawah Ratau cc1plusdalam topperintah
masfenix

Saya juga ingin menggunakan nohup di dalam untuk menjalankan semua perintah dalam "paralel". pada dasarnya ini adalah simulasi untuk program ilmiah. Saya ingin menjalankan 180 simulasi secara total, tetapi dalam batch 60. Penghitung juga perlu beralih dari 1 menjadi 180. Jika saya melakukannya satu per satu, itu akan memakan waktu terlalu lama.
masfenix

waitmenyebabkan bashmenunggu pekerjaan latar belakang yang ditimbulkannya sendiri, tidak ada yang lain. Mungkin ada beberapa kebingungan di sini - forloop ini , apakah Anda menyimpannya ke file dan memanggilnya sebagai skrip (apa yang saya asumsikan, karena ##scriptbaris), atau apakah Anda mengetiknya dengan tangan di terminal?
Matei David

-1

Gunakan fgbuiltin. Ia menunggu sampai proses latar belakang selesai.

Coba help fguntuk detailnya.


Script berjalan tanpa kontrol pekerjaan.
Kusalananda

-1

Jika Anda memasukkan sesuatu seperti segmen kode berikut di antara dua forloop Anda, itu mungkin membantu.

flag=0

while [ flag -eq 0 ]
do
  ps -ef | grep "Rscript --vanilla" | grep -v grep > /dev/null
  flag=${?}
  sleep 10
done

Tentu saja, jika aplikasi Anda Rscriptmemiliki kesempatan untuk tidak menyelesaikan dengan sukses dan berlama-lama, putaran kedua Anda untuk loop mungkin tidak memiliki kesempatan untuk dijalankan. Segmen kode di atas mengasumsikan, semua proses dengan pengenalRscript --vanilla akan lengkap dan hilang dengan benar. Tanpa mengetahui apa yang dilakukan aplikasi Anda dan cara kerjanya, saya harus mengandalkan asumsi ini.

EDIT

Mengingat komentar, ini akan lebih sesuai dengan kebutuhan Anda. (itu termasuk kode asli Anda serta logika pemeriksaan penyelesaian)

for i in {1..30}
do
## append a & if you want to run it parallel;
nohup Rscript --vanilla main.R 10 100 $i &> logfile"$i" &
pids[$i]=${!}
done

flag=0

while [ flag -eq 0 ] 
do
  for PID in $(echo ${pids[@]})
  do
    flag=1
    ps -ef | grep ${PID} | grep -v grep >/dev/null; r=${?}
    if [ ${r} -eq 0 ]
    then 
      flag=0
    fi
  done
done

for i in {31..60}
do
## append a & if you want to run it parallel;
nohup Rscript --vanilla main.R 10 100 $i &> logfile"$i" &
done

Nama proses dalam topacara Rterkadang atau atau cc1plus.
masfenix

Dalam hal ini Anda perlu menemukan penyebut yang sama, yang muncul di ps -efdaftar. Atau setelah setiap nohupperintah, catat PID ke suatu variabel (lebih disukai sebuah array) dengan echo ${!}dan memeriksa grup PID ini. Ketika semuanya hilang, Anda dapat melanjutkan ke forloop kedua
MelBurslan
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.