Оболочка является интерактивной, если она не интерпретирует (, возможно, встроенный в-c
)скрипт, и ее стандартный ввод является терминалом (, но см. ниже для оболочек POSIX)
В этом случае мы хотим, чтобы подсказка (и echo
того, что вы вводите для оболочек, имеющих собственный редактор строк ), отображались на одном и том же терминале. Проблема в том, что стандартный ввод не может быть открыт в режиме чтения и записи, поэтому вывод приглашения на стандартный ввод не будет надежным. Также в середине интерактивного сеанса может потребоваться выполнить exec < other-file
, что также приведет к нарушению отображения подсказки.
Разумным решением и тем, что делает zsh
, было бы определить, какой терминал (используетttyname()
)и повторно открыть его для чтения+записи (на выделенном отдельном fd выше 10 )для взаимодействия с пользователем. Использование дескриптора файла, открытого на/dev/tty
(управляющем терминале, который в подавляющем большинстве случаев будет ссылаться на тот же терминал, что и терминал на стандартном вводе, если стандартный ввод является терминалом ), имело бы для меня смысл, но это не так. похоже, что любая оболочка делает это (, возможно, чтобы позаботиться о случаях, когда нет управляющего терминала, что может произойти в некоторых случаях, таких как оболочки восстановления на консоли ).
Однако спецификация POSIX говорит, что оболочка является интерактивной только в том случае, если помимо требований, описанных выше, stderr также является терминалом , а POSIX требует, чтобы подсказки записывались на stderr .
bash
нацелен на соответствие POSIX, поэтому должен следовать этим требованиям.
Я предполагаю, что причина историческая. Спецификация POSIX sh
основана на ksh88
, и именно так вел себя ksh88
и оболочка Bourne до нее. (хотя ttyname()
уже существовал в Unix V7, где впервые была выпущена оболочка Bourne ).
Обычно взаимодействие пользователя с терминальными приложениями (, например подсказки rm
/ mv
/ find -ok
... ), выполняется на stdin+stderr.stderr будет открыт в режиме записи, где open, а в сеансах терминала будет указывать на терминал. stdout предназначен для обычного вывода команды, важно отделить его от сообщений взаимодействия с пользователем, чтобы можно было использовать перенаправление для сохранения или отправки -обработки обычного вывода. Наличие на stderr (известного заранее конкретного fd )вместо внутреннего fd, открытого на /dev/tty
, упрощает удаление этих сообщений (путем запуска команды с 2> /dev/null
, например )или используйте команду не -в интерактивном режиме.
Однако в случае с оболочкой это не особенно полезно. Выполнение sh 2> /dev/null
делает оболочку не -интерактивной (, что означает, что подсказки не отображаются, но имеет много других побочных эффектов ). Это означает, что можно отключить подсказки с помощью exec 2> /dev/null
, но это будет иметь побочный эффект, заключающийся в отбрасывании всех ошибок команд, если вы не запустите каждую команду с помощью cmd 2> something
. Опорожнение PS1, PS2, PS3, PS4 было бы намного лучше.
Это позволяет пользователю вводить данные с одного терминала, а вывод — на другой терминал, но я не понимаю, зачем кому-то это делать.
Возможная причина в том, что это было бы более надежным:
/dev/tty
как показано выше, может не работать в крайних случаях, когда нет управляющего терминала, ttyname()
может не работать, если /dev
не заполнен должным образом или при использовании chroot
с. Обратите внимание, что в некоторых других оболочках это хуже. csh
, tcsh
, rc
, es
, akanga
, fish
отображать приглашение и эхо того, что вы вводите на стандартный вывод (, хотя для fish
не приглашение, если стандартный вывод не терминал, и csh
который не имеет строки -редактор не выводит ничего echo
(, о котором заботится дисциплина линии tty терминального устройства )).
Включить поддержку заглушки EFI
Запустите make linux-menuconfig
и отредактируйте:
Processor type and features --->
[*] EFI runtime service support
[*] EFI stub support
[?] EFI mixed-mode support
Поддержка смешанного режима EFI -включена по умолчанию в настройках ядра.https://wiki.gentoo.org/wiki/EFI_Stub