我有一个脚本,它使用一种非常标准的方法将所有内容捕获到日志文件中:
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 将写入文件,而不是管道。
您需要保存输出重定向,然后还原到该保存的值,而不是将日志文件硬编码到函数中。
我还修改了您的脚本以分别保存和恢复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
不太常见(。