帮助我理解这个重定向和读取内置函数?

帮助我理解这个重定向和读取内置函数?

我有一个备份脚本,现在要求它在实际运行同步(以交互方式运行时)之前调用 git pull 脚本。同步按如下方式完成:

rsync aiSP --delete 

备份包含此重定向:

exec 2> "${const_logfile}" 

git pull脚本有以下两行:

printf '%s\n' "Shall we pull all the gits?  " 
read -rep "(You will have to enter your git password for each one.)  (y or N) " -n1 

当 rsync 运行时,其所有进度输出都会显示在终端中(而不会被塞进日志文件中)。rsync 中的任何错误都会添加到日志文件中。

当备份脚本调用 git pull 脚本时,printf 行显示在终端中,但读取的文本被塞入日志文件中(而不显示)。直接调用该脚本时不会发生这种情况。

于是我将这行重定向代码拉入一个仅包含该代码和 git pull 脚本调用的测试脚本中,因此我确定这是罪魁祸首。最后,我将重定向代码直接添加到 git pull 脚本中并直接调用该脚本,读取的文本再次无法显示在终端中并被发送到日志文件。

我希望 printf 文本和读取的文本遵循相同的路线?

我确信有一个简单的解释。或者复杂的。请为我解惑。

编辑:

Raj 很有帮助;谢谢,Raj!

然而,我还想了解更多;因此,如果有人知道有一篇文章讨论了什么是这些非同寻常的消息(Raj 是这样称呼它们的)以及为什么将它们发送到 stderr 是有用的,我很乐意阅读更多相关内容。

另外,关注的人可能想知道 read 的 -p 方面(来自这里):

-p prompt 在尝试读取任何输入之前,显示标准错误提示,不带尾随换行符。仅当输入来自终端时才显示提示。

答案1

回答的关键是你已经在问题中写过的内容:“当 rsync 运行时,其所有进度输出都会显示在终端中(并且不会被塞进日志文件中)。rsync 中的任何错误都会添加到日志文件中。”

这是因为该exec命令重定向了标准误差(但不是标准输出)将运行脚本的 shell 的输出写入日志文件。常规rsync输出写入 stdout(即终端),但错误消息写入 stderr(即日志文件)。

Linux 工具中通常使用的惯例是将“正常”输出写入 stdout,而将任何即使在输出重定向时也应该向用户显示的“异常”消息写入 stderr。

因此,read提示符也会写入 stderr,因为它旨在显示给用户。另一方面,printf旨在显示“常规”输出,因此它会写入 stdout(如果您想写入 stderr,您可以随时使用printf ... >&2)。

类似地,如果您希望read将提示写入 stdout,则可以使用read ... 2>&1。但如果 stdout 被重定向怎么办?

正确的解决方案是记住“初始” stderr,然后将其重定向到exec另一个文件描述符中(我们希望它是一个终端),并使用该描述符在“原始” stderr 上显示提示。

在你引用的那一行之前exec应该再放一行:

exec 3>&2

exec在下一个命令重定向之前,这会将文件描述符 2 (stderr) 复制到文件描述符 3。然后在read命令中使用以下重定向:

read ... 2>&3

这应该将提示read重定向到文件描述符 3,即原来的重定向之前的标准错误。

相关内容