Как я могу напечатать на стандартный вывод из ловушки, вызванной во время eval
Я ожидал, что следующий скрипт напечатает This is redirected to 'output'.
когда я нажимаю Ctrl+C:
#!/bin/bash
trap_function(){
trap '' EXIT INT TERM
echo "This is redirected to 'output'."
touch this_will_exist
}
trap trap_function EXIT INT TERM
eval "sleep 100" &> output
Вместо этого ничего не отображается, и текст переходит в файл output
, Как я могу избежать перенаправления изнутри trap_function
и текст отображается для пользователя?
echo "This is redirected to 'output'." > /dev/stdout
не имеет желаемого эффекта.
Я использую GNU bash версии 4.3.48 в Ubuntu 16.04.5 LTS.
1 ответ
Обходной путь должен иметь eval
запустить в подоболочке:
#!/bin/bash
trap_function(){
trap '' EXIT INT TERM
echo "This is redirected to 'output'."
touch this_will_exist
}
trap trap_function EXIT INT TERM
(eval "sleep 100") &> output
Чтобы понять, что происходит, нужно знать, что для того, чтобы bash печатал все, что отправляется на стандартный вывод (который является дескриптором файла 1), он устанавливает дескриптор файла 1 для текущего терминала. Это красиво объяснено здесь https://catonmat.net/bash-one-liners-explained-part-three.
&> output
заменяет терминал в файловом дескрипторе 1 и 2 на файл
output
. Итак, не осталось дескриптора файла, к которому
echo "..."
можно отправить, что будет отображаться в терминале. Следовательно, у нас есть два возможных решения:
Перенаправление на текущий терминал
Это работает с утилитой
tty
который возвращает текущий пользовательский терминал.
#!/bin/bash
trap_function(){
trap '' EXIT INT TERM
echo "This is redirected to 'output'." &>$(tty)
touch this_will_exist
}
trap trap_function EXIT INT TERM
eval "sleep 100" &> output
Однако захват этого вывода с помощью оболочки может оказаться невозможным.
Перенаправление через другой файловый дескриптор
Это решение требует, чтобы для текущего терминала был установлен дополнительный файловый дескриптор (например, 123). Мы можем просто использовать то, что уже установлено в файловом дескрипторе 1, прежде чем заменить его на
output
по
123>&1
. Затем мы можем установить файловый дескриптор
echo
(который является стандартным выводом) к тому, что мы сохранили в файловом дескрипторе 123:
#!/bin/bash
trap_function(){
trap '' EXIT INT TERM
echo "This is redirected to 'output'." >&123
touch this_will_exist
}
trap trap_function EXIT INT TERM
eval "sleep 100" 123>&1 &> output