同步等待 rsyslog flush 完成
wait synchronously for rsyslog flush to complete
我是 运行 rsyslogd 8.24.0,有一个本地日志文件。
我有一个测试运行一个程序,该程序执行一些系统日志记录(我的测试条目通过 rsyslog.conf 设置转到另一个文件)然后退出回到 shell 脚本以检查日志有预期的内容。这通常有效,但有时会失败,就好像日志记录没有发生一样。在执行检查之前,我已经向 shell 脚本添加了刷新(使用 HUP 信号)。我可以看到 HUP 已经发生并且正确的条目在日志中,但脚本的检查仍然失败。
shell 脚本是否可以等待刷新完成?我可以添加任意睡眠,但更希望有更明确的东西。
以下是 shell 脚本的相关部分:
# Set syslog to send dump_hook's logging to a local logfile...
sudo echo "user.* `pwd`/dump_hook_log" >> /etc/rsyslog.conf
sudo systemctl restart rsyslog.service
echo "" > ./dump_hook_log
# run the test program which does syslog logging
kill -HUP `cat /var/run/syslogd.pid` # flush syslog
if [ $? -ne 0 ]
then
logFail "failed to HUP `cat /var/run/syslogd.pid`: $?"
fi
echo "sent HUP to `cat /var/run/syslogd.pid`"
grep <the string I want> ./dump_hook_log >/dev/null
当测试报告失败时,有问题的字符串总是在 dump_hook_log 中,我已经去查看了。我想一定是在 grep 时刷新还没有完成。
这是一个例子:
在/var/log/messages
2019-01-30T12:13:27.216523+00:00 apx-ont-1 apx_dump_hook[28279]: Failed to open raw dump file "core" (Is a directory)
2019-01-30T12:13:27.216754+00:00 apx-ont-1 rsyslogd: [origin software="rsyslogd" swVersion="8.24.0" x-pid="28185" x-info="http://www.rsyslog.com"] rsyslogd was HUPed
Mod 日志文件的日期(n.b。这早于它包含的条目!):
rw-rw-rw- 1 nealec appexenv1_group 2205 2019-01-30 12:13:27.215053296 +0000 testdir_OPT/dump_hook_log
日志文件的最后一行(此处只有 apx_dump_hook 个条目):
2019-01-30T12:13:27.216523+00:00 apx-ont-1 apx_dump_hook[28279]: Failed to open raw dump file "core" (Is a directory)
脚本报告错误:
Wed 30 Jan 12:13:27 GMT 2019 PSE Test 0.2b FAILED: 'Failed to open raw dump file' not found in ./dump_hook_log
作为解决方案,这似乎有点重量级,但您可以使用系统的inotify
api 等待日志文件关闭(HUP 信号的结果)。例如,
inotifywait -e close ./dump_hook_log
将挂起,直到 rsyslogd
(或任何进程)关闭文件,届时您将收到消息
./dump_hook_log CLOSE_WRITE,CLOSE
程序将以 return 代码 0 退出。您可以添加超时。
我想我现在明白了。 HUP 导致 rsyslogd 关闭其打开的文件,但它不会重新打开文件,直到它需要记录到它。
考虑以下:
我使用 inotify 等待文件关闭,像这样:
case 9:
{
// Wait for the file, specified in argv[2], to be closed
int inotfd = inotify_init();
if (inotfd < 0) {
printf("inotify_init failed; errno %d: %s\n",
errno, strerror(errno));
exit(99);
}
int watch_desc = inotify_add_watch(inotfd, argv[2], IN_CLOSE);
if (watch_desc < 0) {
printf("can't watch %s failed; errno %d: %s\n",
argv[2], errno, strerror(errno));
exit(99);
}
size_t bufsiz = sizeof(struct inotify_event) + PATH_MAX + 1;
struct inotify_event* event = static_cast<inotify_event*>(malloc(bufsiz));
if (!event) {
printf("Failed to malloc event buffer; errno %d: %s\n",
errno, strerror(errno));
exit(99);
}
/* wait for an event to occur with blocking read*/
read(inotfd, event, bufsiz);
}
然后在我的 shell 脚本中等待:
# Start a process that waits for the log file be closed
${bin}/test_dump_hook.exe 9 "./dump_hook_log" &
wait_pid=$!
# Signal syslogd to cause it it close/reopen its log files
kill -HUP `cat /var/run/syslogd.pid` # flush syslog
if [ $? -ne 0 ]
then
logFail "failed to HUP `cat /var/run/syslogd.pid`: $?"
fi
wait $waid_pid
我发现这从来没有 returns。从另一个进程向 rsyslogd 发送 HUP 也不会中断等待,但是日志文件的猫(open/close 文件)会。
那是因为 shell 脚本中的 HUP 在其他进程等待它之前完成了。所以文件在等待开始时已经关闭,并且因为没有更多的日志记录到该文件,所以它不会重新打开并且在收到任何后续 HUP 时不需要关闭,所以事件永远不会发生以结束等待.
了解了这种行为后,如何在检查之前确定日志已经写入?我已经采用了这个解决方案;将一条已知消息放入日志中并等待它出现,我知道我正在等待的条目必须在此之前。像这样:-
function flushSyslog
{
logger -p user.info -t dump_hoook_test "flushSyslog"
# Signal syslogd to cause it it close its log file
kill -HUP `cat /var/run/syslogd.pid` # flush syslog
if [ $? -ne 0 ]
then
logFail "failed to HUP `cat /var/run/syslogd.pid`: $?"
fi
# wait upto 10 secs for the entry we've just logged to appear
sleeps=0
until
grep "flushSyslog" ./dump_hook_log > /dev/null
do
sleeps=$((sleeps+1))
if [ $sleeps -gt 100 ]
then
logFail "failed to flush syslog dump_hook_log"
fi
sleep 0.1
done
}
我是 运行 rsyslogd 8.24.0,有一个本地日志文件。
我有一个测试运行一个程序,该程序执行一些系统日志记录(我的测试条目通过 rsyslog.conf 设置转到另一个文件)然后退出回到 shell 脚本以检查日志有预期的内容。这通常有效,但有时会失败,就好像日志记录没有发生一样。在执行检查之前,我已经向 shell 脚本添加了刷新(使用 HUP 信号)。我可以看到 HUP 已经发生并且正确的条目在日志中,但脚本的检查仍然失败。 shell 脚本是否可以等待刷新完成?我可以添加任意睡眠,但更希望有更明确的东西。
以下是 shell 脚本的相关部分:
# Set syslog to send dump_hook's logging to a local logfile...
sudo echo "user.* `pwd`/dump_hook_log" >> /etc/rsyslog.conf
sudo systemctl restart rsyslog.service
echo "" > ./dump_hook_log
# run the test program which does syslog logging
kill -HUP `cat /var/run/syslogd.pid` # flush syslog
if [ $? -ne 0 ]
then
logFail "failed to HUP `cat /var/run/syslogd.pid`: $?"
fi
echo "sent HUP to `cat /var/run/syslogd.pid`"
grep <the string I want> ./dump_hook_log >/dev/null
当测试报告失败时,有问题的字符串总是在 dump_hook_log 中,我已经去查看了。我想一定是在 grep 时刷新还没有完成。
这是一个例子: 在/var/log/messages
2019-01-30T12:13:27.216523+00:00 apx-ont-1 apx_dump_hook[28279]: Failed to open raw dump file "core" (Is a directory)
2019-01-30T12:13:27.216754+00:00 apx-ont-1 rsyslogd: [origin software="rsyslogd" swVersion="8.24.0" x-pid="28185" x-info="http://www.rsyslog.com"] rsyslogd was HUPed
Mod 日志文件的日期(n.b。这早于它包含的条目!):
rw-rw-rw- 1 nealec appexenv1_group 2205 2019-01-30 12:13:27.215053296 +0000 testdir_OPT/dump_hook_log
日志文件的最后一行(此处只有 apx_dump_hook 个条目):
2019-01-30T12:13:27.216523+00:00 apx-ont-1 apx_dump_hook[28279]: Failed to open raw dump file "core" (Is a directory)
脚本报告错误:
Wed 30 Jan 12:13:27 GMT 2019 PSE Test 0.2b FAILED: 'Failed to open raw dump file' not found in ./dump_hook_log
作为解决方案,这似乎有点重量级,但您可以使用系统的inotify
api 等待日志文件关闭(HUP 信号的结果)。例如,
inotifywait -e close ./dump_hook_log
将挂起,直到 rsyslogd
(或任何进程)关闭文件,届时您将收到消息
./dump_hook_log CLOSE_WRITE,CLOSE
程序将以 return 代码 0 退出。您可以添加超时。
我想我现在明白了。 HUP 导致 rsyslogd 关闭其打开的文件,但它不会重新打开文件,直到它需要记录到它。 考虑以下: 我使用 inotify 等待文件关闭,像这样:
case 9:
{
// Wait for the file, specified in argv[2], to be closed
int inotfd = inotify_init();
if (inotfd < 0) {
printf("inotify_init failed; errno %d: %s\n",
errno, strerror(errno));
exit(99);
}
int watch_desc = inotify_add_watch(inotfd, argv[2], IN_CLOSE);
if (watch_desc < 0) {
printf("can't watch %s failed; errno %d: %s\n",
argv[2], errno, strerror(errno));
exit(99);
}
size_t bufsiz = sizeof(struct inotify_event) + PATH_MAX + 1;
struct inotify_event* event = static_cast<inotify_event*>(malloc(bufsiz));
if (!event) {
printf("Failed to malloc event buffer; errno %d: %s\n",
errno, strerror(errno));
exit(99);
}
/* wait for an event to occur with blocking read*/
read(inotfd, event, bufsiz);
}
然后在我的 shell 脚本中等待:
# Start a process that waits for the log file be closed
${bin}/test_dump_hook.exe 9 "./dump_hook_log" &
wait_pid=$!
# Signal syslogd to cause it it close/reopen its log files
kill -HUP `cat /var/run/syslogd.pid` # flush syslog
if [ $? -ne 0 ]
then
logFail "failed to HUP `cat /var/run/syslogd.pid`: $?"
fi
wait $waid_pid
我发现这从来没有 returns。从另一个进程向 rsyslogd 发送 HUP 也不会中断等待,但是日志文件的猫(open/close 文件)会。
那是因为 shell 脚本中的 HUP 在其他进程等待它之前完成了。所以文件在等待开始时已经关闭,并且因为没有更多的日志记录到该文件,所以它不会重新打开并且在收到任何后续 HUP 时不需要关闭,所以事件永远不会发生以结束等待.
了解了这种行为后,如何在检查之前确定日志已经写入?我已经采用了这个解决方案;将一条已知消息放入日志中并等待它出现,我知道我正在等待的条目必须在此之前。像这样:-
function flushSyslog
{
logger -p user.info -t dump_hoook_test "flushSyslog"
# Signal syslogd to cause it it close its log file
kill -HUP `cat /var/run/syslogd.pid` # flush syslog
if [ $? -ne 0 ]
then
logFail "failed to HUP `cat /var/run/syslogd.pid`: $?"
fi
# wait upto 10 secs for the entry we've just logged to appear
sleeps=0
until
grep "flushSyslog" ./dump_hook_log > /dev/null
do
sleeps=$((sleeps+1))
if [ $sleeps -gt 100 ]
then
logFail "failed to flush syslog dump_hook_log"
fi
sleep 0.1
done
}