本文目录导读:

检测系统启动速度通常需要分别测量 BIOS/UEFI 阶段、内核加载阶段、用户态服务启动阶段,以及桌面完全可用阶段,不同的操作系统有不同的检测方法。
以下是针对 Windows、Linux 和 macOS 的脚本检测方案。
Windows 系统
Windows 有强大的日志系统(ETW)和性能计数器,是检测启动速度的最佳途径。
使用 PowerShell 脚本分析事件日志(最常用)
Windows 会在事件日志中记录每个启动阶段的耗时。
# 检查系统启动时间(从内核加载到桌面可用)
# 来源:Event Log -> Microsoft-Windows-Diagnostics-Performance/Operational
$BootEvents = Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-Diagnostics-Performance/Operational'; Id=100} -MaxEvents 10
foreach ($event in $BootEvents) {
# 解析 XML 获取启动耗时(毫秒)
$xml = [xml]$event.ToXml()
$BootTime = ($xml.Event.UserData.EventData.Data | Where-Object {$_.Name -eq 'BootTime'} ).'#text'
$BootTimeSec = [math]::Round($BootTime / 1000, 2)
Write-Host "启动时间点: $($event.TimeCreated)"
Write-Host "总启动时间(到桌面就绪): $BootTimeSec 秒"
Write-Host "---"
}
# 更简单的命令(如果系统启用了快速启动/混合关机)
# 使用 Measure-Command 可以获取系统启动后运行时间
$Uptime = (Get-Date) - (Get-CimInstance Win32_OperatingSystem).LastBootUpTime
Write-Host "系统已运行: $($Uptime.TotalSeconds) 秒"
进阶:分析各阶段耗时
# 提取更多详细信息(Phase 耗时)
$BootDetails = Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-Diagnostics-Performance/Operational'; Id=200} -MaxEvents 5
foreach ($event in $BootDetails) {
$xml = [xml]$event.ToXml()
$data = $xml.Event.UserData.EventData.Data
# 遍历所有 Phase 数据
foreach ($item in $data) {
if ($item.Name -match 'PhaseName|PhaseTime') {
Write-Host "$($item.Name): $($item.'#text')"
}
}
Write-Host "------"
}
使用 wpr (Windows Performance Recorder) 命令行
适合深度分析,但需要 Windows ADK 或 Windows SDK。
:: 开始录制启动跟踪 wpr -start boottrace :: 然后重启电脑,系统会自动记录启动过程 shutdown -r -t 60 :: 重启完毕后,停止录制并生成报告 wpr -stop C:\BootTrace.etl :: 查看报告(需要 xperf 或 WPA 分析) xperf C:\BootTrace.etl
Linux 系统
Linux 启动时间的黄金指标是 systemd-analyze,它直接解析 systemd 日志,精度很高。
使用 systemd-analyze(最推荐)
#!/bin/bash # 检测总启动时间(内核 + 用户态服务) echo "===== 总启动耗时 =====" systemd-analyze echo "" echo "===== 各阶段详细耗时 =====" systemd-analyze blame | head -20 echo "" echo "===== 关键时间点(固件->内核->初始化) =====" systemd-analyze critical-chain echo "" echo "===== 绘制 SVG 启动时间图 =====" systemd-analyze plot > /tmp/boot_plot.svg echo "SVG 图已保存在 /tmp/boot_plot.svg"
输出示例:
Startup finished in 2.480s (firmware) + 3.142s (loader) + 1.980s (kernel) + 5.641s (initrd) + 18.432s (userspace) = 31.675s
graphical.target reached after 18.432s in userspace
使用 dmesg 脚本(基于时间戳)
如果系统没有 systemd,可以解析内核日志。
#!/bin/bash
# 通过 dmesg 日志提取启动时间
echo "===== 内核启动耗时 (dmesg) ====="
# 获取最后一条日志的时间戳(单位:秒)
last_timestamp=$(dmesg | tail -1 | grep -oP '\[\s*\K[0-9]+\.[0-9]+')
echo "内核初始化耗时: ${last_timestamp} 秒"
echo ""
echo "===== 磁盘/服务启动耗时排序 ====="
dmesg | grep -E 'initcall|registered' | awk '{print $1, $0}' | sort -n | tail -10
# 检测第一个和最后一个进程启动时间
first_pid=$(ps -eo pid,lstart,comm --sort=pid | head -2 | tail -1)
last_pid=$(ps -eo pid,lstart,comm --sort=pid | tail -1)
echo "系统第一个进程: $first_pid"
echo "系统最后一个进程: $last_pid"
手动测量脚本(从按下电源到 SSH 可达)
#!/bin/bash
# 放在远程监控机器上运行,测试服务器启动快慢
SERVER_IP="192.168.1.100"
TIMEOUT=300 # 最长等待5分钟
echo "开始监控 $SERVER_IP 启动..."
START_TIME=$(date +%s)
while true; do
if nc -z -w 2 $SERVER_IP 22 2>/dev/null; then
END_TIME=$(date +%s)
ELAPSED=$((END_TIME - START_TIME))
echo "SSH 服务就绪,启动耗时: ${ELAPSED} 秒"
break
fi
CURRENT=$(( $(date +%s) - START_TIME ))
if [ $CURRENT -gt $TIMEOUT ]; then
echo "超时,服务器在 ${TIMEOUT} 秒内未启动。"
exit 1
fi
sleep 2
done
macOS 系统
macOS 使用 launchd 替代 systemd,其启动时间可以通过 log show 或者 sysctl 获取。
使用 sysctl(获取内核启动时间)
#!/bin/bash
# 获取系统启动以来的秒数(内核层面)
BOOT_TIME=$(sysctl -n kern.boottime | awk '{print $4}' | tr -d ',')
CURRENT_TIME=$(date +%s)
UPTIME=$((CURRENT_TIME - BOOT_TIME))
echo "系统已运行: ${UPTIME} 秒"
echo "系统启动时间: $(date -r $BOOT_TIME)"
使用 launchd 日志分析(macOS 特有)
#!/bin/bash # 分析启动过程中各服务的耗时 echo "===== 用户态服务启动耗时 =====" # 查找 launchd 启动记录(需要 root 权限) sudo log show --predicate 'process == "launchd" AND eventMessage contains "com.apple.xpc.launchd"' --last boot | head -30 # 更友好的方式:使用 system_profiler echo "" echo "===== 内核启动参数 =====" sysctl -n kern.bootargs 2>/dev/null || echo "未设置"
使用 PowerMetrics(图形化,可脚本导出)
macOS 内置的性能工具,可以通过命令行调用:
# 生成性能报告(包含启动分析) sudo powermetrics --samplers tasks --show-process-energy --show-process-wait-times -i 1000 -n 1 | grep -E "kernel_task|launchd" | head -5
通用脚本(跨平台使用 Python)
如果你需要编写一个跨平台检测脚本(不依赖特定日志),可以基于 系统运行时间 推测。
#!/usr/bin/env python3
"""
跨平台系统启动时间检测
注意:只能检测当前系统的运行时间,无法回测过去的启动速度。
"""
import platform
import time
def get_uptime_seconds():
system = platform.system()
if system == "Windows":
import ctypes
kernel32 = ctypes.windll.kernel32
# 获取最后一次启动的 tick
tick = kernel32.GetTickCount64()
return tick / 1000.0
elif system == "Linux":
with open('/proc/uptime', 'r') as f:
uptime_seconds = float(f.readline().split()[0])
return uptime_seconds
elif system == "Darwin": # macOS
import subprocess
output = subprocess.check_output(['sysctl', '-n', 'kern.boottime'])
# 解析类似: { sec = 1609459200, usec = 0 }
import re
match = re.search(r'sec = (\d+)', output.decode())
if match:
boot_time = int(match.group(1))
return time.time() - boot_time
return -1
else:
raise NotImplementedError(f"不支持的系统: {system}")
if __name__ == "__main__":
seconds = get_uptime_seconds()
print(f"系统已运行: {seconds:.2f} 秒 ({seconds/60:.2f} 分钟)")
注意事项
- 快速启动/混合关机(Windows):启用快速启动后,
GetTickCount64提供的启动时间会不准确,因为它类似于休眠恢复,而非完整重启。 - 权限问题:
- Windows 读取性能日志可能需要管理员权限。
- Linux
dmesg可能需要sudo才能查看完整内核日志。 - macOS
log show通常需要sudo。
- 测量位置:建议在外部监控机上运行脚本,通过 SSH/Ping 检测目标机器的启动时间,这样能涵盖 BIOS 自检和网络初始化时间,更接近用户感知。
- 多次测量:启动速度受硬件状态、后台服务、杀毒软件扫描影响很大,建议 重启 3-5 次,取中位数或平均值。
根据你的具体需求(是想回测上次启动速度,还是想监控当前的启动时长,或者是自动化测试多台机器),可以选择不同的脚本方案,最常见的是:Windows 用 PowerShell + EventLog,Linux 用 systemd-analyze。