Bisakah shell interaktif menjadi non-interaktif atau sebaliknya?

15

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
   shells  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 ( shdefinisi 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 bashtelah, 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 +idi 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 +idan 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_commentsopsi, 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 inilai $-" 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?)

Wildcard
sumber
Pertanyaan ini juga dibahas cukup panjang dalam obrolan .
Wildcard

Jawaban:

9

Pertanyaan yang saya ajukan adalah mengapa ada orang yang mau melakukan itu?

Anda dapat menonaktifkan beberapa aspek kerang interaktif seperti:

  • PS1= PS2= untuk menonaktifkan konfirmasi
  • set +m untuk menonaktifkan kontrol pekerjaan
  • nonaktifkan histori pada beberapa shell
  • Anda mungkin dapat membongkar zledan semua modul penyelesaian di zsh.

Tetapi jika Anda ingin shell berhenti menjadi interaktif, Anda bisa melakukannya:

. /some/file; exit

Untuk meminta agar mendapatkan sisa perintah /some/file(ganti dengan /dev/ttyjika Anda masih ingin agar perintah dibaca dari perangkat tty), meskipun masih ada beberapa perbedaan dari shell yang tidak interaktif, seperti untuk perilaku returnatau fakta bahwa itu masih akan melakukan kontrol pekerjaan atau:

exec myshell /dev/tty

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 +ikembali dengan bash: set: +i: invalid optionsejenis di sebagian besar shell.

Stéphane Chazelas
sumber
Sepenuhnya setuju itu akan menjadi hal yang konyol untuk dilakukan. Konsep "interaktif" saya, seperti yang saya sebutkan, adalah bahwa itu hanya kumpulan perilaku default yang berguna ketika Anda berinteraksi dengan shell Anda. Jika Anda dapat mengubah masing-masing perilaku itu secara individual, dan Anda memang mengubah masing-masing perilaku, maka pertanyaan "Apakah ini masih merupakan shell interaktif?" hanya semantik konyol; itu bahkan bukan pertanyaan penting. Namun ....
Wildcard
1
@ Kartu Memori, jika Anda melakukannya exec < <(sleep infinity)di shell interaktif, Anda punya shell interaktif yang tidak terlalu interaktif. Shell masih akan menganggap dirinya interaktif dalam yang $-masih mengandung i, tetapi Anda mungkin tidak. Saya tidak yakin ada banyak lagi yang perlu dibicarakan.
Stéphane Chazelas
2
@ Kartu Memori, jika shell dimulai sebagai interactive, tetap begitu. Fakta yang bisa Anda lakukan set +idi versi bash yang lebih lama adalah bug.
Stéphane Chazelas
1
@ Kartu Memori, Jika Anda melihat kode sumber bash, Anda mungkin akan menemukan ada interactivevariabel boolean global yang memetakan ke ibendera $-. Mengubah boolean itu tidak akan secara otomatis mengubah semua perilaku kerang interaktif. Perubahan dari interaktif ke non-interaktif tidak didukung.
Stéphane Chazelas
4
@Wildcard Dash menerima set +idan 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.
Gilles 'SANGAT berhenti menjadi jahat'