这是我使用的测试脚本:
last_reboot=$(last reboot | grep 'still running' | awk '{for (i=5; i<=NF; i++) printf $i FS}' | awk '{for (i=1; i<=NF - 2; i++) printf $i FS}')
if [ "$last_reboot" ]; then
date -d "$last_reboot" '+last reboot: %Y-%m-%d'
fi
days=$(uptime | awk '{print $3}')
hours=$(uptime | awk '{print $5}' | sed -E 's/,$//')
h=$(echo "$hours" | cut -d: -f 1)
m=$(echo "$hours" | cut -d: -f 2)
date -d "- $days days - $h hours - $m minutes" '+uptime: %Y-%m-%d'
who -b | awk '{print "who: " $3}'
journalctl --list-boots | awk '$1 == "0" {print "journalctl: " $4}'
在本地,所有四个日期都匹配。
我在大约 10 台服务器上运行它。last reboot
不报告任何内容(可能是因为wtmp
旋转了logrotate
)。uptime
并who -b
匹配。但journalctl
事实并非如此。具体报告什么journalctl --list-boots
?为什么它与其他工具的报告不匹配?
答案1
Linux 操作系统上的新二进制日志与旧二进制日志的工作方式不同。
旧的二进制日志是/var/log/wtmp
和/var/log/btmp
。在系统引导时,将wtmp
使用用户名写入一个条目,而在系统关闭时,将使用用户名reboot
写入一个条目。查找系统重新启动的时间只需使用和命令打印出这些条目即可。wtmp
shutdown
last reboot
last shutdown
新的二进制日志是 systemd 日志,它们没有这样的条目。
反而,每一篇日记记录有一个名为启动ID。您可以通过选项看到这-o verbose
一点journalctl
。引导 ID 由内核在引导时生成,并systemd-journald
在将其添加到日志时将从内核获取的当前引导 ID 应用于每个日志记录。
要实现该list-boots
功能,journalctl
请扫描整个期刊,读取时间戳和启动ID每条记录,并注意到最早和最晚的时间戳与每个唯一的启动 ID 相关联。
因此,如果日志的某些部分被清除,或者相反地停留时间过长,则报告的明显启动和关闭时间journalctl
将与实际启动和关闭时间有很大差异。
/run/utmp
是一个终端登录记录表,其中包含启动和关闭的特殊条目。这些条目由uptime
和读取who -b
。它们是由systemd-update-utmp
类似于 FreeBSD 命令的等程序编写的utx
,这些程序作为启动和关闭过程的一部分运行。它们不是最先或最后运行的,因为相关服务不是(而且实际上不能)绝对最先或最后订购的。可能存在具有相关引导 ID 的日志条目早于运行时间,以及类似的日志条目晚于运行systemd-update-utmp reboot
时间。systemd-update-utmp shutdown