Apakah dukungan bash fork mirip dengan fork C ()?

25

Saya memiliki skrip yang ingin saya tandai pada satu titik sehingga dua salinan skrip yang sama berjalan.

Misalnya, saya ingin ada skrip bash berikut:

echo $$
do_fork()
echo $$

Jika skrip bash ini benar-benar ada, output yang diharapkan adalah:

<ProcessA PID>
<ProcessB PID>
<ProcessA PID>

atau

<ProcessA PID>
<ProcessA PID>
<ProcessB PID>

Apakah ada sesuatu yang bisa saya ganti "do_fork ()" untuk mendapatkan output seperti ini, atau menyebabkan skrip bash melakukan fork seperti C?

Cory Klein
sumber

Jawaban:

23

Iya nih. Forking dieja &:

echo child & echo parent

Apa yang mungkin membingungkan Anda adalah bahwa $$itu bukan PID dari proses shell, itu adalah PID dari proses shell asli . Maksud dari membuatnya seperti ini adalah itu $$adalah pengidentifikasi unik untuk contoh tertentu dari skrip shell: itu tidak berubah selama eksekusi skrip, dan itu berbeda dari $$skrip lain yang berjalan bersamaan. Salah satu cara untuk mendapatkan PID aktual proses shell adalah sh -c 'echo $PPID'.

Aliran kontrol dalam shell tidak sama dengan C. Jika dalam C Anda akan menulis

first(); fork(); second(); third();

maka setara shell

after_fork () { second; third; }
first; after_fork & after_fork

Bentuk shell sederhana first; child & parentsesuai dengan idiom C yang biasa

first(); if (fork()) parent(); else child();

&dan $$ada dan berperilaku seperti ini di setiap shell Bourne-style dan di (t) csh. $PPIDtidak ada di shell Bourne orignal tetapi dalam POSIX (jadi abu, bash, ksh, zsh, ...).

Gilles 'SANGAT berhenti menjadi jahat'
sumber
3
Tapi itu pada dasarnya "fork + exec", bukan hanya fork.
mattdm
@mattdm: Uh? &adalah garpu, tidak ada eksekutif yang terlibat. Fork + exec adalah ketika Anda meluncurkan perintah eksternal.
Gilles 'SO- stop being evil'
@mattdm: Ah, saya pikir saya melihat apa yang Cory maksudkan. Tidak ada exec, tetapi kedua bahasa memiliki aliran kontrol yang berbeda.
Gilles 'SO- stop being evil'
1
@Gilles: Operator kontrol bash &memulai subkulit tempat perintah yang diberikan dijalankan. Fork + exec. Anda tidak bisa hanya menempatkan &tanpa perintah sebelumnya untuk dieksekusi.
mattdm
5
Nah, jika "Forking dieja &" adalah pernyataan yang benar, Anda bisa memasang &garis dengan sendirinya. Tapi kamu tidak bisa. Itu tidak berarti "bercabang di sini". Ini berarti "jalankan perintah sebelumnya di latar belakang dalam sebuah subkulit".
mattdm
10

Ya, ini disebut subkulit . Kode shell di dalam tanda kurung dijalankan sebagai subkulit (garpu). Namun cangkang pertama biasanya menunggu anak untuk menyelesaikan. Anda dapat membuatnya tidak sinkron menggunakan &terminator. Lihat beraksi dengan sesuatu seperti ini:

#!/bin/bash

(sleep 2; echo "subsh 1")&
echo "topsh"

$ bash subsh.sh

Keith
sumber
5
Tanda kurung membuat subkulit, tapi itu garpu + tunggu. &adalah garpu sendiri. Jika Anda ingin mengeksekusi lebih dari satu pipa dalam proses anak, cukup menggunakan kawat gigi (yang melakukan pengelompokan tanpa membuat proses anak):{ sleep 2; echo child; } &
Gilles 'SO- stop being evil'
6

Tidak ada bash asli (atau, setahu saya, cara khas * nix shell) lainnya untuk melakukan ini. Ada banyak cara untuk menelurkan proses bercabang yang melakukan sesuatu yang lain secara serempak, tapi saya tidak berpikir ada sesuatu yang mengikuti semantik yang tepat dari sistem panggilan fork ().

Pendekatan tipikal adalah membuat skrip level atas Anda memunculkan pembantu yang hanya melakukan pekerjaan yang Anda inginkan. Jika Anda melakukan $0 $@ &atau apa pun, Anda akan mulai dari awal lagi dan perlu memikirkannya.

Saya sebenarnya mulai memikirkan beberapa cara pintar di mana orang bisa melakukan hal itu ....

Tapi , sebelum otak saya terlalu terbawa oleh itu, saya pikir aturan yang cukup bagus adalah: jika Anda mencoba untuk menulis sesuatu di shell dan itu penuh dengan trik pintar dan Anda berharap untuk lebih banyak fitur bahasa, waktu untuk beralih ke bahasa pemrograman nyata .

mattdm
sumber
2
Meskipun poin Anda baik-baik saja, sintaksis bash bisa dibilang sulit dan tidak memiliki struktur data yang lebih elegan dan fitur Perl atau Python, bash sama nyatanya dengan yang ada di domainnya . Ini adalah bahasa khusus domain, dan saya berpendapat lebih baik (lebih ringkas, lebih sederhana) daripada misalnya Python dalam banyak hal. Bisakah Anda mengelola satu ruangan penuh sistem dan tidak tahu Python? Iya nih. Bisakah Anda melakukan itu dan tidak tahu sedikitpun [pemrograman] bash? Saya tidak ingin mencoba. Setelah 30 tahun pemrograman shell, saya katakan itu nyata. Dan ya, saya berbicara Python. Tapi jangan membingungkan anak-anak muda.
Mike S
2
Yang mengatakan, secara teknis saya lebih suka jawaban ini. Mengatakan bahwa "&" adalah jawaban untuk pertanyaan pengguna, "bercabang pada satu titik sehingga dua salinan dari skrip yang sama berjalan" menurut saya membingungkan. Apa yang dilakukan "&", menurut manual bash, adalah "... menjalankan perintah [diberikan] di latar belakang dalam sebuah subkulit." Itu harus mengakhiri perintah, dan itu memang melibatkan garpu (secara teknis, di Linux, klon ()), tetapi pada saat itu dua salinan dari skrip yang sama tidak berjalan.
Mike S