对于 SSH,我喜欢 Paramiko,因为它可以处理开销。为了演示,我编写了两个版本的代码:一个一直使用 Pexpect,另一个使用 Paramiko。请记住:
- 确保远程机器的IP地址不在
/root/.ssh/known_hosts中;否则会出现WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! 错误。
- 我更喜欢expect_exact,因为expect 使用正则表达式模式。使用
expect,如果您查找使用正则表达式字符的提示(例如$),您可能会收到错误消息。
- 如果我必须使用
root,我也更喜欢使用su - 而不是su,因为它会清除环境变量。
顺便说一句,谢谢你的问题。有时我会忘记我刚刚告诉您要记住的内容:facepalm:!
注意 - 使用两个 Debian VM 和 Python 3.9 进行测试。我更改了提示并隐藏了密码和 IP 地址。
使用 Pexpect(所有内容都回显到 STDOUT):
import sys
import pexpect
child = pexpect.spawn("su -", logfile=sys.stdout.buffer)
child.expect_exact("Password:")
child.sendline("**********")
child.expect_exact("#")
child.sendline("ssh user@192.168.X.X")
while True:
# Must use expect_exact to avoid expect regex conflict with prompt ($)!
index = child.expect_exact(
["Are you sure you want to continue connecting", "password:", "$", ])
if index == 0:
child.sendline("yes")
elif index == 1:
child.sendline("**********")
else:
break
child.sendline("cat hello.txt >> auth.txt")
child.expect_exact("$")
child.sendline("cat auth.txt")
child.expect_exact("$")
# If you do not use the logfile, you can make sure the file got copied using:
# print(child.before)
child.sendline("exit")
child.expect_exact("#")
child.sendline("exit")
# The child closes after the exit command (EOF); this is just to make sure
child.expect_exact(["$", pexpect.EOF, ])
child.close()
print("Script complete. Have a nice day.")
输出:
Password: **********
test@MACHINE12:~# ssh user1@192.168.X.X
ssh user1@192.168.X.X
The authenticity of host '192.168.X.X (192.168.X.X)' can't be established.
RSA key fingerprint is SHA256:********************************************
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
yes
Warning: Permanently added '192.168.X.X' (RSA) to the list of known hosts.
**********@192.168.X.X's password: **********
Last login: Sat Dec 4 20:40:12 2021 from 192.168.X.X
user1@192.168.X.X:~$ cat hello.txt >> auth.txt
cat hello.txt >> auth.txt
user1@192.168.X.X:~$ cat auth.txt
cat auth.txt
Hello, world!
user1@192.168.X.X:~$ b' cat auth.txt\r\nHello, world!\r\nuser1@192.168.X.X:~'
exit
exit
logout
Connection to 192.168.X.X closed.
test@MACHINE12:~# exit
exit
Script complete. Have a nice day.
Process finished with exit code 0
使用 Paramiko(无回显):
import paramiko
import pexpect
child = pexpect.spawn("su -")
child.expect_exact("Password:")
child.sendline("**********")
child.expect_exact("#")
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect("192.168.X.X", username="user1", password="**********")
ssh.exec_command("cat hello.txt >> auth.txt")
_, chan_out, _ = ssh.exec_command("cat auth.txt")
print("\nauth contents:", chan_out.read().decode())
ssh.close()
child.sendline("exit")
child.expect_exact(["$", pexpect.EOF, ])
child.close()
print("Script complete. Have a nice day.")
输出:
auth contents: Hello, world!
祝你的代码好运!