我试图计算在SUSE系统(SLES11和SLES12系统)上重新引导所需的时间如下:
reboot_time = end_time - start_time
where
start_time is "time at which reboot command is triggered"
end_time is "time at which system is ready after booting process, finishing up startup and userspace programs" OR "time when login is prompted soon after reboot"我能认识start_time。但无法了解SLES11系统的time SLES11 (init.d SysV版本)。对于SLES12 (systemd初始化),systemd-analyze给出了所需的信息,但我无法为init.d系统找到可靠的方法。在SysV init系统或SLES11上是否有类似的替代方案,可以让我花在引导上的时间(启动内核、完成启动程序和完成用户空间初始化)?
发布于 2021-08-31 15:09:18
您可以使用以下命令获得(非第二次精确的)最后关机日期
last -x | egrep "shutdown|reboot" | head -1 | awk '{print $5" "$7" "$6" "$8}'last -x可以为您提供系统启动/重新启动和关闭时间,以及自系统创建以来的所有系统启动日志。问题是不显示年份,而且只有很小的分辨率。
last读取各种日志二进制日志文件(/var/ log /wtmp、utmp和btmp),您可以使用utmpdump实用工具获得关闭&用更精确的时间戳重新启动时间戳
utmpdump /var/log/wtmp | egrep "shutdown|reboot" | awk -F '[' '{print $9}' | sed 's/ ]//g'最终,您可以使用以下一行(非常长)获得从关机到重新启动所需的时间:
echo "System $(hostname) took $(($(date -d "$(LC_ALL=C utmpdump /var/log/wtmp 2>/dev/null| grep "reboot" | grep -Eo '[[:alpha:]]{3} [[:alpha:]]{3} [[:digit:]]{2} [[:digit:]]{2}:[[:digit:]]{2}:[[:digit:]]{2} [[:digit:]]{4}|[[:digit:]]{4}-[[:digit:]]{2}-[[:digit:]]{2}T[[:digit:]]{2}:[[:digit:]]{2}:[[:digit:]]{2}' | tail -1)" "+%s") - $(date -d "$(LC_ALL=C utmpdump /var/log/wtmp 2>/dev/null| grep "shutdown" | grep -Eo '[[:alpha:]]{3} [[:alpha:]]{3} [[:digit:]]{2} [[:digit:]]{2}:[[:digit:]]{2}:[[:digit:]]{2} [[:digit:]]{4}|[[:digit:]]{4}-[[:digit:]]{2}-[[:digit:]]{2}T[[:digit:]]{2}:[[:digit:]]{2}:[[:digit:]]{2}' | tail -1)" "+%s"))) to reboot"解释:
LC_ALL=C将输出以下命令,unlocalizedutmpdump /var/log/wtmp 2>/dev/null将列出所有事件,而2>/dev/null将重定向错误,而不必要的output.grep "reboot"或grep "shutdown"将筛选utmpdump输出,以显示仅重新启动或关机events'[[:alpha:]]{3} [[:alpha:]]{3} [[:digit:]]{2} [[:digit:]]{2}:[[:digit:]]{2}:[[:digit:]]{2} [[:digit:]]{4}'是捕获非本地化日期字符串的正则表达式,类似于"Fri Aug 02 00:01:27 2019",这些命令用于CentOS'[[:digit:]]{4}-[[:digit:]]{2}-[[:digit:]]{2}T[[:digit:]]{2}:[[:digit:]]{2}:[[:digit:]]{2}'是捕获看起来类似于"2021-08-17T10:11:03“的ISO 8601日期字符串的regex。这些都用于Debiandate -d "datestring",将日期转换为epoch$(command)是command$((x - y))的输出,用于数学运算(如减两个时代)您还可以使用utmpdump的输出来检索登录时间戳。请注意,关闭/重新启动周期与关闭/系统引导周期不同,因此这些命令必须适应您的使用。还要注意,任何强制的系统重置都不会包含在日志中,因此会给出虚假的值。
发布于 2021-08-31 13:18:25
也许有点麻烦,但您可能只是添加了一个最终执行的脚本,即/etc/init.d/K99WriteShutdownTime (其中K表示关闭脚本,数字越高,执行的时间越晚)。
这个脚本可能包含一些类似的内容
#!/usr/bin/env bash
timestamp_logfile="/var/log/shutdown_timestamp"
date +"%s" > "$timestamp_logfile"然后,您可以使用另一个脚本(如/etc/init.d/S99WriteGetTime )
#!/usr/bin/env bash
timestamp_logfile="/var/log/shutdown_timestamp"
boot_time_logfile="/var/log/boot_time.log"
if [ -f "$logfile" ]; then
boot_timestamp=$(date +"%s")
shutdown_timestamp=$(cat "$timestamp_logfile")
delta=$((boot_timestamp - shutdown_timestamp))
echo "$(date +"%Y-%m-%d %H:%M:%S"): It took $delta seconds to boot $(hostname)" >> boot_time_logfile
else
echo "$(date +"%Y-%m-%d %H:%M:%S"): No prior shutdown time detected. Cannot compute boot time" >> boot_time_logfile
fi发布于 2021-09-07 08:00:37
在init系统上(如SLES11),只有在启动所有启动程序之后才会向用户显示登录提示。因此,我们可以依赖于从wtmp文件获得登录提示时间(如用户"Orsiris“所建议的那样)。
下面是在上次重新启动后获得登录提示的python脚本。
#!/usr/bin/env python3
import subprocess
import re
from datetime import datetime
from typing import List
class UnableToFindLoginTimeError(Exception):
pass
class UnexpectedCommandException(Exception):
pass
class CommandResult:
def __init__(self, command, stdout, stderr, exit_code):
self.command = command
self.stdout = stdout
self.stderr = stderr
self.exit_code = exit_code
def validate(self, check_stderr=True, check_exit_code=True):
if (check_stderr and self.stderr) or (check_exit_code and self.exit_code != 0):
raise UnexpectedCommandException('Unexpected command result')
def run_command(command, timeout=600):
completed_process = subprocess.run(
command,
encoding='utf-8',
timeout=timeout,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
shell=True,
errors='ignore',
)
command_result = CommandResult(
stdout=completed_process.stdout.strip(),
stderr=completed_process.stderr.strip(),
exit_code=completed_process.returncode,
command=command,
)
return command_result
def _extract_data_in_square_brackets(row: str) -> List[str]:
"""
Extract data within square brackets from a string.
Example:
'[One] [Two ] [Three ] [Wed Aug 25 09:21:59 2021 UTC]'
returns
['One', 'Two', 'Three', 'Wed Aug 25 09:21:59 2021 UTC']
"""
regex = r'\[(.*?)\]'
columns_list = re.findall(regex, row)
return [item.strip() for item in columns_list]
def convert_datetime_string_to_epoch(datetime_str: str) -> int:
"""
Run following command to automatically parse datetime string (in any valid format) into epoch:
# date -d '{datetime_str}' +%s
Note: The Unix epoch is the number of seconds that have elapsed since January 1, 1970 (midnight UTC/GMT).
At any point of time, epoch will be same throughout all time zones.
Example: epoch for "Fri Sep 3 11:08:09 UTC 2021" will be 1630667289.
"""
command_result = run_command(f"date -d '{datetime_str}' +%s")
command_result.validate()
epoch = round(float(command_result.stdout.strip()))
return epoch
def get_login_time_from_wtmp() -> datetime:
"""
Read through /var/log/wtmp binary file using utmpdump
and find least LOGIN time after last reboot.
wtmp gives historical data of utmp (gives information about user logins, logouts, system boot etc.).
In case of failed logins, we see multiple entries for same tty in the output.
In such case, we get first occurred entry after last reboot since that is when
startup processes have been completed and welcome screen appeared.
Sample:
-------
Output:
[2] [00000] [~~ ] [reboot ] [~ ] [3.10.0-957.12.2.el7.x86_64] [0.0.0.0 ] [Mon Aug 16 06:21:06 2021 UTC]
[6] [01828] [tty1] [LOGIN ] [tty1 ] [ ] [0.0.0.0 ] [Mon Aug 16 06:21:26 2021 UTC]
[2] [00000] [~~ ] [reboot ] [~ ] [3.10.0-957.12.2.el7.x86_64] [0.0.0.0 ] [Wed Aug 25 09:21:34 2021 UTC]
[6] [01815] [tty1] [LOGIN ] [tty1 ] [ ] [0.0.0.0 ] [Wed Aug 25 09:21:59 2021 UTC]
Returns: "Wed Aug 25 09:21:59 2021 UTC" as datetime object
"""
command_result = run_command(f'utmpdump /var/log/wtmp | grep -e reboot -e LOGIN')
command_result.validate(check_stderr=False)
output = command_result.stdout
list_of_login_epochs = []
# read output in reverse order
for line in output.splitlines()[::-1]:
if 'reboot' in line:
# exit loop since we dont require data before last reboot
break
items = _extract_data_in_square_brackets(line)
if 'LOGIN' in items:
login_time_str = items[-1].strip()
epoch = convert_datetime_string_to_epoch(login_time_str)
list_of_login_epochs.append(epoch)
if not list_of_login_epochs:
raise UnableToFindLoginTimeError()
# collect least login time out of all since we need time at which login was prompted first.
least_epoch = min(list_of_login_epochs)
login_datetime_object = datetime.utcfromtimestamp(round(least_epoch))
return login_datetime_object
if __name__ == '__main__':
print(
f'Login screen was displayed to user after last reboot at {get_login_time_from_wtmp()} UTC'
)https://stackoverflow.com/questions/67777065
复制相似问题