Subkulit dimulai sebagai salinan hampir identik dari proses shell asli. Di bawah tenda, shell memanggil fork
system call 1 , yang menciptakan proses baru yang kode dan memorinya adalah salinan 2 . Ketika subkulit dibuat, ada sangat sedikit perbedaan antara itu dan induknya. Secara khusus, mereka memiliki variabel yang sama. Bahkan $$
variabel khusus menyimpan nilai yang sama dalam subkulit: ini adalah ID proses shell asli. Demikian pula $PPID
PID induk dari shell asli.
Beberapa shell mengubah beberapa variabel dalam subkulit. Bash mengatur BASHPID
ke PID dari proses shell, yang berubah dalam subshell. Bash, zsh dan mksh mengatur untuk $RANDOM
menghasilkan nilai yang berbeda di induk dan di subkulit. Namun terlepas dari kasus khusus bawaan seperti ini, semua variabel memiliki nilai yang sama dalam subkulit seperti pada shell asli, status ekspor yang sama, status hanya baca yang sama, dll. Semua definisi fungsi, alias definisi, opsi shell dan pengaturan lain juga diwarisi.
Subkulit yang dibuat oleh (…)
memiliki deskriptor file yang sama dengan pembuatnya. Beberapa cara lain untuk membuat subkulit memodifikasi beberapa deskriptor file sebelum mengeksekusi kode pengguna; misalnya, sisi kiri pipa berjalan dalam subkulit 3 dengan output standar yang terhubung ke pipa. Subkulit juga dimulai dengan direktori saat ini yang sama, masker sinyal yang sama, dll. Salah satu dari beberapa pengecualian adalah bahwa subkulit tidak mewarisi jebakan khusus: sinyal yang diabaikan ( ) tetap diabaikan dalam subkulit, tetapi jebakan lain ( SIGNAL ) diatur ulang ke tindakan standar 4 .trap '' SIGNAL
trap CODE
Subshell berbeda dari mengeksekusi skrip. Sebuah skrip adalah program terpisah. Program terpisah ini mungkin secara kebetulan juga merupakan skrip yang dijalankan oleh penerjemah yang sama dengan induknya, tetapi kebetulan ini tidak memberikan program terpisah visibilitas khusus pada data internal induk. Variabel yang tidak diekspor adalah data internal, jadi ketika interpreter untuk skrip shell anak dieksekusi , ia tidak melihat variabel-variabel ini. Variabel yang diekspor, yaitu variabel lingkungan, ditransmisikan ke program yang dijalankan.
Jadi:
x=1
(echo $x)
dicetak 1
karena subkulit adalah replikasi dari shell yang memunculkannya.
x=1
sh -c 'echo $x'
kebetulan menjalankan shell sebagai proses anak dari shell, tetapi x
pada baris kedua tidak memiliki lebih banyak koneksi dengan x
pada baris kedua daripada di
x=1
perl -le 'print $x'
atau
x=1
python -c 'print x'
1 Pengecualian adalah ksh93
shell di mana forking dioptimalkan keluar dan sebagian besar efek sampingnya ditiru.
2 Semantik, itu salinan. Dari perspektif implementasi, ada banyak sharing yang terjadi.
3 Untuk sisi kanan, tergantung pada cangkangnya.
4 Jika Anda menguji ini, perhatikan bahwa hal-hal seperti$(trap)
dapat melaporkan jebakan dari shell asli. Perhatikan juga bahwa banyak cangkang memiliki bug dalam kasus sudut yang melibatkan jebakan. Misalnya ninjalj mencatat bahwa pada bash 4.3, bash -x -c 'trap "echo ERR at \$BASH_SUBSHELL \$BASHPID" ERR; set -E; false; echo one subshell; (false); echo two subshells; ( (false) )'
menjalankan ERR
jebakan dari subkulit bersarang dalam kasus "dua subkulit", tetapi bukan ERR
jebakan dari subkulit perantara - set -E
opsi harus menyebarkanERR
jebakan ke semua subkulit tetapi subkulit perantara dioptimalkan dan jadi tidak ada untuk menjalankan ERR
jebakannya.
x=out; (x=in; echo $x)
)echo $(x=2; echo $x)
, fragmen$(x=2; echo $x)
perlu diperluas. Ini membutuhkan evaluasi perintahx=2; echo $x
. Perluasan$x
terjadi selama evaluasi ini, setelah mengevaluasi bagianx=2
.x
tidak disetel)echo $(echo foo >somefile)${x-$(cat somefile)}
atauecho $(echo $x),${x=1}
../file
tidak dieksekusi dalam subkulit. Lihat juga unix.stackexchange.com/q/261638 dan unix.stackexchange.com/a/157962Jelas, ya, seperti semua dokumentasi mengatakan, perintah di dalam tanda kurung dijalankan dalam subkulit.
Subkulit mewarisi salinan dari semua variabel induk. Perbedaannya adalah bahwa setiap perubahan yang Anda buat dalam subkulit tidak juga dibuat di induknya.
Halaman manual ksh membuat ini sedikit lebih jelas daripada halaman bash:
man ksh
:man bash
:sumber
When a simple command other than a builtin or shell function is to be executed, it is invoked in a separate execution environment that consists of the following.
, yang berisi item:· shell variables and functions marked for export, along with variables exported for the command, passed in the environment
(dari bagian yang samaman bash
) yang menjelaskan mengapaecho $x
-script tidak mencetak apa-apa jikax
tidak diekspor.