Saya tampaknya salah paham aturan Bash untuk membuat subkulit. Saya pikir tanda kurung selalu membuat subkulit, yang berjalan sebagai prosesnya sendiri.
Namun, sepertinya tidak demikian. Dalam Cuplikan Kode A (di bawah), sleep
perintah kedua tidak berjalan di shell yang terpisah (sebagaimana ditentukan oleh pstree
terminal lain). Namun, di Cuplikan Kode B, kedua sleep
perintah tidak dijalankan di shell terpisah. Satu-satunya perbedaan antara snippet adalah bahwa snippet kedua memiliki dua perintah di dalam tanda kurung.
Bisakah seseorang tolong jelaskan aturan ketika subkulit dibuat?
SNIPPET KODE A:
sleep 5
(
sleep 5
)
SNIPPET KODE B:
sleep 5
(
x=1
sleep 5
)
sumber
fork
dan proses anak dibuat (untuk menjalankan perintah eksternal) dengan memanggilfork + exec
. Tapi para Anda yang pertama menyarankan agarfork + exec
dipanggil juga untuk subkulit. Apa yang salah di sini?fork
+exec
tidak dipanggil untuk subshell, itu dipanggil untuk perintah eksternal. Tanpa optimasi, adafork
panggilan untuk subkulit dan satu lagi untuk perintah eksternal. Saya telah menambahkan uraian alur terperinci ke jawaban saya.(...)
(dalam kasus dasar), mungkin ada atau tidak ada panggilan untukexec
bergantung pada apakah subkulit memiliki perintah eksternal untuk dieksekusi, sedangkan dalam kasus mengeksekusi perintah eksternal harus adafork + exec
.date
di shell?strace -f -e clone,execve,write bash -c 'date'
danstrace -f -e clone,execve,write bash -c 'date; true'
Dari Panduan Pemrograman Bash Lanjutan :
"Secara umum, perintah eksternal dalam skrip memotong dari suatu proses, sedangkan Bash builtin tidak. Untuk alasan ini, builtin mengeksekusi lebih cepat dan menggunakan lebih sedikit sumber daya sistem daripada setara dengan perintah eksternal mereka."
Dan sedikit lebih jauh ke bawah:
"Daftar perintah yang disematkan di antara tanda kurung berjalan sebagai subkulit."
Contoh:
Contoh menggunakan kode OP (dengan tidur lebih pendek karena saya tidak sabar):
Hasil:
sumber
sleep
berjalan dalam subkulit (mungkin pada proses subkulit karena ini merupakan bawaan, bukan proses dalam subkulit). Namun, dalam hal apa pun, saya akan mengharapkan subkulit ada, yaitu subproses Bash di bawah proses induk Bash. Untuk Cuplikan B di atas, sepertinya tidak demikian.sleep
sepertinya bukan built-in, saya berharapsleep
panggilan kedua di kedua snippet berjalan di subproses proses subshell.$BASHPID
variabel saya . Sayangnya cara Anda melakukannya tidak memberi Anda seluruh cerita yang saya percaya. Lihat hasil tambahan saya di jawabannya.Catatan tambahan untuk jawaban @Gilles.
Seperti yang dikatakan oleh Gilles:
The parentheses always start a subshell.
Namun, angka yang mungkin dimiliki oleh sub-shell tersebut:
Seperti yang Anda lihat, $$ terus berulang, dan itu seperti yang diharapkan, karena (jalankan perintah ini untuk menemukan
man bash
baris yang benar ):Yaitu: Jika shell tidak diinisialisasi ulang, $$ adalah sama.
Atau dengan ini:
Ini
$$
adalah ID dari shell saat ini (bukan subshell).sumber