[英]Extract EXPECT result to local variable/file
I've been struggling with getting the output from a remote server to a local variable or a local file.我一直在努力将 output 从远程服务器获取到本地变量或本地文件。
My attempt:我的尝试:
#!/bin/bash
my_pass=!!psw!!
server=10.10.10.10
/usr/bin/expect << ENDOFEXPECT
exp_internal 1 ;# expect internal debugging. remove when not needed
set PROMPT ":~ ?# ?"
set timeout 30
spawn bash -c "ssh root@$server"
expect "assword:"
send "$my_pass\r"
expect -re "$PROMPT"
send -- "df -kh /\r"
expect -re "df\[^\n]+\n.+\n(.+\r\n.+)\r\n"
set command_output $expect_out(1,string)
send_user "$command_output\r"
interact
ENDOFEXPECT
echo "====================="
echo " >> $command_output"
Output: Output:
spawn bash -c ssh root@10.10.10.10
parent: waiting for sync byte
parent: telling child to go ahead
parent: now unsynchronized from child
spawn: returns {154725}
expect: does "" (spawn_id exp4) match glob pattern "assword:"? no
Password:
expect: does "\rPassword: " (spawn_id exp4) match glob pattern "assword:"? yes
expect: set expect_out(0,string) "assword:"
expect: set expect_out(spawn_id) "exp4"
expect: set expect_out(buffer) "\rPassword:"
send: sending "!!psw!!\r" to { exp4 }
Gate keeper glob pattern for '' is ''. Not usable, disabling the performance booster.
expect: does " " (spawn_id exp4) match regular expression ""? (No Gate, RE only) gate=yes re=yes
expect: set expect_out(0,string) ""
expect: set expect_out(spawn_id) "exp4"
expect: set expect_out(buffer) ""
send: sending "df -kh /\r" to { exp4 }
Gate keeper glob pattern for 'df[^
]+
.+
(.+
.+)
' is ''. Not usable, disabling the performance booster.
expect: does " " (spawn_id exp4) match regular expression "df[^\n]+\n.+\n(.+\r\n.+)\r\n"? (No Gate, RE only) gate=yes re=no
expect: does " \r\n" (spawn_id exp4) match regular expression "df[^\n]+\n.+\n(.+\r\n.+)\r\n"? (No Gate, RE only) gate=yes re=no
Last login: Fri Dec 2 23:58:09 2022 from 10.10.10.1
Welcome to server image 2.2
expect: does " \r\nLast login: Fri Dec 2 23:58:09 2022 from 10.10.10.1\r\r\n\r\nWelcome to server image 2.2\r\n\r\n" (spawn_id exp4) match regular expression "df[^\n]+\n.+\n(.+\r\n.+)\r\n"? (No Gate, RE only) gate=yes re=no
REMY_SERVER:~ #
expect: does " \r\nLast login: Fri Dec 2 23:58:09 2022 from 10.10.10.1\r\r\n\r\nWelcome to server image 2.2\r\n\r\n\u001b[?1034h\u001b[1m\u001b[31mREMY_SERVER:~ # \u001b(B\u001b[m" (spawn_id exp4) match regular expression "df[^\n]+\n.+\n(.+\r\n.+)\r\n"? (No Gate, RE only) gate=yes re=no
expect: timed out
interact: received eof from spawn_id exp0
=====================
>>
Expected:预期的:
What I ultimately want is to get the output of df -kh
into a local variable or even better, append it directly to a local file (on the local machine, not the server on which the command is executed) so that it contains something like:我最终想要的是将
df -kh
放入局部变量或更好,append 直接放入本地文件(在本地机器上,而不是执行命令的服务器上),以便它包含类似:
$ cat ./result.txt
Filesystem Size Used Avail Use% Mounted on
/dev/sda1 20G 18G 1,7G 92% /
Method 1: The proper way is to not use expect and use key pair access:方法一:正确的方法是不使用expect,使用密钥对访问:
Step #1步骤1
Setup a SSH key pair (google it) and then copy the SSH key to the remote server.设置一个 SSH 密钥对(google 一下),然后将 SSH 密钥复制到远程服务器。 To do this I'd recommend using ssh-copy-id.
为此,我建议使用 ssh-copy-id。
Step #2第2步
Now with the ability to SSH to a server in place using a key, your above problem turns into this:现在有了使用密钥将 SSH 连接到服务器的能力,您的上述问题就变成了:
$ ssh root@10.10.10.10 "df -kh"
You can get fancy and use here documents (heredocs aka. here-docs) to further enhance this technique.您可以想象并使用此处文档(heredocs 又名 here-docs)来进一步增强此技术。
$ ssh root@10.10.10.10 <<EOF
> df -kh
> EOF
or put the commands in a file and pass them to ssh:或者将命令放在文件中并将它们传递给 ssh:
$ ssh root@10.10.10.10 < my.cmds
Method 2: Expect方法二:期待
See the following, expains how to use it properly and a tool to create expect scripts https://hostadvice.com/how-to/how-to-automate-tasks-in-ssh/请参阅以下内容,解释如何正确使用它以及创建期望脚本的工具https://hostadvice.com/how-to/how-to-automate-tasks-in-ssh/
First, your PROMPT regex is not matching.首先,您的 PROMPT 正则表达式不匹配。 I see the output has some colour codes in it:
我看到 output 中有一些颜色代码:
expect: does " \r\nLast login: ...REMY_SERVER:~ # \u001b(B\u001b[m" (spawn_id exp4) match regular expression ...
It's good to anchor prompt regexes, and to enclose them in braces.锚定提示正则表达式并将它们括在大括号中是很好的。 Try
尝试
set PROMPT { # \S*$}
Or, assuming the login shell is bash, set a new prompt that's easier to match:或者,假设登录 shell 是 bash,设置一个更容易匹配的新提示:
send "$my_pass\r"
expect "Welcome to server"
send -- "PS1='>'\r"
set PROMPT {>$}
expect -re $PROMPT
Next, the relevant code for the question.接下来是题目的相关代码。
send -- "df -kh /\r"
expect -re "df\[^\n]+\n.+\n(.+\r\n.+)\r\n"
set command_output $expect_out(1,string)
send_user "$command_output\r"
I'd adjust your regex a touch:我会调整你的正则表达式:
set cmd "df -kh /"
send -- "$cmd\r"
expect -re "$cmd\r\n(.+)\r\n.*$PROMPT"
Then you're capturing and "echoing" the result correctly然后您将正确捕获并“回显”结果
set command_output $expect_out(1,string)
send_user "$command_output\n"
# use a newline here ......^
And to append it to a local file:并将 append 写入本地文件:
set fh [open ./results.txt a]
puts $fh $command_output
close $fh
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.