Dari apa yang saya baca, meletakkan perintah dalam tanda kurung harus menjalankannya dalam subkulit, mirip dengan menjalankan skrip. Jika ini benar, bagaimana cara melihat variabel x jika x tidak diekspor?
x=1
Menjalankan (echo $x)
pada baris perintah menghasilkan 1
Menjalankan echo $x
dalam skrip tidak menghasilkan apa-apa, seperti yang diharapkan
Jawaban yang Diterima:
Sebuah subkulit dimulai sebagai salinan yang hampir identik dari proses cangkang asli. Di bawah tenda, shell memanggil fork
panggilan sistem, yang menciptakan proses baru yang kode dan memorinya disalin. Saat subkulit dibuat, hanya ada sedikit perbedaan antara subkulit 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
adalah PID induk dari shell asli.
Beberapa shell mengubah beberapa variabel dalam subkulit. Bash mengatur BASHPID
ke PID dari proses shell, yang berubah dalam subkulit. Bash, zsh dan mksh mengatur $RANDOM
untuk menghasilkan nilai yang berbeda di induk dan di subkulit. Namun terlepas dari kasus khusus bawaan seperti ini, semua variabel memiliki nilai yang sama di subkulit seperti di cangkang asli, status ekspor yang sama, status hanya baca yang sama, dll. Semua definisi fungsi, definisi alias, opsi shell dan pengaturan lain juga diwariskan.
Sebuah 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 di subkulit dengan output standar yang terhubung ke pipa. Subkulit juga dimulai dengan direktori saat ini yang sama, topeng sinyal yang sama, dll. Salah satu dari sedikit pengecualian adalah bahwa subkulit tidak mewarisi perangkap khusus:sinyal yang diabaikan (trap '' SIGNAL
) tetap diabaikan di subkulit, tetapi jebakan lainnya (trap CODE
SINYAL ) disetel ulang ke tindakan default.
Dengan demikian, subkulit berbeda dari menjalankan skrip. Skrip adalah program terpisah. Program terpisah ini mungkin secara kebetulan juga merupakan skrip yang dieksekusi oleh penerjemah yang sama dengan induknya, tetapi kebetulan ini tidak memberikan program terpisah visibilitas khusus apa pun pada data internal induknya. Variabel yang tidak diekspor adalah data internal, jadi ketika penerjemah untuk skrip shell anak dijalankan, variabel ini tidak terlihat. Variabel yang diekspor, yaitu variabel lingkungan, ditransmisikan ke program yang dieksekusi.
Jadi:
x=1
(echo $x)
mencetak 1
karena subkulit adalah replikasi dari cangkang yang melahirkannya.
x=1
sh -c 'echo $x'
kebetulan menjalankan shell sebagai proses anak dari shell, tetapi x
pada baris kedua tidak memiliki koneksi lagi dengan x
di baris kedua daripada di
x=1
perl -le 'print $x'
atau
x=1
python -c 'print x'
Pengecualian adalah ksh93
shell tempat forking dioptimalkan dan sebagian besar efek sampingnya ditiru.
Secara semantik, mereka adalah salinan. Dari perspektif implementasi, ada banyak berbagi yang terjadi.
Untuk sisi kanan, tergantung cangkangnya.
Jika Anda menguji ini, perhatikan bahwa hal-hal seperti $(trap)
dapat melaporkan jebakan cangkang 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
perangkap dari subkulit bersarang dalam kasus "dua subkulit", tetapi bukan ERR
trap dari subkulit perantara — set -E
opsi harus menyebarkan ERR
trap ke semua subkulit tetapi subkulit perantara dioptimalkan sehingga tidak ada untuk menjalankan ERR
perangkap.