我想在bash脚本提供一个可选的日志记录参数,并想用exec
给tee
管道从一开始。但是,打开tee
进程导致脚本挂起,我相信是因为未关闭stdout:
# Output to a log file, if set
if [[ $OPT_LOG ]]; then
exec > >(tee -a $OPT_LOG)
fi
Run Code Online (Sandbox Code Playgroud)
我试图用以下方法结束:
exec >&-
Run Code Online (Sandbox Code Playgroud)
但它仍然挂起-还有另一种方法可以正确关闭,tee
以便脚本在执行结束时正确退出吗?
由于某种原因,使用似乎会tee
停止出现提示($PS1
),因为shell脚本尚未退出。作为一种解决方法,我通常sleep
在致电后稍等片刻tee
。
#!/bin/bash
exec > >(tee -a mylog)
sleep .1
# my code
Run Code Online (Sandbox Code Playgroud)
将评论转换为答案,稍作修改。
我注意到:
以下代码在 Mac OS X 10.10.3 上退出正常。
Run Code Online (Sandbox Code Playgroud)OPT_LOG=file.name if [[ $OPT_LOG ]] then exec > >(tee -a $OPT_LOG) fi for ((i = 0; i < 10; i++)) do echo "Logging message $i at $(date)" sleep 1 done
您的问题可能出在您未显示的代码中。你在运行什么命令?你从中得到
bash -x yourscript.sh
什么?
如果您从示例中删除 sleep 和 date 调用,则脚本将不再正确退出,正如 Andrew 所说:
Run Code Online (Sandbox Code Playgroud)OPT_LOG=file.name; if [[ $OPT_LOG ]]; then exec > >(tee -a $OPT_LOG); fi; for ((i = 0; i < 10; i++)); do echo "Logging message $i"; done
我回应说:
这是一个有趣的观察!我可以重现你的结果。
我试验了一下:
pwd
在for循环之前添加了一个'just the echo',这不会影响事情(但pwd
可能是内置的Bash)。bash -c 'exit 0'
(它不是内置的)并且代码终止正常。> >(tee -a $OPT_LOG &)
但没有出现输出 - 在屏幕上或文件中。(我觉得这令人惊讶,但这是一种尝试的解决方法,而不是工作的主要部分。)我的印象是 Andrew 在 Bash 中发现了一个可以切实报告的错误。(有关如何执行此操作,请参阅有关报告错误的 Bash 手册。)我认为不会因为 I/O 重定向正常后没有执行任何外部命令而不退出。我可以确认Apple的Bash 3.2.57有问题;这样做的Bash 4.3.27(这是我为自己建造所以它与修复的补丁弹震错误)。
shell 脚本不调用任何外部命令是相对不寻常的,并且在 exec 重定向之后调用任何外部命令似乎可以抑制该错误。
它还证实了chatraed的解决方法有效,尽管速度比最低限度要慢。对于生产用途,我会选择sleep 0
,它比 快十分之一秒sleep 0.1
。几分之一秒的睡眠仅适用于某些系统;经典地(根据 POSIX),sleep
不会在几秒钟内休眠。OTOH,如果你写sleep 0.1
, 在不支持小数秒的系统上,包括前导0
可能使它休眠零秒;写作.1
可能会也可能不会产生相同的效果。
归档时间: |
|
查看次数: |
2724 次 |
最近记录: |