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



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

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

问题是该函数在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,而不是stdout;read -p精确地使用stderr,以便在重定向stdout时可以使用它(在这种情况下重定向stderr不太常见(。

最新更新