bash 中的 exec 重定向

Rob*_*Rob 4 bash shell-script output

我写了很多非交互式脚本,我希望所有输出都转到日志文件并且屏幕上没有任何内容。

为了解决这个问题,我一直在使用:

#!/bin/bash

exec &> logfile
echo "Step One:"
/some/command/one
echo "Step Two:"
/some/command/two
Run Code Online (Sandbox Code Playgroud)

我想确保这是一个理智的方法。

如果我继续采用这种方法,我会遇到任何重大的缺点或问题吗?如果是这样,它们是什么以及如何最好地减轻它们(包括通过改变我的方法)。

Ant*_*gan 6

将命令输出重定向到日志文件

将所有命令输出(包括错误消息)重定向到日志文件是非交互式 shell 脚本的标准做法。记录由 cron 运行或由其他外部事件触发的脚本的命令输出记录特别有用,并且在此类用例中没有缺点。

我的许多 shell 脚本在开头附近包含以下几行:

exec 1>>"$logfile"
exec 2>&1
Run Code Online (Sandbox Code Playgroud)

这些重定向命令的顺序很重要。第一个exec命令将所有写入重定向到stdout(1) 流以将 ( >>)附加到日志文件。第二个命令将所有对stderr(2) 流的写入重定向到stdout(1) 当前指向的相同文件描述符。仅使用一个文件描述符来访问文件可确保写入按所需顺序进行。

如果使用 Bash,您可以将这些命令组合成一个执行相同操作的结构:

exec &>>"$logfile"
Run Code Online (Sandbox Code Playgroud)

如果您希望每次运行脚本时都清除日志文件中以前的条目,请仅使用一个>重定向操作符(覆盖以前的内容):

exec &>"$logfile"
Run Code Online (Sandbox Code Playgroud)

在使用exec内置的输入/输出重定向是由POSIX定义为指定的shell命令行语言exec内置可在任何兼容POSIX外壳。

运行交互式 shell 时的重定向

您可以在临时/一次性交互式 shell 会话中尝试将标准输出重定向到文件。运行后exec 1>outfile,所有未来的命令都会将其输出打印到outfile而不是终端。

您还可以尝试在交互式 shell 会话中重定向标准错误,但这会使交互式 shell 很难使用:

运行后exec 2>errorfile,任何进一步命令产生的标准错误都会写入重定向的错误文件——正如预期的那样。但是,问题是从现在开始,shell(在本例中为 Bash)会将其提示打印到此文件,并且任何键入为命令的文本也将重定向到此文件。一些 shell(例如 Bash)也会回显stdinto接收到的字符stderr。其他的,例如dash对于 shell 会话的其余部分,您实际上是在盲目工作,因为没有任何内容发送到终端,这显然使得继续与 shell 交互变得非常困难

正如 Orion 指出的那样,您可以在分别使用和尝试任何此类实验之前存储对默认stdoutstderr文件描述符的引用。完成实验后,您可以通过运行将打印恢复到标准错误并将打印恢复到标准输出。exec 3>&1exec 4>&2exec 2>&4exec 1>&3

对于交互使用,我建议通过重定向命令的基础标准输出和标准错误流上的命令:>>outfile 2>&1 command with arguments

  • 如果您害怕“丢弃”文件描述符,您可以随时保存它们。使用 `3>&1`、`4>&2` 然后你可以随时使用 `1>&3`、`2>&4` 当你想要它们回来时。 (2认同)
  • 我更新了我的答案,以解释重定向“stderr”如何使得继续与 shell 交互“非常困难”。我还纳入了存储文件描述符的技巧(谢谢,@orion)。 (2认同)