Jalankan skrip Bash dalam folder sekaligus

10

Misalkan saya memiliki lima .shskrip Bash ( ) dalam folder ( my_folder), dan mereka diberi nama sebagai berikut:

script_1.sh
script_2.sh
script_3.sh
script_4.sh
script_5.sh

Bagaimana saya bisa menulis skrip Bash keenam atau hanya satu liner yang akan mulai menjalankan semua skrip ini bersama-sama?

Saya membutuhkan lima skrip untuk mulai berjalan bersama pada saat yang sama dan tidak satu demi satu.

aaaaa
sumber

Jawaban:

12

GNU parallelsangat cocok untuk hal semacam ini. Instal dengan sudo apt install paralleldan kemudian:

parallel -j0 ::: my_folder/*sh

The -jmengontrol berapa banyak proses t dijalankan secara paralel, dan -j0berarti "mereka semua". Setel ke nilai lain (misalnya -j20) untuk menjalankan skrip dalam batch sebagai gantinya.

terdon
sumber
1
Catatan: ada juga parallelperintah dari moreutilspaket. Contoh penggunaan: parallel -j 20 -- my_folder/*.sh(Tidak seperti GNU parallel, -j0akan menjalankan skrip satu per satu).
jfs
1
@ jfs poin bagus. Tetapi perhatikan bahwa sudo apt install parallelakan mengganti file /usr/bin/paralleldengan yang dari paralel GNU. Jadi selama Anda menginstalnya, seperti jawaban saya menyarankan, itu harus berfungsi seperti yang diharapkan.
terdon
Ya, saya menemukannya dengan cara yang sulit ketika mencoba parallelperintah yang tidak berhasil dari manual saat menulis jawaban saya untuk menyarankan GNU paralel.
jfs
9

Untuk menjalankan semua skrip pada saat yang sama (secara paralel) gunakan:

script_1.sh &
script_2.sh &
script_3.sh &
script_4.sh &
script_5.sh &

Untuk menjalankan yang satu setelah yang lain (secara berurutan) gunakan:

script_1.sh &&
script_2.sh &&
script_3.sh &&
script_4.sh &&
script_5.sh

Peningkatan untuk komentar

Jika Anda memiliki 200 skrip yang ingin Anda jalankan pada saat yang sama (yang mungkin menghambat mesin BTW) gunakan skrip ini:

#!/bin/bash
for Script in my_folder/*.sh ; do
    echo bash "$Script" &
done

Atur atribut skrip menjadi executable dengan perintah:

chmod a+x /path/to/script.sh

Pertama kali Anda menjalankan skrip itu hanya akan menggemakan nama 200 skrip yang akan dieksekusi. Ketika Anda senang nama-nama yang tepat dipilih edit skrip dan ubah baris ini:

    echo bash "$Script" &

untuk:

    bash "$Script" &

Ada tiga cara Anda dapat memanggil skrip bash dari yang lain seperti dijawab di sini:

  1. Jadikan skrip lain dapat dieksekusi, tambahkan #!/bin/bashbaris di atas, dan jalur tempat file ke $PATHvariabel lingkungan. Kemudian Anda dapat menyebutnya sebagai perintah normal;

  2. Atau panggil dengan perintah sumber (alias.) Seperti ini source /path/to/script:;

  3. Atau gunakan perintah bash untuk melaksanakannya: /bin/bash /path/to/script;

Dalam kasus OP, satu atau lebih dari 200 skrip tidak berisi #!/bin/bashbaris pertama shebang dalam file. Dengan demikian, opsi 3. harus digunakan.


200 Script berjalan pada saat bersamaan

Sebuah komentar telah diajukan tentang apakah mereka "berjalan pada saat yang sama". Pada sistem 8 CPU yang khas, 25 skrip akan berbagi satu CPU pada saat yang sama tetapi hanya satu skrip yang akan dieksekusi pada satu waktu sampai irisan waktu (diukur dalam milidetik) habis. Kemudian pekerjaan berikutnya akan menerima bagian yang adil dari milidetik, kemudian pekerjaan berikutnya, dll., Dll.

Secara longgar kita dapat mengatakan 200 pekerjaan berjalan "bersamaan" tetapi tidak "secara bersamaan" di 8 CPU yang setara dengan 25 pekerjaan per CPU:

utas States.png

Di atas gambar dan komentar di bawah ini dari penjadwal kernel Linux

waktu slice.png

WinEunuuchs2Unix
sumber
terima kasih .. masalahnya adalah dalam kasus saya yang sebenarnya saya memiliki lebih dari 200 skrip untuk dijalankan. jadi apakah ada cara saya bisa menjalankan semuanya dengan satu perintah (yaitu tanpa menulis nama file mereka)?
aaaaa
@aaaaa Saya sudah mengubah jawaban untuk 200 skrip.
WinEunuuchs2Unix
Terima kasih. itu berfungsi .. satu-satunya hal yang saya harus tambahkan ke baris terakhir Anda adalah 'bash'. kalau tidak, saya mendapatkan 'izin ditolak'.
aaaaa
1
@aaaaa Apakah Anda sebenarnya lebih suka agar semua 200+ skrip berjalan pada saat yang sama, atau apakah Anda lebih suka memiliki jumlah yang lebih kecil (katakanlah, 10) berjalan pada satu waktu, dengan yang lain antri untuk berjalan ketika satu atau lebih dari mereka selesai dan jumlah skrip yang saat ini berjalan turun di bawah angka itu? (Jika Anda tertarik dengan solusi semacam itu, saya sarankan untuk mengedit pertanyaan Anda dengan informasi tentang berapa banyak skrip yang Anda miliki, berapa lama mereka cenderung berjalan, jenis pekerjaan apa yang mereka lakukan, dan sebagainya.)
Eliah Kagan
@aaaaa Terima kasih atas umpan baliknya. Saya telah memperbarui jawaban untuk menyertakan bashawalan untuk memanggil skrip.
WinEunuuchs2Unix
3

Ada alat untuk ini, baca man run-parts.

Sebagai contoh, saya lakukan:

 run-parts ${visorhome}/pbackup.d/

dalam skrip cadangan Palm Pilot saya. ${visorhome}/pbackup.d/:

01PopulateJpilot  02Extract_Pedometer  03URLs  04google  05Books  06Weight  07Sec  08Bkgm 50hardlinks
waltinator
sumber
1
@ eliah-kagan Menjalankan "lebih dari 200 skrip" "pada saat yang sama" tampaknya tidak bijaksana. Ini mungkin cara yang bagus untuk menguji stres suatu sistem
waltinator
Poin yang bagus. Saya pikir Anda mungkin masih ingin menyebutkan bahwa run-partsmengeksekusi skrip secara berurutan daripada sekaligus sebagai OP diminta. Namun, Anda benar bahwa menjalankan 200 skrip sekaligus tidak mungkin melakukan hal yang sama dengan menjalankan 5 - dan bahkan jika menjalankannya sekaligus tidak menyebabkan masalah, itu mungkin masih tidak perlu. Saya telah berkomentar untuk menyarankan OP mengklarifikasi preferensi mereka dalam hal ini.
Eliah Kagan
run-partstidak akan menjalankan skrip (mereka memiliki titik dalam nama:my_folder/*.sh
jfs
1
run-partsmemiliki persyaratan nama file yang sangat spesifik untuk beberapa alasan aneh. Itu tidak akan meluncurkan nama file dengan ekstensi, jadi saya khawatir ini tidak akan berfungsi di sini.
terdon
1

Untuk menjalankan semua *.shskrip di my_folderdirektori pada saat yang sama menggunakan xargs:

$ ls my_folder/*.sh | xargs -P0 -n1 bash

Untuk membatasi jumlah skrip yang dieksekusi secara bersamaan menjadi 10:

$ ls my_folder/*.sh | xargs -P10 -n1 bash
jfs
sumber
Merupakan praktik yang buruk untuk menggunakan hasil lsdalam skrip. Penggunaannya findjauh lebih aman. Ini item pertama di sini: mywiki.wooledge.org/BashPitfalls#for_f_in_.24.28ls_.2A.mp3.29
Joe
@ Jo pada umumnya, itu benar. Saya tidak melihat masalah dalam kasus khusus ini.
jfs
Itu karena Anda sudah tahu tentang itu. Orang yang datang ke sini nanti mungkin tidak.
Joe
@Joe jangan mengikuti dogma secara membabi buta. Berpikir untuk diri Anda sendiri dari satu opsi lebih baik dari yang lain apa trade off dalam kasus Anda.
jfs
Itu bukan dogma. Saya alergi terhadap itu. Tetapi saya telah melihat hal-hal yang dapat dipancarkannya. Parsing output yang dapat dibaca manusia tidak dapat diandalkan. Tidak ada insentif bagi pengembang untuk menjaga
Joe