文章程式碼顯示

2018年8月2日 星期四

一起學 Python 117 : 使用 Python 藉由 ssh 至 Rapsberry pi 及 sftp 上傳/下載 文件

我寫了一個 class 幫助我快速的操作 Rpi 如下

'''''
上傳/下載 文件 ( 電腦 <-> Raspberry pi )
電腦對 Rpi 發送 SSH command 
'''''
#-*- coding:utf-8 -*-
import os
import sys
import paramiko

# 須安裝 parmiko 庫
# pip install paramiko

class mySSH(object):

    def __init__(self,hostname,port,username,password):
        self.ssh = paramiko.SSHClient() # 創建 SSH 物件        
        self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        self.sftp_T = paramiko.Transport((hostname,port)) #建立sftp加密連線
        self.hostname = hostname
        self.port = port
        self.username = username
        self.password = password
    

    # == 單行指令 ==
    def send(self,command):
        try:            
            '''''
            ssh.exec_command(comment) #執行命令並獲取命令結果
            stdin為輸入的命令
            stdout為命令返回的結果
            stderr為命令錯誤時返回的結果'''''
            print("發送 comment = '%s'"%command)
            stdin, stdout, stderr = self.ssh.exec_command(command)
            res ,err = stdout.read(), stderr.read()
            result = res if res else err      
            return str(result)
        except Exception as msg:
            print(str(msg))
    
    # == 多行指令 ==
    def send_muti(self,command):
        try:            
            '''''
            ssh.exec_command(comment) #執行命令並獲取命令結果
            stdin為輸入的命令
            stdout為命令返回的結果
            stderr為命令錯誤時返回的結果            '''''            
            for i in command:
                print("發送 comment = '%s'"%i)
                stdin, stdout, stderr = self.ssh.exec_command(i)           
            res ,err = stdout.read(), stderr.read()
            result = res if res else err
            print(result)
            return str(result)
        except Exception as msg:
            print(str(msg))
    
    # == Raspberry 重啟 ==
    def reBoot(self):
        self.ssh.connect(hostname=self.hostname, port=self.port, username=self.username, password=self.password)
        command = 'sudo reboot'
        result = self.send(command)
        self.ssh.close() #關閉連接

    # == 自 Raspberry 下載文件 ==
    def sftpGet(self,FILEPATH,PCPATH):
        try:
            username = 'root'
            password = 'sftp root 帳戶的密碼(可由sudo passwd root進行設置)'
            self.sftp_T.connect(username=username,password=password) #建立加密連線            
            self.sftp = paramiko.SFTPClient.from_transport(self.sftp_T) #建立一個sftp客戶端
            
            #Copy a remote file (remotepath) from the SFTP server to the local host
            self.sftp.get(FILEPATH,PCPATH)            
            self.sftp_T.close()
            print("自 ", FILEPATH,, " 下載至 ",PCPATH, " 完成")
        except Exception as msg:
            print(str(msg))
    
    # == 上傳文件至 Raspberry ==
    def sftpUpLoad(self,FILEPATH,PCPATH):
        try:
            username = 'root'
            password = 'sftp root 帳戶的密碼(可由sudo passwd root進行設置)'
            self.sftp_T.connect(username=username, password=password)
            sftp = paramiko.SFTPClient.from_transport(self.sftp_T)
            sftp.put(PCPATH, FILEPATH)
            self.sftp_T.close()
            print(PCPATH, " 上傳至 ",FILEPATH, " 完成")
        except Exception as msg:
            print(str(msg))

if __name__=="__main__":
    hostname = 'Raspberry IP位址'
    port = Raspberry SSH 端口(若你沒特別更改過的話就輸入22)
    username = 'pi'
    password = '登入 SSH 的密碼'
    
    # 建立物件
    Rpi = mySSH(hostname, port, username, password)

    # 以下請依自己想測試的 method 進行選用

    # ==樹梅派重開機==
    Rpi.reBoot()

    # 發送單筆 command (記得開頭要 connect , 結尾要 close )
    Rpi.ssh.connect(hostname=hostname, port=port, username=username, password=password)
    Rpi.send('ls')    
    Rpi.ssh.close()

    # 發送多筆 command (記得開頭要 connect , 結尾要 close )
    Rpi.ssh.connect(hostname=hostname, port=port, username=username, password=password)
    Rpi.send_muti(['sudo su','ls'])    
    Rpi.ssh.close()

    # ==從 Rpi 的路徑下載文件至電腦==
    FILEPATH = '/home/pi/python_program/log_EqLineNotify.txt' #注意須完整指定路徑以及檔名
    PCPATH = 'log_EqLineNotify.txt' #注意須完整指定路徑以及檔名(此種寫法會把文件下載到與此.py檔相同路徑下)
    Rpi.sftpGet(FILEPATH ,PCPATH)

    # ==上傳文件==
    FILEPATH = '/etc/testfile.txt'
    FILEPATH_PCPATH = r"D:\USER\Desktop\testfile.txt" #注意須完整指定路徑以及檔名(亦可指定路徑),寫法如左
    Rpi.sftpUpLoad(FILEPATH,FILEPATH_PCPATH)
   



Sftp 上傳/下載部分,如何設置 root 帳戶請見下篇文章(很多資料夾須設定 root 帳戶才有辦法上傳文件)

一起學 Python 118 : 使用 Python 藉由 sftp 上傳文件至 Rapsberry pi 開啟 root 權限


有關於使用 python 從 Raspberry sftp 上傳以及下載文件可參考以下

Python + Paramiko实现sftp文件上传下载
Python黑帽子——通过Paramiko使用SSH
系統運維工程師的法寶:python paramiko
python模块paramiko与ssh


↓↓↓ 連結到部落格方針與索引 ↓↓↓

Blog 使用方針與索引