Ste*_*ski 7 io-redirection shell-script
我正在将旧的 ksh 脚本移植到 Bourne shell。旧的 ksh 脚本包含以下代码:
#!/bin/sh
tmpLog=/var/tmp/logfile.$$
exec 1> $tmpLog
exec 2>&1
eval $*
another_command_1
another_command_2
Run Code Online (Sandbox Code Playgroud)
从我读到的内容来看,这两个 exec 语句似乎是为了执行 $*、another_command_1、another_command_2 和所有以下命令;然后将这些命令中的所有 STDERR 和 STDOUT 重定向到/var/tmp/logfile.$$
. 但是,当我在脚本中运行它时,脚本在exec 2>&1
.
stefanl@host:~ $ sh -xv ./output.sh echo "Hello"
#!/bin/sh
tmpLog=/var/tmp/logfile.$$
+ tmpLog=/var/tmp/logfile.39918
exec 1> $tmpLog
+ exec
exec 2>&1
+ exec
stefanl@host:~ $
Run Code Online (Sandbox Code Playgroud)
当我在命令行上运行它时,我的外壳在我执行后冻结exec 2>&1
:
stefanl@host:~ $ tmpLog=/var/tmp/logfile.$$
stefanl@host:~ $ exec 1> $tmpLog
stefanl@host:~ $ exec 2>&1
### FREEZE ###
Run Code Online (Sandbox Code Playgroud)
我的问题:
exec 2>&1
应该做的?jw0*_*013 17
你的脚本没有失败 - 它工作得很好。您的理解是正确的,exec >logfile; exec 2>&1
将标准输出和标准错误都重定向到logfile
. 因此,您应该查看日志文件而不是终端以获取输出和错误信息。如果您直接在当前 shell 中执行这些重定向,看起来您的 shell 已冻结,因为您将所有输出都从终端发送出去。
请注意,xtrace
( set -x
) 选项的输出也会进入标准错误,它始终是文件描述符 2 ... 您将其发送到日志文件。你应该exec 2>&1
在那里找到它的其余部分。
这种形式的 exec(即没有命令)用于重定向当前 shell 解释器的所有后续输出。
来自 bash 的内置帮助:
$ 帮助执行 exec: exec [-cl] [-a name] [command [arguments ...]] [redirection ...] 用给定的命令替换 shell。 执行 COMMAND,用指定的程序替换这个 shell。 ARGUMENTS 成为 COMMAND 的参数。如果未指定 COMMAND, 任何重定向都在当前 shell 中生效。 [...]
我用来exec &> logfile
同时重定向 stdout 和 stderr。例如,我的大多数备份和 rsync 包装器脚本(或任何产生大量输出的脚本,我可能想在以后详细检查)以这样的方式开始:
$ help exec exec: exec [-cl] [-a name] [command [arguments ...]] [redirection ...] Replace the shell with the given command. Execute COMMAND, replacing this shell with the specified program. ARGUMENTS become the arguments to COMMAND. If COMMAND is not specified, any redirections take effect in the current shell. [...]
然后我从 cron 或在后台运行脚本,并tail -F
在脚本运行时用于观察日志文件。保存日志让我保留最近 7 次运行的输出(默认情况下为 7,savelog -c
可用于更改它)。