Bisakah shell interaktif menjadi non-interaktif atau sebaliknya?
Catatan: Saya telah melakukan banyak penelitian pada pertanyaan dasar, "Apa perbedaan antara interaktif dan non-interaktif?", Dan hasil penelitian saya membuat saya mengajukan pertanyaan ini .
Pertanyaan ini memiliki pembukaan panjang sebagian karena sangat penting apa jenis definisi yang kita gunakan untuk "interaktif" untuk menjawabnya. Definisi dapat berupa label yang berubah-ubah untuk set tertentu; bisa deskriptif dari berbagai properti; atau dapat memberi Anda informasi yang dapat Anda gunakan untuk memprediksi perilaku dan memahami tujuan. Jenis terakhir ini bisa kita sebut "definisi tindakan" atau "definisi dinamis" dan ini yang paling berguna.
Dalam man 1p sh
, definisi shell interaktif berikut diberikan:
If the -i option is present, or if there are no operands and the shell’s standard input and standard error are attached to a terminal, the shell is considered to be interactive.
Dari penyebutan "-i opsi" dan penggunaan kata "operan," ini merujuk pada permohonan shell , bukan atribut yang bisa diperiksa dalam shell yang sedang berjalan.
Halaman Bash man mengutarakannya sedikit berbeda:
An interactive shell is one started without non-option arguments and without the -c option whose standard input and error are both connected to terminals (as determined by isatty(3)), or one started with the -i option. PS1 is set and $- includes i if bash is interactive, allowing a shell script or a startup file to test this state.
Definisi dalam kalimat pertama lagi hanya mengacu pada permulaan shell.
Kalimat kedua (dalam bacaan saya) mendefinisikan kondisi yang digunakan sebagai proxy untuk menentukan apakah shell dimulai dengan cara tertentu yang didefinisikan sebagai membuatnya "interaktif."
Perhatikan bahwa saya tidak menafsirkan kalimat ini sebagai: "Sebuah bash shell bersifat interaktif jika dan hanya jika $-
menyertakan 'i'." $-
tampaknya hanya menjadi indikator yang berguna, bukan definisi interaktif. Ini sangat relevan dengan pertanyaan saya.
Kedua hal ini ( sh
definisi POSIX dan Bash) adalah definisi mekanis yang menunjukkan dalam keadaan apa label "interaktif" berlaku untuk shell yang telah Anda mulai. Mereka bukan definisi tindakan karena mereka tidak memberikan implikasi label ini.
Namun, saya melihat bahwa di seluruh halaman manual Bash terdapat referensi yang bertabur pada shell yang berperilaku dengan cara tertentu "kecuali itu adalah shell interaktif" atau "hanya di shell interaktif, atau jika opsi _____ diatur." (Ada banyak contoh dan itu bukan poin utama dari pertanyaan ini.)
Jadi saya akan menerima bahwa "interaktif" hanyalah label yang sesuai untuk kumpulan perilaku "interaktif" default (pengaturan opsi) yang dijelaskan di seluruh halaman manual. Itu bukan istilah fundamental atau objek itu sendiri; tidak memiliki definisi resmi di luar kode sumber shell. (Berbeda dengan, misalnya, istilah "deskriptor file terbuka" atau "proses berhenti" yang mengacu pada abstraksi yang dibangun ke dalam desain kernel itu sendiri.)
(Sementara itu juga didefinisikan dalam definisi POSIX sh
, bahwa halaman manual [ man 1p sh
] memiliki penggunaan jauh lebih sedikit "kecuali shell adalah interaktif" dan pernyataan serupa dari yang man bash
telah, dan hampir secara eksklusif berfokus pada perbedaan waktu doa, jadi saya akan fokus pada Bash dari titik ini dan seterusnya.)
Beberapa implikasi shell menjadi "interaktif" hanya relevan pada waktu doa , seperti file mana yang diambil oleh shell sebelum membaca perintah lain. Namun, ada yang implikasi (setidaknya di Bash) yang relevan setiap saat. Jadi harus ada cara untuk mengetahui, untuk setiap shell yang dijalankan , apakah itu interaktif atau tidak.
Berjalan set +i
di shell Bash interaktif menyebabkan 'i' dihapus dari konten $-
.
Pertanyaannya adalah: Apakah ini berarti shell tidak lagi interaktif?
Menurut definisi pasti Bash, seharusnya tidak, karena tidak ada dalam definisi yang mengharuskan 'i' hadir di $-
:
An interactive shell is one started without non-option arguments and without the -c option whose standard input and error are both connected to terminals (as determined by isatty(3)), or one started with the -i option.
Pembacaan ketat dari definisi yang tepat juga menimbulkan pertanyaan: Jika stdin atau stderr dari terminal interaktif diarahkan sehingga mereka tidak lagi terhubung ke terminal, apakah shell menjadi non-interaktif?
( Tampaknya jawaban untuk yang ini adalah "tidak" dan halaman manual bisa menyertakan pengubah: "yang input dan kesalahan standar keduanya terhubung ke terminal ... pada saat doa, " tapi saya tidak tahu secara definitif.)
Jika jawabannya adalah, "Tidak, shell tidak bisa menjadi non-interaktif, atau sebaliknya," lalu apa cara definitif untuk menentukan apakah shell itu interaktif?
Dengan kata lain: Jika ada perilaku "shell interaktif" yang bertahan setelahnya set +i
, apa yang digunakan untuk menentukan bahwa perilaku itu harus terus diterapkan?
Jangan ada orang diragukan lagi itu: Ada yang perilaku shell dipanggil secara interaktif yang bertahan setelah set +i
dan perilaku dari shell dipanggil non-interaktif yang tetap ada setelah set -i
. Sebagai contoh, pertimbangkan kutipan berikut dari man bash
:
COMMENTS In a non-interactive shell, or an interactive shell in which the inter- active_comments option to the shopt builtin is enabled (see SHELL BUILTIN COMMANDS below), a word beginning with # causes that word and all remaining characters on that line to be ignored. An interactive shell without the interactive_comments option enabled does not allow comments. The interactive_comments option is on by default in interac- tive shells.
Dengan demikian dengan membatalkan interactive_comments
opsi, kita dapat melihat perbedaan antara shell interaktif dan non-interaktif. Kegigihan perbedaan ini ditunjukkan oleh skrip berikut:
#!/bin/bash
# When the testfile is run interactively,
# all three comments will produce an error
# (even the third where 'i' is not in '$-').
# When run noninteractively, NO comment will
# produce an error, though the second comment
# is run while 'i' IS in '$-'.
cat >testfile <<'EOF'
shopt interactive_comments
shopt -u interactive_comments
shopt interactive_comments
echo $-
#first test comment
set -i
echo $-
#second test comment
set +i
echo $-
#third test comment
EOF
echo 'running bash -i <testfile'
bash -i <testfile
echo 'running bash <testfile'
bash <testfile
Ini menegaskan bahwa "interaktif" dan "memiliki i
nilai $-
" tidak setara.
Pengujian serupa menggunakan ${parameter:?word}
dengan parameter yang tidak disetel menghasilkan hasil yang serupa, sekali lagi menegaskan bahwa $-
itu bukan "sumber kebenaran" untuk interaktivitas shell.
Jadi, akhirnya, di mana sifat 'interaktivitas' definitif dari sebuah shell disimpan?
Dan, dapatkah shell interaktif menjadi non-interaktif atau sebaliknya? (... dengan mengubah sifat ini?)
sumber
Jawaban:
Pertanyaan yang saya ajukan adalah mengapa ada orang yang mau melakukan itu?
Anda dapat menonaktifkan beberapa aspek kerang interaktif seperti:
PS1= PS2=
untuk menonaktifkan konfirmasiset +m
untuk menonaktifkan kontrol pekerjaanzle
dan semua modul penyelesaian dizsh
.Tetapi jika Anda ingin shell berhenti menjadi interaktif, Anda bisa melakukannya:
Untuk meminta agar mendapatkan sisa perintah
/some/file
(ganti dengan/dev/tty
jika Anda masih ingin agar perintah dibaca dari perangkat tty), meskipun masih ada beberapa perbedaan dari shell yang tidak interaktif, seperti untuk perilakureturn
atau fakta bahwa itu masih akan melakukan kontrol pekerjaan atau:Untuk mengganti shell interaktif Anda saat ini dengan yang non-interaktif yang masih membaca perintah dari perangkat tty.
Perhatikan bahwa dengan bash 4.4,
set +i
kembali denganbash: set: +i: invalid option
sejenis di sebagian besar shell.sumber
exec < <(sleep infinity)
di shell interaktif, Anda punya shell interaktif yang tidak terlalu interaktif. Shell masih akan menganggap dirinya interaktif dalam yang$-
masih mengandungi
, tetapi Anda mungkin tidak. Saya tidak yakin ada banyak lagi yang perlu dibicarakan.interactive
, tetap begitu. Fakta yang bisa Anda lakukanset +i
di versi bash yang lebih lama adalah bug.bash
, Anda mungkin akan menemukan adainteractive
variabel boolean global yang memetakan kei
bendera$-
. Mengubah boolean itu tidak akan secara otomatis mengubah semua perilaku kerang interaktif. Perubahan dari interaktif ke non-interaktif tidak didukung.set +i
dan berhenti menampilkan prompt. Ini adalah sesuatu yang seharusnya tidak dilakukan oleh pengguna, jadi tidak mengherankan bahwa perilaku tergantung pada shell dan sering tidak disengaja daripada hasil keputusan yang disengaja oleh pelaksana shell.