You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过SSH捕获远程Linux机器启动日志并验证重启状态?

Python远程Linux重启脚本:捕获启动日志与验证重启状态问题解答

问题背景

目标:编写Python测试脚本,通过SSH对远程Linux机器执行重启命令,捕获启动日志并验证重启是否成功。
当前问题:使用Paramiko发送重启命令后机器可正常重启,但无法捕获启动日志,且代码未等待重启完成就执行完毕。

原代码片段

import paramiko
import time

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
    ssh.connect(host, username=username, password=password)
except paramiko.SSHException as e:
    ssh.get_transport().auth_none(username)  # 无密码认证

# 执行重启命令并捕获启动日志
stdin, stdout, stderr = ssh.exec_command("/sbin/reboot")
print(stdout.readlines())
print(stderr.readlines())

# 检查重启是否完成
exit_status = ''
msg = ''
while True:
    if stdout_channel.exit_status_ready():
        exit_status = ssh.stdout.channel.recv_exit_status()
        print("Exit status: %s" % exit_status)
        break
    time.sleep(10)

ssh.close()
if exit_status == 0:
    print("Reboot successful")
else:
    print("Reboot not successful")

执行输出

[]
[]
Exit status: 0
Reboot successful

问题解答

a) 如何捕获启动日志?

原代码无法捕获启动日志的核心原因:reboot命令执行后会立即返回退出状态码,SSH会话随即断开,而系统启动日志是在重启过程中产生的,无法通过当前SSH会话获取。

可行解决方案:

  • 步骤1:确保目标机器启动日志持久化
    大部分Linux系统默认会将启动日志保存到/var/log/boot.log,或通过systemd-journald持久化存储日志(可通过journalctl命令查看)。如果目标机器未开启日志持久化,可提前配置(比如修改rsyslog或journald配置)。
  • 步骤2:重启后重新连接读取日志
    待机器重启完成并恢复SSH服务后,重新建立SSH连接,执行日志读取命令:
    • 读取传统启动日志文件:cat /var/log/boot.log
    • 读取systemd启动日志:journalctl -b(-b表示查看本次启动的日志)

b) 如何正确检查重启完成后的状态?

原代码通过reboot命令的退出状态判断重启成功是错误的——reboot命令只要发送成功就会返回0,和机器是否完成重启无关。正确的验证逻辑如下:

  1. 发送重启命令后主动断开SSH连接
    执行reboot后,当前SSH会话会很快失效,无需等待,直接关闭连接。
  2. 循环尝试重新连接目标机器
    机器重启过程中SSH服务会中断,需要循环尝试连接,直到连接成功(说明机器已重启完成并恢复SSH服务)。
  3. 连接成功后验证重启状态
    可执行以下命令验证:
    • who -b:查看系统最后启动时间,确认是本次重启的时间
    • uptime:查看系统运行时长,确认时长较短(刚重启)
    • 检查关键服务状态(如systemctl status <service-name>)

修改后的完整代码示例

import paramiko
import time

def ssh_connect(host, username, password=None):
    ssh = paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    try:
        if password:
            ssh.connect(host, username=username, password=password, timeout=10)
        else:
            ssh.connect(host, username=username, timeout=10)
        return ssh
    except (paramiko.SSHException, TimeoutError):
        return None

def main():
    host = "your-remote-host"
    username = "your-username"
    password = "your-password"  # 无密码则设为None

    # 第一步:建立连接并发送重启命令
    ssh = ssh_connect(host, username, password)
    if not ssh:
        print("初始SSH连接失败")
        return

    print("发送重启命令...")
    stdin, stdout, stderr = ssh.exec_command("/sbin/reboot &")
    # 立即关闭连接,因为重启后会话会失效
    ssh.close()

    # 第二步:等待机器重启并尝试重新连接
    print("等待机器重启...")
    reconnect_attempts = 12  # 最多尝试12次,每次间隔10秒,共2分钟
    connected = False
    while reconnect_attempts > 0:
        time.sleep(10)
        ssh = ssh_connect(host, username, password)
        if ssh:
            connected = True
            break
        reconnect_attempts -= 1
        print(f"重新连接失败,剩余尝试次数:{reconnect_attempts}")

    if not connected:
        print("机器重启后无法重新连接,验证失败")
        return

    # 第三步:验证重启状态
    print("验证重启状态...")
    # 检查最后启动时间
    stdin, stdout, stderr = ssh.exec_command("who -b")
    boot_time = stdout.read().decode().strip()
    print(f"系统最后启动时间:{boot_time}")

    # 读取启动日志
    print("读取启动日志:")
    stdin, stdout, stderr = ssh.exec_command("journalctl -b --no-pager | head -50")  # 取前50行示例
    boot_log = stdout.read().decode()
    print(boot_log)

    # 检查系统运行时长
    stdin, stdout, stderr = ssh.exec_command("uptime")
    uptime_info = stdout.read().decode().strip()
    print(f"系统运行时长:{uptime_info}")

    ssh.close()
    print("重启验证完成,机器已成功重启")

if __name__ == "__main__":
    main()

内容的提问来源于stack exchange,提问作者Michael Tan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 03:20:52