Чи може інтерактивна оболонка стати неінтерактивною чи навпаки?
Примітка. Я провів багато досліджень з основного питання "Яка різниця між інтерактивним та неінтерактивним?", І результати мого дослідження змусили мене задати це питання.
Це питання частково має довгу преамбулу, оскільки важливо, який тип визначення ми використовуємо для "інтерактивного", щоб відповісти на нього. Визначення може бути довільною міткою для певного набору; це може бути описовим для різних властивостей; або він може дати вам інформацію, яку ви можете використовувати для прогнозування поведінки та розуміння мети. Останній тип ми можемо назвати "визначенням дії" або "динамічним визначенням", і він є найбільш корисним.
В man 1p sh
дається таке визначення інтерактивної оболонки:
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.
Від згадки про "-і варіант" та використання слова "операнди", це стосується виклику оболонки , а не атрибутів, які можна було б вивчити в запущеній оболонці.
Сторінка чоловіка Bash дещо по-іншому формулює це:
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.
Визначення в першому реченні знову лише стосується початку оболонки.
Друге речення (на мій прочитання) визначає умови, які використовуються як проксі, щоб встановити, чи була запущена оболонка певними способами, які визначаються як зробити її "інтерактивною".
Зауважте, що я не трактую це речення як: "Оболонка bash є інтерактивною тоді і лише тоді, коли $-
містить" i "." $-
здається, це просто зручний показник, а не визначення інтерактивного. Це вкрай важливо для мого питання.
Обидва ці ( sh
визначення POSIX та визначення Bash) - це механічні визначення, які вказують, за яких обставин мітка "інтерактивна" застосовується до запущеної оболонки. Вони не є визначеннями дій, оскільки вони не дають жодних наслідків для цієї мітки.
Однак я бачу, що на всій решті сторінки Bash man посипаються посилання на оболонку, яка поводиться певними способами, "якщо це не інтерактивна оболонка" або "тільки в інтерактивних оболонках, або якщо встановлено _____ параметр". (Є численні приклади, і це не головний пункт цього питання.)
Тож я прийму, що "інтерактивний" - це лише зручна мітка для колекції типових "інтерактивних" поведінок (налаштування опцій), описаних на всій іншій сторінці сторінки. Це сам по собі не фундаментальний термін чи об'єкт; воно не має авторитетного визначення поза вихідним кодом оболонки. (На відміну, наприклад, терміни "дескриптор відкритого файлу" або "зупинений процес", які посилаються на абстракції, вбудовані в дизайн самого ядра.)
(Хоча це також визначено у визначенні POSIX sh
, ця сторінка [ man 1p sh
] має набагато менше використання ", якщо оболонка не є інтерактивною" та подібними висловлюваннями, ніж man bash
має, і майже виключно фокусується на різницях у часі виклику, тому я зупинюсь на Bash з цього моменту і далі.)
Деякі з наслідків оболонки, яка є "інтерактивною", в будь-якому разі є актуальною лише під час виклику , наприклад, які файли отримує оболонка, перш ніж читати інші команди. Однак є наслідки (принаймні у Bash), які є актуальними в будь-який час. Таким чином, повинен бути спосіб сказати для будь-якої запущеної оболонки, чи є вона інтерактивною чи ні.
Запуск set +i
в інтерактивній оболонці Bash призводить до видалення "i" зі вмісту $-
.
Питання: чи це насправді означає, що оболонка більше не є інтерактивною?
За точним визначенням Баша, це не повинно, оскільки ніде у цьому визначенні не потрібно, щоб "я" був присутній у $-
:
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.
Чітке читання точного визначення також викликає питання: Якщо stdin або stderr інтерактивного терміналу перенаправляються, щоб вони більше не були підключені до терміналів, чи стає оболонка неінтерактивною?
( Здається, що відповідь на це - «ні», і довідкова сторінка могла включити модифікатор: «чий стандартний вхід і помилка підключені до терміналів ... під час виклику », але я не знаю остаточно.)
Якщо відповідь: "Ні, оболонка не може стати неінтерактивною, ні навпаки", то який остаточний спосіб визначити, чи оболонка інтерактивна?
Інший спосіб: якщо є поведінка "інтерактивної оболонки", яка зберігається і надалі set +i
, то що застосовується для визначення того, що ця поведінка повинна продовжувати застосовуватися?
Щоб ніхто сумнів його: Там є поведінка оболонки залученого в інтерактивному режимі, які зберігаються після set +i
і поведінки оболонки викликається не інтерактивно , які зберігаються після set -i
. Для прикладу розглянемо наступний уривок із 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.
Таким чином, відмінивши interactive_comments
опцію, ми можемо побачити різницю між інтерактивними та неінтерактивними оболонками. Стійкість цієї різниці демонструється наступним сценарієм:
#!/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
Це підтверджує, що "інтерактивні" та "мають i
значення $-
" не є рівнозначними.
Аналогічний тест ${parameter:?word}
з використанням невстановленого параметра дає подібні результати, знову підтверджуючи, що $-
це не "джерело істини" для інтерактивності оболонки.
Отже, нарешті, де зберігається остаточна ознака «інтерактивності» оболонки?
І чи може інтерактивна оболонка стати неінтерактивною чи навпаки? (... змінивши цю ознаку?)