这是我使用的测试脚本:
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
报告了什么?为什么它不能匹配其他工具报告的内容?
Linux 操作系统上的新二进制日志不像旧的二进制日志那样工作。
旧的二进制日志是
/var/log/wtmp
和/var/log/btmp
. 在系统引导时,将wtmp
使用用户名写入reboot
条目,在关闭时将wtmp
使用用户名写入条目shutdown
。查找系统重新启动的时间是使用last reboot
andlast shutdown
命令打印出这些条目的问题。新的二进制日志是 systemd 日志,它们没有这样的条目。
相反,每条日志记录都有一个名为boot ID的字段。
-o verbose
您可以通过选项来查看此内容journalctl
。引导 ID 由内核在引导时生成,并将systemd-journald
从内核获取的当前引导 ID 应用于每个日志记录,因为它正在将其添加到日志中。为了实现该
list-boots
功能,journalctl
扫描整个日志,读取每条记录的时间戳和引导 ID ,并记录与每个唯一引导 ID 相关联的最早和最新时间戳。因此,如果日志的某些部分被清除,或者相反地停留时间过长,则报告的明显启动和关闭时间
journalctl
将与实际的启动和关闭时间大不相同。/run/utmp
是一个终端登录记录表,带有用于启动和关闭的特殊条目。这些条目由uptime
和读取who -b
。它们是由systemd-update-utmp
类似 FreeBSDutx
命令的程序编写的,它们作为启动和关闭过程的一部分运行。它们不是最先或最后运行的,因为相关服务不是(并且实际上不能)绝对首先或最后订购。在运行时间之前可能存在具有相关引导 ID 的systemd-update-utmp reboot
日志条目,以及在运行时间之后的类似日志条目systemd-update-utmp shutdown
。进一步阅读