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

Expect脚本:如何将远程命令输出拆分至多个变量

解决Expect脚本拆分日志文件名到独立变量的问题

看起来你已经搭好了基础的Expect脚本框架,现在就差把输出的三个日志文件名拆成独立变量,再加上抓取文件的逻辑对吧?我来一步步帮你搞定~

步骤1:从列表中提取独立变量

你的现有脚本里,Last3LogFiles已经是一个包含三个文件名的列表(因为cmd1的输出是每行一个文件名,lappend会把每行内容作为列表的一个元素存起来)。我们可以用Tcl的lindex命令直接从列表里提取每个元素,赋值给单独的变量:

# 在收集完Last3LogFiles之后添加这段代码
if {[llength $Last3LogFiles] == 3} {
    set log1 [lindex $Last3LogFiles 0]
    set log2 [lindex $Last3LogFiles 1]
    set log3 [lindex $Last3LogFiles 2]
    
    # 打印验证一下
    send_user "拆分后的日志文件名:\n"
    send_user "1. $log1\n"
    send_user "2. $log2\n"
    send_user "3. $log3\n"
} else {
    send_user "出错了:预期获取3个日志文件,但实际得到了[llength $Last3LogFiles]个\n"
    exit 1
}

步骤2:优化输出捕获逻辑

你原来的捕获输出的代码可以更精准一点,直接匹配每行的文件名(避免捕获多余字符),修改后的代码如下:

# 替换原有的set Last3LogFiles {}到expect -ex $prompt1的部分
set Last3LogFiles {}
expect {
    -re {^(\S+)\r\n} {  ;# 匹配每行的非空白字符(也就是文件名)
        lappend Last3LogFiles $expect_out(1,string)
        exp_continue  ;# 继续捕获下一行
    }
    -ex $prompt1 {  ;# 匹配到提示符就停止捕获
        # 啥也不用做,直接往下走
    }
}

步骤3:添加抓取日志文件的逻辑

这里给你两种方案,按需选择:

方案A:在SSH会话内直接下载(适合小文件)

直接在远程执行cat命令,把文件内容传回本地保存:

# 定义本地保存目录,改成你自己的路径
set local_dir "/your/local/logs"

# 先确保本地目录存在
if {![file exists $local_dir]} {
    file mkdir $local_dir
}

# 逐个下载文件
foreach log [list $log1 $log2 $log3] {
    send "cat $dir/$log\r"
    expect -re "^(.+)\r\n$prompt1" {
        set file_content $expect_out(1,string)
        # 写入本地文件
        set local_file [open "$local_dir/$log" w]
        puts $local_file $file_content
        close $local_file
        send_user "已保存$log到$local_dir\n"
    }
}

方案B:用SCP下载(更稳定,适合大文件)

如果日志文件比较大,用SCP更可靠,你可以在退出SSH会话后执行:

# 先退出当前SSH会话
send "exit\r"
expect eof

# 逐个用SCP下载
foreach log [list $log1 $log2 $log3] {
    spawn scp admin@10.30.35.36:$dir/$log $local_dir/
    expect {
        -re ".*Are.*.*yes.*no.*" {
            send "yes\r"
            exp_continue
        }
        "*?assword:*" {
            send "$passwd\r"
        }
    }
    expect eof
    send_user "已通过SCP下载$log\n"
}

完整优化后的脚本

#!/usr/bin/expect -f

set passwd "xxx"
set cmd1 "ls -ltr | tail -3 | awk '{print \$NF}'"
set dir "/cluster/storage/var/log/alarms"
set local_dir "/your/local/logs"  ;# 改成你的本地保存路径
set timeout 10  ;# 适当延长超时时间,避免下载超时
set prompt1 "*\$ "

log_user 0

# 建立SSH连接
spawn ssh admin@10.30.35.36
expect {
    -re ".*Are.*.*yes.*no.*" {
        send "yes\n"
        exp_continue
    }
    "*?assword:*" {
        send "$passwd\n"
    }
}

# 切换到日志目录
expect $prompt1 {
    send "cd $dir\r"
}

# 执行命令获取最近3个日志文件
expect $prompt1 {
    send "$cmd1\r"
}

# 捕获文件名到列表
set Last3LogFiles {}
expect {
    -re {^(\S+)\r\n} {
        lappend Last3LogFiles $expect_out(1,string)
        exp_continue
    }
    -ex $prompt1
}

# 拆分到独立变量
if {[llength $Last3LogFiles] == 3} {
    set log1 [lindex $Last3LogFiles 0]
    set log2 [lindex $Last3LogFiles 1]
    set log3 [lindex $Last3LogFiles 2]
    
    send_user "成功获取日志文件:\n"
    send_user "1. $log1\n"
    send_user "2. $log2\n"
    send_user "3. $log3\n"
} else {
    send_user "错误:预期3个日志文件,实际得到[llength $Last3LogFiles]个\n"
    exit 1
}

# 确保本地目录存在
if {![file exists $local_dir]} {
    file mkdir $local_dir
}

# 方案A:SSH会话内下载(小文件用这个)
foreach log [list $log1 $log2 $log3] {
    send "cat $dir/$log\r"
    expect -re "^(.+)\r\n$prompt1" {
        set file_content $expect_out(1,string)
        set local_file [open "$local_dir/$log" w]
        puts $local_file $file_content
        close $local_file
        send_user "已保存$log到$local_dir\n"
    }
}

# 退出SSH会话
send "exit\r"
expect eof

# 如果你想用方案B的SCP,注释掉方案A的代码,取消下面的注释
# foreach log [list $log1 $log2 $log3] {
#     spawn scp admin@10.30.35.36:$dir/$log $local_dir/
#     expect {
#         -re ".*Are.*.*yes.*no.*" {
#             send "yes\r"
#             exp_continue
#         }
#         "*?assword:*" {
#             send "$passwd\r"
#         }
#     }
#     expect eof
#     send_user "已通过SCP下载$log\n"
# }

exit 0

注意事项

  • 记得把$local_dir改成你实际要保存文件的本地路径
  • 如果远程服务器的提示符不是*$,请修改prompt1变量的值,确保能正确匹配
  • 可以根据文件大小调整timeout的值,避免超时错误

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:44:52