Saya mencoba menulis fungsi untuk menggantikan fungsi exit
builtin untuk mencegah saya keluar dari terminal.
Saya telah mencoba menggunakan SHLVL
variabel lingkungan tetapi tampaknya tidak berubah di dalam subkulit:
$ echo $SHLVL
1
$ ( echo $SHLVL )
1
$ bash -c 'echo $SHLVL'
2
Fungsi saya adalah sebagai berikut:
exit () {
if [[ $SHLVL -eq 1 ]]; then
printf '%s\n' "Nice try!" >&2
else
command exit
fi
}
Ini tidak memungkinkan saya untuk menggunakan exit
dalam subkulit:
$ exit
Nice try!
$ (exit)
Nice try!
Apa metode yang baik untuk mendeteksi apakah saya dalam subkulit atau tidak?
(...)
mewarisi semua properti dari proses induk. Jawaban yang diberikan adalah solusi yang lebih kuat untuk menentukan level shell Anda.BASH_SUBSHELL
jawabannya (walaupun kontroversial) tidak berlaku untuk pertanyaan itu.Jawaban:
Di bash, Anda dapat membandingkan
$BASHPID
ke$$
Jika Anda tidak dalam bash,
$$
harus tetap sama dalam subkulit, jadi Anda perlu cara lain untuk mendapatkan ID proses yang sebenarnya.Salah satu cara untuk mendapatkan pid Anda yang sebenarnya adalah
sh -c 'echo $PPID'
. Jika Anda hanya meletakkannya di dataran( … )
, sepertinya tidak berfungsi, karena shell Anda telah mengoptimalkan garpu. Coba perintah no-op tambahan( : ; sh -c 'echo $PPID'; : )
untuk membuatnya berpikir subshell terlalu rumit untuk dioptimalkan. Kredit jatuh ke John1024 di Stack Overflow untuk pendekatan itu.sumber
(sh -c 'echo $PPID'; : )
- lihat komentar saya pada jawaban John1024 .Bagaimana dengan
BASH_SUBSHELL
?sumber
[ini seharusnya komentar, tetapi komentar saya cenderung dihapus oleh moderator, jadi ini akan tetap sebagai jawaban yang bisa saya gunakan sebagai referensi bahkan jika dihapus]
Menggunakan
BASH_SUBSHELL
sepenuhnya tidak dapat diandalkan karena hanya diatur ke 1 di beberapa subkulit, tidak di semua subkulit.Sebelum mengklaim bahwa subproses perintah pipeline dijalankan bukan subshell yang benar - benar nyata, pertimbangkan
man bash
potongan ini :dan implikasi praktis - apakah fragmen skrip menjalankan subproses atau tidak yang penting, bukan beberapa terminologi berdalih.
Satu-satunya solusi, seperti yang sudah dijelaskan dalam jawaban untuk pertanyaan ini adalah untuk memeriksa apakah
$BASHPID
sama$$
atau, mudah dibawa tetapi jauh lebih efisien:sumber
BASH_SUBSHELL
diatur cukup andal, tetapi mendapatkan nilainya dengan benar adalah rapuh. Perhatikan apa yang dikatakan dokumen : "Bertambah satu dalam setiap subkulit atau lingkungan subkulit ketika shell mulai mengeksekusi di lingkungan itu. " Saya pikir bahwa dalam contoh pipa, bash belum memulai mengeksekusi dalam subkulit itu ketika variabel diperluas. Anda dapat membandingkanecho $BASH_VERSION
dengandeclare -p BASH_VERSION
- yang terakhir harus andal keluaran 1 dengan pipa, pekerjaan latar belakang, dlleval 'echo $BASH_SUBSHELL $BASHPID' | cat
akan menghasilkan 1 untukBASH_SUBSHELL
, karena variabel diperluas setelah eksekusi dimulai.subshell_level
benar-benar ditangguhkan dalam kasus pipa latar depan , yang mungkin memiliki beberapa alasan, tetapi yang saya tidak bisa melihat ;-)echo $$ $BASHPID $BASH_SUBSHELL | cat
.