所以我有这个 Bash 脚本:
#!/bin/bash
PID=`ps -u ...`
if [ "$PID" = "" ]; then
echo $(date) Server off: not backing up
exit
else
echo "say Server backup in 10 seconds..." >> fifo
sleep 10
STARTTIME="$(date +%s)"
echo nosave >> fifo
echo savenow >> fifo
tail -n 3 -f server.log | while read line
do
if echo $line | grep -q 'save complete'; then
echo $(date) Backing up...
OF="./backups/backup $(date +%Y-%m-%d\ %H:%M:%S).tar.gz"
tar -czhf "$OF" data
echo autosave >> fifo
echo "$(date) Backup complete, resuming..."
echo "done"
exit 0
echo "done2"
fi
TIMEDIFF="$(($(date +%s)-STARTTIME))"
if ((TIMEDIFF > 70)); then
echo "Save took too long, canceling backup."
exit 1
fi
done
fi
基本上,服务器从 fifo 获取输入并输出到 server.log。 fifo 用于向服务器发送停止/启动命令以进行自动保存。最后,一旦它从服务器收到服务器已完成保存的消息,它就会 tar 数据目录并再次开始保存。
我在 exit 0
行遇到了麻烦。一切都执行得很好,但我得到了这个输出:
srv:scripts $ ./backup.sh
Sun Nov 24 22:42:09 EST 2013 Backing up...
Sun Nov 24 22:42:10 EST 2013 Backup complete, resuming...
done
但它卡在那里。请注意“done”如何回显但“done2”失败。某些原因导致它在 exit 0
处挂起。
附录:为了避免以后看到这个的人感到困惑,它卡在退出行并且永远不会返回到命令提示符。不确定我的原始描述是否足够清楚。
有什么想法吗?这是整个脚本,没有其他任何事情发生,我直接从 bash 调用它。
最佳答案
这是一个表现出相同行为的更小的自包含示例:
echo foo > file
tail -f file | while read; do exit; done
问题在于,由于管道的每个部分都在子 shell 中运行,exit
仅退出 while read
循环,而不是整个脚本。
然后它将挂起,直到 tail
找到一个新行,尝试写入它,并发现管道坏了。
要修复它,你可以更换
tail -n 3 -f server.log | while read line
do
...
done
与
while read line
do
...
done < <(tail -n 3 -f server.log)
通过从进程替换重定向,流程不必像在管道中那样等待 tail
完成,并且它不会在子 shell 中运行,因此 exit
实际上会退出整个脚本。
关于Bash 脚本 : `exit 0` fails to exit,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20184390/