期望脚本中的退出处理程序不删除文件
Exit handler in expect script not removing file
我在编写 expect 脚本时遇到了一些问题。该脚本的目标是通过 SSH 连接到合作伙伴并获取网络配置信息。该信息保存在一个文件中,并复制回本地主机进行处理。然后在退出时从远程主机中删除该文件。
在正常情况下,一切正常,正如我所期望的那样。但是,如果用户在 SCP 过程中按 ^C 中断脚本,则文件不会从远程主机中删除。它留在那里。我不确定这是为什么或如何强制删除它。在这种情况下单步执行我的信号处理程序和退出处理程序时,似乎出于某种原因,退出处理程序认为该文件不存在并跳过 if 语句。不过我不知道为什么。
我已经从下面的脚本中复制了退出处理程序和信号处理程序。如果您有任何想法或看到任何明显的错误,请告诉我。我不确定从这里去哪里。
# Configure exit handler
exit -onexit {
# Remove configuration info file if it exists
if {[file exists ptinit.txt]} {
send "rm -rf ptinit.txt\r"
expect -exact "rm -rf ptinit.txt\r"
}
}
# Configure signal trap to remove partner file before exiting
proc errsig_handler {pidlst} {
send_user "\nStop command received from user. Exiting.\n"
for {set i [expr [llength $pidlst]-1]} {$i >= 0} {incr i -1} {
send_user "Current PID is: [lindex $pidlst $i]\n"
# If pid is not null and process is currently running, kill it
if {[lindex $pidlst $i] != "" && [exec kill -0 [lindex $pidlst $i] 2>/dev/null] == ""} {
send_user "PID [lindex $pidlst $i] is not null and is currently running.\n"
exec kill -9 [lindex $pidlst $i]
}
}
}
trap {errsig_handler $cur_pid} {INT TSTP}
更新:
我尝试了 Dinesh 建议的方法,但仍有问题。我更新了退出处理程序代码如下:
退出-onexit {
exp_internal 1
取消设置 expect_out(缓冲区)
# Remove configuration info file from remote server
send_user "\nIN EXIT HANDLER\n"
send "rm -rf ptinit.txt\r"
expect {
"rm -rf ptinit.txt\r" {
sleep 5
send "exit\r"
expect eof {puts "EOF in rm match received."; sleep 2}
}
"cannot remove" {
puts "File deletion was not successful - ptinit.txt needs to be deleted manually."
}
-re $prompt {
sleep 5
send "exit\r"
expect eof {puts "EOF received."; sleep 2}
}
}
send_user "LEAVING EXIT HANDLER\n"
}
我能让它工作的唯一方法是注释掉我的信号处理程序 for 循环,它会杀死生成的 PID。当取消注释时,退出处理程序期望超时。
不管怎样,文件仍然没有从远程系统中删除。这是我从 exp_internal 1:
看到的
Stop command received from user. Exiting.
IN EXIT HANDLER
send: sending "rm -rf ptinit.txt\r" to { exp9 }
Gate keeper glob pattern for '(%|#|>|$) $' is ''. Not usable, disabling the performance booster.
expect: does " \r\n" (spawn_id exp9) match glob pattern "rm -rf ptinit.txt\r"? no
"cannot remove"? no
"(%|#|>|$) $"? (No Gate, RE only) gate=yes re=no
expect: does " \r\nrm -rf ptinit.txt\r\n" (spawn_id exp9) match glob pattern "rm -rf ptinit.txt\r"? yes
expect: set expect_out(0,string) "rm -rf ptinit.txt\r"
expect: set expect_out(spawn_id) "exp9"
expect: set expect_out(buffer) " \r\nrm -rf ptinit.txt\r"
send: sending "exit\r" to { exp9 }
expect: read eof
expect: set expect_out(spawn_id) "exp9"
expect: set expect_out(buffer) "\n\rptinit.txt 0% 0 0.0KB/s --:-- ETA\rptinit.txt
100% 35 0.0KB/s 00:00 \r\nexit\r\n"
EOF in rm match received.
LEAVING EXIT HANDLER
tty_set: raw = 5, echo = 0
更新 2:
我将退出处理程序更新为以下内容:
exit -onexit {
exp_internal 1
unset expect_out(buffer)
# Remove configuration info file from remote server
set filename ptinit.txt
send_user "\nIN EXIT HANDLER\n"
send "rm -rf $filename\r"
expect {
"cannot remove" { puts "File deletion is not successful" }
-re $prompt { puts "File deleted" }
}
send_user "LEAVING EXIT HANDLER\n"
}
这是调试信息 - 仍然没有文件被删除。
Stop command received from user. Exiting.
IN EXIT HANDLER
send: sending "rm -rf ptinit.txt\r" to { exp9 }
Gate keeper glob pattern for '(%|#|>|$) $' is ''. Not usable, disabling the performance booster.
expect: does " \r\n" (spawn_id exp9) match glob pattern "cannot remove"? no
"(%|#|>|$) $"? (No Gate, RE only) gate=yes re=no
expect: does " \r\nrm -rf ptinit.txt\r\n" (spawn_id exp9) match glob pattern "cannot remove"? no
"(%|#|>|$) $"? (No Gate, RE only) gate=yes re=no
expect: does " \r\nrm -rf ptinit.txt\r\n\rptinit.txt 0% 0 0.0KB/s --:-- ETA" (spawn_id
exp9) match glob pattern "cannot remove"? no
"(%|#|>|$) $"? (No Gate, RE only) gate=yes re=no
expect: does " \r\nrm -rf ptinit.txt\r\n\rptinit.txt 0% 0 0.0KB/s --:-- ETA\rptinit.tx
t 100% 35 0.0KB/s 00:00 \r\n" (spawn_id exp9) match glob pattern "cannot remove"? no
"(%|#|>|$) $"? (No Gate, RE only) gate=yes re=no
expect: read eof
expect: set expect_out(spawn_id) "exp9"
expect: set expect_out(buffer) " \r\nrm -rf ptinit.txt\r\n\rptinit.txt 0% 0 0.0KB/s --
:-- ETA\rptinit.txt 100% 35 0.0KB/s 00:00 \r\n"
LEAVING EXIT HANDLER
tty_set: raw = 5, echo = 0
问题是因为 file exists
。无论您身在何处,它都会检查本地计算机中是否存在文件路径 运行 Expect
脚本, 不在远程目录中。
删除即可解决问题。
#This is a common approach for few known prompts
#If your device's prompt is missing here, then you can add the same.
set prompt "#|>|\$"; # We escaped the `$` symbol with backslash to match literal '$'
set filename ptinit.txt
send "rm -rf $filename\r"
expect {
"cannot remove" { puts "File deletion is not successful"}
-re $prompt { puts "File deleted" }
}
更新:
在您的代码中,您期望 rm -rf ptinit.txt\r
这是错误的。因为 expect
将看到发送到派生进程的内容(也就是 rm -rf ptinit.txt\r
)并匹配它。因此,它永远不会真正发送到生成的进程。
所以,你能为我给出的上述代码启用调试并在这里分享吗?
我在编写 expect 脚本时遇到了一些问题。该脚本的目标是通过 SSH 连接到合作伙伴并获取网络配置信息。该信息保存在一个文件中,并复制回本地主机进行处理。然后在退出时从远程主机中删除该文件。
在正常情况下,一切正常,正如我所期望的那样。但是,如果用户在 SCP 过程中按 ^C 中断脚本,则文件不会从远程主机中删除。它留在那里。我不确定这是为什么或如何强制删除它。在这种情况下单步执行我的信号处理程序和退出处理程序时,似乎出于某种原因,退出处理程序认为该文件不存在并跳过 if 语句。不过我不知道为什么。
我已经从下面的脚本中复制了退出处理程序和信号处理程序。如果您有任何想法或看到任何明显的错误,请告诉我。我不确定从这里去哪里。
# Configure exit handler
exit -onexit {
# Remove configuration info file if it exists
if {[file exists ptinit.txt]} {
send "rm -rf ptinit.txt\r"
expect -exact "rm -rf ptinit.txt\r"
}
}
# Configure signal trap to remove partner file before exiting
proc errsig_handler {pidlst} {
send_user "\nStop command received from user. Exiting.\n"
for {set i [expr [llength $pidlst]-1]} {$i >= 0} {incr i -1} {
send_user "Current PID is: [lindex $pidlst $i]\n"
# If pid is not null and process is currently running, kill it
if {[lindex $pidlst $i] != "" && [exec kill -0 [lindex $pidlst $i] 2>/dev/null] == ""} {
send_user "PID [lindex $pidlst $i] is not null and is currently running.\n"
exec kill -9 [lindex $pidlst $i]
}
}
}
trap {errsig_handler $cur_pid} {INT TSTP}
更新: 我尝试了 Dinesh 建议的方法,但仍有问题。我更新了退出处理程序代码如下: 退出-onexit { exp_internal 1 取消设置 expect_out(缓冲区)
# Remove configuration info file from remote server
send_user "\nIN EXIT HANDLER\n"
send "rm -rf ptinit.txt\r"
expect {
"rm -rf ptinit.txt\r" {
sleep 5
send "exit\r"
expect eof {puts "EOF in rm match received."; sleep 2}
}
"cannot remove" {
puts "File deletion was not successful - ptinit.txt needs to be deleted manually."
}
-re $prompt {
sleep 5
send "exit\r"
expect eof {puts "EOF received."; sleep 2}
}
}
send_user "LEAVING EXIT HANDLER\n"
}
我能让它工作的唯一方法是注释掉我的信号处理程序 for 循环,它会杀死生成的 PID。当取消注释时,退出处理程序期望超时。
不管怎样,文件仍然没有从远程系统中删除。这是我从 exp_internal 1:
看到的Stop command received from user. Exiting.
IN EXIT HANDLER
send: sending "rm -rf ptinit.txt\r" to { exp9 }
Gate keeper glob pattern for '(%|#|>|$) $' is ''. Not usable, disabling the performance booster.
expect: does " \r\n" (spawn_id exp9) match glob pattern "rm -rf ptinit.txt\r"? no
"cannot remove"? no
"(%|#|>|$) $"? (No Gate, RE only) gate=yes re=no
expect: does " \r\nrm -rf ptinit.txt\r\n" (spawn_id exp9) match glob pattern "rm -rf ptinit.txt\r"? yes
expect: set expect_out(0,string) "rm -rf ptinit.txt\r"
expect: set expect_out(spawn_id) "exp9"
expect: set expect_out(buffer) " \r\nrm -rf ptinit.txt\r"
send: sending "exit\r" to { exp9 }
expect: read eof
expect: set expect_out(spawn_id) "exp9"
expect: set expect_out(buffer) "\n\rptinit.txt 0% 0 0.0KB/s --:-- ETA\rptinit.txt
100% 35 0.0KB/s 00:00 \r\nexit\r\n"
EOF in rm match received.
LEAVING EXIT HANDLER
tty_set: raw = 5, echo = 0
更新 2:
我将退出处理程序更新为以下内容:
exit -onexit {
exp_internal 1
unset expect_out(buffer)
# Remove configuration info file from remote server
set filename ptinit.txt
send_user "\nIN EXIT HANDLER\n"
send "rm -rf $filename\r"
expect {
"cannot remove" { puts "File deletion is not successful" }
-re $prompt { puts "File deleted" }
}
send_user "LEAVING EXIT HANDLER\n"
}
这是调试信息 - 仍然没有文件被删除。
Stop command received from user. Exiting.
IN EXIT HANDLER
send: sending "rm -rf ptinit.txt\r" to { exp9 }
Gate keeper glob pattern for '(%|#|>|$) $' is ''. Not usable, disabling the performance booster.
expect: does " \r\n" (spawn_id exp9) match glob pattern "cannot remove"? no
"(%|#|>|$) $"? (No Gate, RE only) gate=yes re=no
expect: does " \r\nrm -rf ptinit.txt\r\n" (spawn_id exp9) match glob pattern "cannot remove"? no
"(%|#|>|$) $"? (No Gate, RE only) gate=yes re=no
expect: does " \r\nrm -rf ptinit.txt\r\n\rptinit.txt 0% 0 0.0KB/s --:-- ETA" (spawn_id
exp9) match glob pattern "cannot remove"? no
"(%|#|>|$) $"? (No Gate, RE only) gate=yes re=no
expect: does " \r\nrm -rf ptinit.txt\r\n\rptinit.txt 0% 0 0.0KB/s --:-- ETA\rptinit.tx
t 100% 35 0.0KB/s 00:00 \r\n" (spawn_id exp9) match glob pattern "cannot remove"? no
"(%|#|>|$) $"? (No Gate, RE only) gate=yes re=no
expect: read eof
expect: set expect_out(spawn_id) "exp9"
expect: set expect_out(buffer) " \r\nrm -rf ptinit.txt\r\n\rptinit.txt 0% 0 0.0KB/s --
:-- ETA\rptinit.txt 100% 35 0.0KB/s 00:00 \r\n"
LEAVING EXIT HANDLER
tty_set: raw = 5, echo = 0
问题是因为 file exists
。无论您身在何处,它都会检查本地计算机中是否存在文件路径 运行 Expect
脚本, 不在远程目录中。
删除即可解决问题。
#This is a common approach for few known prompts
#If your device's prompt is missing here, then you can add the same.
set prompt "#|>|\$"; # We escaped the `$` symbol with backslash to match literal '$'
set filename ptinit.txt
send "rm -rf $filename\r"
expect {
"cannot remove" { puts "File deletion is not successful"}
-re $prompt { puts "File deleted" }
}
更新:
在您的代码中,您期望 rm -rf ptinit.txt\r
这是错误的。因为 expect
将看到发送到派生进程的内容(也就是 rm -rf ptinit.txt\r
)并匹配它。因此,它永远不会真正发送到生成的进程。
所以,你能为我给出的上述代码启用调试并在这里分享吗?