Вопрос или проблема
Я пытаюсь связать веб-терминал с bash.
Моя текущая попытка сделать это заключается в создании оболочки, использующей FIFO-канал в качестве ввода, вот так:
Терминал 1
$ mkfifo pipe
$ bash <> pipe
file1 file2 file4
Терминал 2
$ echo "ls" > pipe
Как вы могли заметить, я получаю только ответы на команды, запуская оболочку в Терминале 1 (очевидно). Могу ли я определить, находится ли bash в простое время или нет? Мне нужно знать, когда показывать $PS1
на стороне клиента.
Если я выполняю что-то вроде apt-get install curl -y
, команда выполняется непрерывно и завершается, когда завершится. Мне нужно знать, когда это завершится, чтобы на фронтенде я мог показать приглашение терминала.
Есть идеи?
Вы можете использовать другой канал, где bash
(запущенный интерактивно) выводит ready
, когда он готов, через $PROMPT_COMMAND
:
$ mkfifo pipe ready
$ PS1= PS2= PROMPT_COMMAND='echo ready >&9' bash --norc --noediting -i <> pipe 9<> ready
done
В другом терминале:
$ read < ready
$ echo 'sleep 10; echo done' > pipe
$ if read < ready; then echo Ready to get more; else echo Terminated; fi
Ready to get more
Вместо вывода ready
, вы могли бы выводить "$?"
или "${PIPESTATUS[@]}"
, что позволило бы вам получить код завершения последней команды/конвейера в вашем другом терминале.
С опцией -i
вы получаете интерактивную оболочку, в которой оболочка читает ~/.bashrc
, выдает приглашение, и где readline используется для редактирования ввода, в результате чего вы видите эхо того, что напечатано (здесь отправлено через канал), все из чего не желательно здесь, поэтому мы отключаем их с помощью --norc
, --noediting
и устанавливаем строки приглашения P
rompt S
trings на пустые.
Есть еще несколько вещей, которые делает bash при интерактивном запуске, которые вы, возможно, захотите отключить, такие как расширение истории, расширение псевдонимов, управление заданиями.
Также будьте осторожны с тем, что некоторые вещи, такие как синтаксические ошибки, которые обычно завершают неинтерактивную оболочку, не завершают интерактивную, где вы возвращаетесь к приглашению вместо этого.
Ответ или решение
Чтобы определить, когда Bash завершает выполнение команды через FIFO (именованный канал), можно использовать подход с двумя FIFO каналами. Один канал будет использоваться для ввода команд в Bash, а другой — для получения уведомлений о том, что Bash готов принимать новые команды.
Вот шаги, которые помогут вам правильно настроить это взаимодействие.
Шаг 1: Создание FIFO каналов
В первом терминале создайте два FIFO канала:
$ mkfifo pipe ready
Шаг 2: Запуск Bash с использованием FIFO
Запустите Bash в интерактивном режиме, перенаправив его ввод и добавив специальную команду PROMPT_COMMAND
, которая будет отправлять сообщение о готовности Bash:
$ PS1= PS2= PROMPT_COMMAND='echo ready >&9' bash --norc --noediting -i < pipe 9<> ready
PS1=
иPS2=
убирают приглашения командной строки, чтобы они не отображались.PROMPT_COMMAND
будет отправлять строку "ready" в административный FD 9, когда Bash завершает выполнение команды и готов принимать новую.- Опция
--norc
отключает загрузку конфигурационных файлов, такие как~/.bashrc
, что может быть полезно для предотвращения нежелательного поведения. --noediting
отключает режим редактирования команд, чтобы не возникали конфликты.
Шаг 3: Отправка команд
Во втором терминале отправляйте команды через канал:
$ read < ready # Ожидайте, пока Bash будет готов
$ echo 'sleep 10; echo done' > pipe
Здесь сначала считывается готовность Bash, а затем отправляется команда, которую вы хотите выполнить.
Шаг 4: Ожидание завершения выполнения команды
После отправки команды вы можете снова считать с канала ready
, чтобы узнать, завершилась ли команда. Если команда завершена, Bash отправит строку "ready":
$ if read < ready; then echo Ready to get more; else echo Terminated; fi
Ready to get more
Дополнительно: Обработка статуса последней команды
Чтобы получать статус выполнения последней команды, можно отправить "$?"
или "${PIPESTATUS[@]}"
в ready
:
$ PROMPT_COMMAND='echo $? >&9' bash --norc --noediting -i < pipe 9<> ready
Это позволит вам получить код завершения последней команды, что может быть полезно для диагностики ошибок.
Заключение
Таким образом, с помощью двух FIFO каналов вы можете контролировать выполнение команд и получать уведомления о готовности Bash. Это обеспечит синхронизацию между вашим веб-терминалом и Bash, позволяя управлять выводом приглашения и состоянием выполнения команд в реальном времени.