我有一个 bash 脚本,只要 Linux 机器开机就可以运行。我启动它如下所示:
( /mnt/apps/start.sh 2>&1 | tee /tmp/nginx/debug_log.log ) &
启动后,我可以在ps输出中看到 tee 命令,如下所示:
$ ps | grep tee
418 root 0:02 tee /tmp/nginx/debug_log.log
3557 root 0:00 grep tee
我有一个函数可以监视tee生成的日志的大小,并在日志达到一定大小时终止tee命令:
monitor_debug_log_size() {
## Monitor the file size of the debug log to make sure it does not get too big
while true; do
cecho r "CHECKING DEBUG LOG SIZE... "
debugLogSizeBytes=$(stat -c%s "/tmp/nginx/debug_log.log")
cecho r "DEBUG LOG SIZE: $debugLogSizeBytes"
if [ $((debugLogSizeBytes)) -gt 100000 ]; then
cecho r "DEBUG LOG HAS GROWN TO LARGE... "
sleep 3
#rm -rf /tmp/nginx/debug_log.log 1>/dev/null 2>/dev/null
kill -9 `pgrep -f tee`
fi
sleep 30
done
}
令我惊讶的是,杀死tee命令也会被 start.sh 实例杀死。为什么是这样?如何结束tee命令但让我的 start.sh 继续运行?谢谢。
终止时
tee
,提供它的命令将继续运行,直到它尝试写入更多输出。然后它将获得一个 SIGPIPE(在大多数系统上为 13),用于尝试写入没有读取器的管道。如果您修改脚本以捕获 SIGPIPE 并采取一些适当的操作(例如,停止写入输出),那么您应该能够在 tee 终止后继续它。
更好的是,为了简单起见
tee
,使用选项而不是杀死。logrotate
copytruncate
引用
logrotate(8)
:解释“为什么”
简而言之:如果写入失败没有导致程序退出(默认情况下),我们就会一团糟。考虑一下
find . | head -n 10
——您不想find
继续运行,扫描硬盘驱动器的其余部分,在head
已经占用了它需要的 10 行并继续之前。做得更好:在您的记录器内旋转
考虑以下根本不使用
tee
的示例:如果运行为:
...这将首先附加到
/tmp/nginx/debug_log
,将文件重命名/tmp/nginx/debug_log.old
为存在超过 100KB 的内容。因为记录器本身在进行旋转,所以当旋转发生时没有损坏的管道,没有错误,也没有数据丢失窗口——每一行都将被写入一个或另一个文件。当然,在本机 bash 中实现这一点效率很低,但以上只是一个说明性示例。有许多程序可以为您实现上述逻辑。考虑:
svlogd
,来自 Runit 套件的服务记录器。s6-log
,一个积极维护的替代 skanet 套件。multilog
来自 DJB Daemontools,该系列流程监督和监控工具的鼻祖。