python下的ssh都需要藉助第三方模組paramiko來實現,在使用前需要手動安裝。
一、python實現ssh
(1) linux下的ssh登入
root@ubuntu:~# ssh morra@192.168.1.42
The authenticity of host '192.168.1.42 (192.168.1.42)' can't be established.
ECDSA key fingerprint is SHA256:/ufx+/OLtdsYy7vsdk4KDu9xJsBp6zHonRAf2jjT0GI.
Are you sure you want to continue connecting (yes/no)? y
Please type 'yes' or 'no': yes
Warning: Permanently added '192.168.1.42' (ECDSA) to the list of known hosts.
Password:
Last login: Fri Dec 2 14:15:36 2016
localhost:~ morra$
檢視known_hosts檔案
root@ubuntu:~# cat .ssh/known_hosts
|1|ohKgSMq+1NLbr37anPqNZKQxh/8=|83NZfZYMUwLGaH32oLhCW/2PsXk= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBMTpJEzRyK6Bn96JT9+8IMK57ouWZspbs+oVuc7lD+aAwDB6C9Qgoy8P7cGjRaOA5ImDiBTLSQgHT+cZeGIJbI4=
(2) python實現ssh
import paramiko
#建立SSH物件
ssh = paramiko.SSHClient()
#把要連線的機器新增到known_hosts檔案中
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
#連線伺服器
ssh.connect(hostname='192.168.1.96', port=22, username='morra', password='123456')
cmd = 'ps'
#cmd = 'ls -l;ifconfig' #多個命令用;隔開
stdin, stdout, stderr = ssh.exec_command(cmd)
result = stdout.read()
if not result:
result = stderr.read()
ssh.close()
print(result.decode())
(3) python實現sftp
import paramiko
transport = paramiko.Transport(('192.168.1.96', 22))
transport.connect(username='morra', password='357447218')
sftp = paramiko.SFTPClient.from_transport(transport)
sftp.put('123.py', '/tmp/test.py') # 將123.py 上傳至伺服器 /tmp下並改名為test.py
sftp.get('remove_path', 'local_path') # 將remove_path 下載到本地 local_path
transport.close()
二、傳統的免密登入
(1) 生成公鑰
使用ssh-keygen生產公鑰和私鑰
morra@ubuntu:~$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/morra/.ssh/id_rsa):
Created directory '/home/morra/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/morra/.ssh/id_rsa.
Your public key has been saved in /home/morra/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:8IVM56bc/2deLZcDXwVs2XDNCuTTbvvlCKmCnUxiHuw morra@ubuntu
The key's randomart image is:
+---[RSA 2048]----+
| . ....o=o|
| o + ...+o+|
| . o + oo...|
| + = o. .|
| . S . .o .|
| = . . oo.+|
| + B . + o+=|
| E = . o **|
| .. o++|
+----[SHA256]-----+
#生成的公鑰私鑰存放在.ssh目錄下,id_rsa.pub就是本機的公鑰
morra@ubuntu:~$ cd .ssh/
morra@ubuntu:~/.ssh$ ls
id_rsa id_rsa.pub
(2) 複製公鑰
最後把本機的id_rsa.pub檔案中的內容copy到目標機的.ssh/authorized_keys中就可以了,如果沒有authorized_keys,自己建立。但是要注意authorized_keys的許可權一般是600
localhost:.ssh morra$ ls -l authorized_keys
-rw-r--r-- 1 morra staff 393 Dec 6 16:33 authorized_keys
或者直接使用一條命令也可以實現公鑰的複製,ssh-copy-id後面接入的使用者就是要支援免密登入的使用者。
morra@ubuntu:~/.ssh$ ssh-copy-id "morra@192.168.1.42"
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/morra/.ssh/id_rsa.pub"
The authenticity of host '192.168.1.42 (192.168.1.42)' can't be established.
ECDSA key fingerprint is SHA256:/ufx+/OLtdsYy7vsdk4KDu9xJsBp6zHonRAf2jjT0GI.
Are you sure you want to continue connecting (yes/no)? n^H
Please type 'yes' or 'no': yes
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
Password:
Number of key(s) added: 1
Now try logging into the machine, with: "ssh 'morra@192.168.1.42'" and check to make sure that only the key(s) you wanted were added.
#去目標機器下,檢查authorized_keys檔案
localhost:.ssh morra$ cat authorized_keys
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDB/mkvSx1mo/l/huMiOSqQjTb3KSB+D67qDRe1VgbjeZpwtodpSNueqGMj3mGDtf8tfmfwygKHuMtkVCQuD+1trLZ/yn8dKK9JV2pM4iwmaEvSda/qbQR7lQ37lsmvGnwCloJ49h8MpsF9UsDVXnyo4kauOj+0HYlur1E5Y7dzBuuzBiKAnwS66ZVTtHpIzubfXYanyBEinClpHNr6B7DVWp0J4ubZ8k/AgFMyD8NyJmugoObD3+wry0Dk2LG/WadOaY1luooQN4m55WyfZE2w0Kzi4F7W6v8/GRnpxVKOmNUNk6/c6hr/CDWnthS1abMjI9u/bGru6X2kiyymq3wR morra@ubuntu
(3) 登入測試
morra@ubuntu:~/.ssh$ ssh 'morra@192.168.1.42'
Last login: Tue Dec 6 16:28:07 2016 from 192.168.1.69
localhost:~ morra$
登入方式注意區別
$ ssh morra@192.168.1.42 #使用者名稱密碼登入
$ ssh 'morra@192.168.1.42' #公鑰免密登入
三、用pythonssh免密實現
(1) 免密ssh
import paramiko
private_key = paramiko.RSAKey.from_private_key_file('id_rsa96') #使用目標的私鑰來登入
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname='192.168.1.96',port=22,username='morra',pkey=private_key)
cmd = 'ps'
stdin, stdout, stderr = ssh.exec_command(cmd)
result = stdout.read()
if not result:
result = stderr.read()
ssh.close()
print(result.decode())
(2) 免密sftp
import paramiko
private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa')
transport = paramiko.Transport(('hostname', 22))
transport.connect(username='wupeiqi', pkey=private_key )
sftp = paramiko.SFTPClient.from_transport(transport)
sftp.put('/tmp/location.py', '/tmp/test.py')
# 將location.py 上傳至伺服器 /tmp/test.py
sftp.get('remove_path', 'local_path')
# 將remove_path 下載到本地 local_path
transport.close()
四、練手Demo
import paramiko
import uuid
class Haproxy(object):
def __init__(self):
self.host = '192.168.1.96'
self.port = 22
self.username = 'morra'
self.pwd = '123456'
self.__k = None
def create_file(self):
file_name = str(uuid.uuid4())
with open(file_name,'w') as f:
f.write('sb')
return file_name
def run(self):
self.connect()
self.upload()
self.rename()
self.close()
def connect(self):
transport = paramiko.Transport((self.host,self.port))
transport.connect(username=self.username,password=self.pwd)
self.__transport = transport
def close(self):
self.__transport.close()
def upload(self):
# 連線,上傳
file_name = self.create_file()
sftp = paramiko.SFTPClient.from_transport(self.__transport)
sftp.put(file_name, '/home/test.py') # 將location.py 上傳至伺服器 /tmp/test.pydef rename(self):
ssh = paramiko.SSHClient()
ssh._transport = self.__transport # 執行命令
stdin, stdout, stderr = ssh.exec_command('mv /home/test.py /home/test2.py')
result = stdout.read()
ha = Haproxy()
ha.run()