脚本如何检测系统启动速度

wen 实用脚本 1

本文目录导读:

脚本如何检测系统启动速度

  1. Windows 系统
  2. Linux 系统
  3. macOS 系统
  4. 通用脚本(跨平台使用 Python)
  5. 注意事项

检测系统启动速度通常需要分别测量 BIOS/UEFI 阶段内核加载阶段用户态服务启动阶段,以及桌面完全可用阶段,不同的操作系统有不同的检测方法。

以下是针对 WindowsLinuxmacOS 的脚本检测方案。

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} 分钟)")

注意事项

  1. 快速启动/混合关机(Windows):启用快速启动后,GetTickCount64 提供的启动时间会不准确,因为它类似于休眠恢复,而非完整重启。
  2. 权限问题
    • Windows 读取性能日志可能需要管理员权限。
    • Linux dmesg 可能需要 sudo 才能查看完整内核日志。
    • macOS log show 通常需要 sudo
  3. 测量位置:建议在外部监控机上运行脚本,通过 SSH/Ping 检测目标机器的启动时间,这样能涵盖 BIOS 自检和网络初始化时间,更接近用户感知。
  4. 多次测量:启动速度受硬件状态、后台服务、杀毒软件扫描影响很大,建议 重启 3-5 次,取中位数或平均值。

根据你的具体需求(是想回测上次启动速度,还是想监控当前的启动时长,或者是自动化测试多台机器),可以选择不同的脚本方案,最常见的是:Windows 用 PowerShell + EventLog,Linux 用 systemd-analyze

抱歉,评论功能暂时关闭!