我正在运行一个脚本,该脚本可以为我的 NAS 服务器自动执行 snapraid。这是我在网上找到的一个脚本,它在 Debian 9 上运行没有问题。我上周更新到 Debian 10,该脚本现在挂在 Debian 9 上没有的地方。我想我已经将问题范围缩小到了问题的范围并等待命令。
我已将脚本缩短为以下代码片段以进行测试,并且问题正在发生,这就是为什么我认为需要等待。
#!/bin/bash
# location of the snapraid binary
SNAPRAID_BIN="/usr/local/bin/snapraid"
# redirect all output to screen and file
> $TMP_OUTPUT
exec 3>&1 4>&2
# NOTE: Not preferred format but valid: exec &> >(tee -ia "${TMP_OUTPUT}" )
exec > >(tee -a "${TMP_OUTPUT}") 2>&1
# run the snapraid DIFF command
echo "###SnapRAID DIFF [`date`]"
$SNAPRAID_BIN diff
# wait for the above cmd to finish
wait
echo
echo "DIFF finished [`date`]"
我还运行 htop 来查看发生了什么,并且从 snapraid 命令创建的进程并没有结束。
wait 正在做它应该做的事情,等等,但是为什么这个方法以前有效而不是现在呢?
完整脚本在这里:https://pastebin.com/gJqnz875
答案1
进程内部tee
的替换不会退出,直到它的 stdin 上收到 eof 或发生一些错误。
EOF
而且,由于它的标准输入是一个管道,因此只有当其写入端的所有句柄都关闭时,它才会在其标准输入上得到一个。
因此,您必须保存原始的 stdout 和 stderr,然后在 之前wait
将它们重定向到原始文件;通过new>&old
导致fd 关闭来复制 fd old
。
exec {out}>&1 {err}>&2
exec > >(tee -a output) 2>&1
...
exec >&$out 2>&$err
wait $(pgrep -P "$$")
此外,只有在较新版本的 bash 中,wait
才会等待> >(...)
进程替换中运行的进程;这就是为什么我使用wait $(pgrep -P "$$")
而不是简单地使用wait
(pgrep -P
查找其父进程的进程)。另请参阅这里对于这个和其他相关的陷阱> >(...)
。