暂时停止重定向以获取用户输入

时间:2018-09-30 21:48:47

标签: bash io-redirection

我有一个脚本,该脚本使用一种非常标准的方法将所有内容捕获到日志文件中:

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行,则会正确读取并返回输入,但是即使我执行了以下重定向,当然也不会显示对用户的提示:{{ 1}}

1 个答案:

答案 0 :(得分:1)

问题在于该函数在执行echo "$userInput"之前将输出重定向到日志文件。但是,通过运行命令并将其输出重定向到管道,命令替换可以起作用,您将对此进行覆盖。结果,nput被写入文件,而不是管道。

您需要保存输出重定向,然后还原到该保存的值,而不是将日志文件硬编码到函数中。

我还修改了您的脚本,以分别保存和恢复stdoutstderr,而不是假设它们最初指向的是同一事物。另外,由于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重定向到此处,而不是stdoutread -p精确地使用stderr,以便在重定向stdout时可以使用它(在这种情况下,重定向stderr不太常见)。