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

Temporarily stop redirection to get user input

提问人:miken32 提问时间:10/1/2018 最后编辑:miken32 更新时间:10/2/2018 访问量:237

问:

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

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"

此时将显示提示,我可以输入响应,但输入不会返回到主脚本。为什么?


编辑以添加,如果我从函数中删除行,输入将被正确读取并返回,但当然不会显示对用户的提示,即使我执行此重定向:execread -rp "Prompt: " input >&6

bash io-重定向

评论

0赞 Barmar 10/1/2018
输入来自 FD 0,它不参与任何重定向。
0赞 miken32 10/1/2018
我知道,这就是我感到困惑的原因!
0赞 Barmar 10/1/2018
尝试在函数和主程序中使用不同的变量,而不是同时使用两者。input
0赞 Barmar 10/1/2018
可能与问题无关,但重定向应该使用而不是重复2>&1>"$logfile"
1赞 Barmar 10/2/2018
in中的提示是写给stderr的,而不是stdout的,所以使用read -pread -rp "Prompt: " input 2>&6

答:

1赞 Barmar 10/2/2018 #1

问题是该函数在执行之前将输出重定向到日志文件。但是,命令替换的工作原理是运行命令,并将其输出重定向到管道,并且您正在覆盖它。因此,nput 被写入文件,而不是管道。echo "$userInput"

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

我还修改了您的脚本以分别保存和恢复,而不是假设它们最初指向同一事物。另外,由于使用 ,我只在函数中保存/恢复该 FD。stdoutstderrread -pstderr

#!/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

请注意,它应该是重定向到此处,而不是 ; 精确地使用它,以便在重定向时可以使用它(在这种情况下重定向不太常见)。stderrstdoutread -pstderrstdoutstderr

评论

0赞 miken32 10/2/2018
标记为已接受,但我最终会使用您关于如何正确重定向命令的评论!read
1赞 Barmar 10/2/2018
为了完整起见,我已将其添加到答案中。