如何在 Expect 脚本中关闭 stderr 或退出后停止 "Connection to ... closed" 消息?

How to turn off stderr in Expect script or stop "Connection to ... closed" message after exiting?

所以我一直在尝试学习 bash 使用 expect 编写脚本,但我 运行 遇到了一个烦人的问题,即使我通过将 log_user 设置为 0 来关闭输出,当我退出 ssh 服务器时的注销消息仍然打印为“注销 与 blah.blah.blah 的连接已关闭”。采用 hackish 方式并在脚本中发出 exit 命令是不可取的,并且忽略了在终端中打印新行,留下难看的终端提示。我如何抑制或在我的期望脚本中关闭此连接关闭消息?这是我的期望脚本的代码模板:

#!/usr/bin/expect -f
#-f flag tells expect to read commands from file

# Set Password Prompt and Password
set PASSP "password:"
set PASSW "your_password_here\n"

# Set SFTP Prompt 
set SFTP "sftp> "

# Set Remote Prompt and Project Directories
# The GL server is super weird, so make sure RPROMPT ends in the
# name of the project compilation directory and PROJDIR is the 
# relative path (from home but without the tilde) of the main 
# project directory.

set RPROMPT "projdir_here]"
set PROJDIR "path_to_projdir_here"

# Set SSH Address
set ADDRESS your_username_here@your_address_here

# Annoying long output turned off
log_user 0

send_user "Logging in...\n"

spawn sftp $ADDRESS
expect $PASSP
send $PASSW

expect $SFTP
send_user "Uploading necessary files...\n"

send "cd $PROJDIR\n"
expect $SFTP
send "put *.cpp .\n"
expect $SFTP
send "put *.h .\n"
expect $SFTP
send "put Makefile .\n"
expect $SFTP
send "exit\n"

spawn ssh $ADDRESS
expect $PASSP
send $PASSW
expect "]"
send "cd $PROJDIR\n"

expect $RPROMPT
send_user "Cleaning remote directory...\n"

send "make clean\n"

# Output turned on temporarily so compiler feedback can be determined
expect $RPROMPT
log_user 1
send_user "Compiling on server...\n"

send "make\n"

# Turn off output and submit (this assumes that your makefile has a 'submit'
# target with the command to submit your file there)
expect $RPROMPT
log_user 0
send_user "\nSubmitting Requisite Files...\n"

send "make submit\n"

expect $RPROMPT
send_user "Quitting...\n"

# I can't figure out how to turn off stderr in expect so that an annoying 'connection closed' 
# message is printed even the log_user has been set to 0
send "logout\n"

# Transfer control to user
interact

您可以看到,在程序的最后,在我使用 interact 命令之前,在发送 "logout\n" 并关闭与服务器的连接后打印了有问题的消息。尽管上面 log_user 被设置为 0,但还是会发生这种情况。我究竟该如何关闭脚本中的 stderr 输出?我什至在 expect man page 查看了 expect 的手册页,但那里似乎没有多大用处。我不明白如何在 expect 脚本中关闭 stderr 以便不打印此消息,将不胜感激!我真的只是希望脚本在我注销时保持安静。因为很明显我发出了注销命令,所以我不确定为什么这个输出会转到 stderr。 ssh有没有在用户退出时不输出"Connection to...closed"信息的命令?如果我可以通过管道将 stderr 遗忘或以某种方式抑制它会更好。常规方法似乎不起作用,因为这是一个 expect 脚本。

只是log_user的用法不正确而已。它应该用作,

log_user 0
send "logout\r"  
expect eof
log_user 1

请注意,我在发送 logout\r 后期待 eof 模式,因为它会导致连接关闭。在使用 send 命令时,始终使用 \r 代替 \n

阅读 here 以了解有关 log_user 抑制输出的更多信息。

与其提示定义为静态字符串,不如将其概括为,

# We escaped the `$` symbol with backslash to match literal '$' 
# The last dollar sign represents line-end.
set prompt "#|>|%|\$ $"; 

虽然使用了 expect,但我们必须伴随 -re 标志以将其指定为正则表达式。

expect -re $prompt

SshDemo.exp

#!/usr/bin/expect 
set prompt "#|>|\$ $"
spawn ssh dinesh@myserver
expect {
        "(yes/no)" { send "yes\r";exp_continue}
        "password"
}
send "welcome123\r"
expect -re $prompt 
# Simply executing 'ls -l' command...
send "ls -l\r"
expect -re $prompt
log_user 0
send "logout\r"
expect eof
log_user 1

这是我根据上述建议改进后的新脚本。我还决定使用 scp 而不是 sftp,因为它更简洁,而且我只上传文件。

#!/usr/bin/expect -f
#-f flag tells expect to read commands from file

# Set Password Prompt and Password
set PASSP "password: "
set PASSW "your_password_here"

# Set Remote Prompt and Project Directories
# The ssh server is super weird, so make sure PROJDIR is the 
# directory name of the main project directory and PATH is
# the relative path to the project directory from home (with the tilde)

set PROJDIR "your_projdir_name_here"
set PATH "your_projdir_path_here"

# Set SSH Address
set ADDRESS your_username_here@source_hostname_here

# Turn off annoying output
log_user 0

send_user "Logging in and uploading necessary files...\n"

# upload files via scp, (shows upload prompt for user, concise)
spawn bash -c "scp *.cpp *.h Makefile $ADDRESS:$PATH"
expect $PASSP 
send "$PASSW\r"

interact

spawn ssh $ADDRESS
expect $PASSP
send "$PASSW\r"
expect "]"
send "cd $PATH\r"

expect "$PROJDIR]"
send_user "\nCleaning remote directory...\n"

send "make clean\r"

# Output turned on temporarily so compiler feedback can be determined
expect "$PROJDIR]"
log_user 1
send_user "Compiling on server...\n\n"

send "make\r"

# Turn off output and submit (this assumes that your makefile has a 'submit'
# target with the command to submit your file there)
expect "$PROJDIR]"
log_user 0
send_user "\n\nSubmitting Requisite Files...\n"

send "make submit\r"

expect "$PROJDIR]"
send_user "Quitting...\n"

send "logout\r"
expect eof

# Exit
exit