我编写了很多非交互式脚本,我希望所有输出都转到日志文件,并且屏幕上不显示任何内容。
为了解决这个问题,我一直在使用:
#!/bin/bash
exec &> logfile
echo "Step One:"
/some/command/one
echo "Step Two:"
/some/command/two
我想确保这是一个明智的方法。
如果我继续使用这种方法,是否会遇到任何重大缺点或问题?如果是这样,它们是什么以及如何最好地减轻它们(包括通过改变我的方法)。
答案1
将命令输出重定向到日志文件
将所有命令输出(包括错误消息)重定向到日志文件是非交互式 shell 脚本的标准做法。记录由 cron 运行或由其他外部事件触发的脚本的命令输出尤其有用,并且在此类用例中没有任何缺点。
我的许多 shell 脚本在开头附近都包含以下几行:
exec 1>>"$logfile"
exec 2>&1
这些重定向命令的顺序很重要。第一个exec
命令将所有写入重定向到stdout
(1) 流以追加 ( >>
) 到日志文件。第二个命令将对 (2) 流的所有写入重定向到(1) 当前指向的stderr
同一文件描述符。stdout
仅使用一个文件描述符来访问文件可确保写入按所需顺序发生。
如果使用 Bash,您可以将这些命令组合成一个执行相同操作的结构:
exec &>>"$logfile"
如果您希望每次运行脚本时清除日志文件中以前的条目,请仅使用单个>
重定向运算符(覆盖以前的内容):
exec &>"$logfile"
使用exec
内置函数进行输入/输出重定向是由 POSIX 定义指定的外壳命令语言,并且 exec
内置函数可在任何 POSIX 兼容 shell 中使用。
运行交互式 shell 时重定向
您可以在临时/一次性交互式 shell 会话中尝试将标准输出重定向到文件。运行后exec 1>outfile
,所有未来的命令都会将其输出打印到outfile
终端而不是终端。
您还可以尝试在交互式 shell 会话中重定向标准错误,但这可能会使交互式 shell 会话非常难以使用。
运行后exec 2>errorfile
,任何其他命令产生的标准错误都会按预期写入重定向的错误文件。然而,问题是今后,shell(在本例中为 Bash)将其提示打印到此文件,并且作为命令键入的任何文本也会重定向到此文件。某些 shell(例如 Bash)也会回显 to 接收到的stdin
字符stderr
。在其他情况下,例如dash
,对于 shell 会话的其余部分,您基本上是在盲目工作,因为根本没有任何内容发送到终端。这显然使得非常困难继续与 shell 交互。
作为猎户座指出和斯科特说,您可以在分别使用和尝试任何此类实验之前存储对默认描述符stdout
和文件描述符的引用 。完成实验后,您可以通过运行将打印恢复为标准错误, 并将打印恢复为标准输出。stderr
exec 3>&1
exec 4>&2
exec 2>&4
exec 1>&3
对于交互式使用,我建议在逐个命令的基础上重定向标准输出和标准错误流: .>> outfile 2>&1 command with arguments