Временно остановить перенаправление, чтобы получить ввод пользователя - PullRequest
0 голосов
/ 01 октября 2018

У меня есть скрипт, который использует довольно стандартный метод для захвата всего в файл журнала:

exec 6>&1 1>"$logFile" 2>"$logFile"

# do stuff

exec 1>&6 2>&6 6>&-

Теперь я хочу захватить некоторый пользовательский ввод, но я не могу получить пользователяданные возвращаются из функции.

#!/usr/bin/env bash

function getInput() {
    local userInput
    # disable redirection temporarily
    exec 1>&6 2>&6 6>&- 
    read -rp "Prompt: " userInput
    # restore redirection
    exec 6>&1 1>>"$logFile" 2>>"$logFile"
    echo "$userInput"
}

logFile="$HOME/foo.txt"

# enable redirection to the log file
exec 6>&1 1>"$logFile" 2>"$logFile"

input=$(getInput)

exec 1>&6 2>&6 6>&-

echo "Got $input"

Появляется подсказка, и я могу ввести ответ, но ввод не возвращается в основной скрипт.Почему?


Редактирование, чтобы добавить, что, если я удаляю строки exec из функции, ввод читается и возвращается правильно, но, конечно, подсказка для пользователя не отображается, даже если ясделать это перенаправление: read -rp "Prompt: " input >&6

1 Ответ

0 голосов
/ 01 октября 2018

Проблема в том, что функция перенаправляет вывод в файл журнала до того, как это сделает echo "$userInput".Но подстановка команды работает, выполняя команду с ее перенаправленным выводом в канал, и вы переопределяете это.В результате nput записывается в файл, а не в канал.

Вам необходимо сохранить перенаправление вывода и затем восстановить его до сохраненного значения, а не жестко кодировать файл журнала в функцию.

Я также изменил ваш скрипт, чтобы сохранять и восстанавливать stdout и stderr по отдельности, а не предполагать, что они изначально указывают на одно и то же.Кроме того, поскольку read -p использует stderr, я только сохраняю / восстанавливаю этот FD в функции.

#!/usr/bin/env bash

function getInput() {
    local userInput
    # disable redirection temporarily
    exec 8>&2 2>&7
    read -rp "Prompt: " userInput
    # restore redirection
    exec 2>&8 8>&-
    echo "$userInput"
}

logFile="$HOME/foo.txt"

# enable redirection to the log file
exec 6>&1 7>&2 1>"$logFile" 2>&1

input=$(getInput)

exec 1>&6 2>&7 6>&- 7>&-

echo "Got $input"

Но все это перенаправление действительно не нужно, вы можете просто перенаправить команду read:

read -rp "Prompt: " userInput 2>&7

Обратите внимание, что здесь должно быть перенаправлено stderr, а не stdout;read -p использует stderr именно так, чтобы его можно было использовать при перенаправлении stdout (в таких случаях редкость перенаправления stderr реже).

...