SFTP連線

tags: python ftp sftp

準備

安裝pysftp模組

# pip3 install pysftp

常用方法

方法名稱 說明 範例
pwd 目前路徑 print(sftp.pwd)
cwd() 移動目錄 sftp.cwd('/test')
list_dir() 取得目錄下所有檔案和目錄(僅名稱) sftp.list_dir()
listdir_attr() 取得目錄下所有檔案和目錄(含屬性) sftp.listdir_attr()
exists() 判斷檔案或目錄是否存在 sftp.exists('hello')
mkdir() 建立新的目錄 sftp.mkdir('hello')
put() 上傳檔案到目前路徑 sftp.put('a.txt', 'c.txt')
get() 下載目前路徑下的檔案 sftp.get('a.txt', 'b.txt')
isdir() 判斷檔案是否為目錄 sftp.isdir('hello')
isfile() 判斷檔案是否為檔案 sftp.isfile('a.txt')

補充

  • sftp為已連線的物件

說明

SFTP Server連線時會檢查HostKey,如果沒有提供的話會出現錯誤而造成無法連線,

AttributeError: 'Connection' object has no attribute '_sftp_live'

有幾種解決方式如下:

方式一:在~/.ssh/known_hosts加入Public Key

先使用ssh-keyscan工具掃描該站台的Public Key

$ ssh-keyscan example.com
example.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDj4CkA3SdT7TiPqHKMOa1u...

然後再將掃描得到的Public Key加入到~/.ssh/known_hosts檔案中

example.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDj4CkA3SdT7TiPqHKMO...

在Python內加入下面程式碼:

cnopts = pysftp.CnOpts(knownhosts='known_hosts') with pysftp.Connection(host, username, password, cnopts=cnopts) as sftp: ...

方式二:直接在程式碼裡面指定Public Key

keydata = b"""AAAAB3NzaC1yc2EAAAADAQABAAAAgQDj4CkA3SdT7TiPqHKMO...""" key = paramiko.RSAKey(data=decodebytes(keydata)) cnopts = pysftp.CnOpts() cnopts.hostkeys.add(host, 'ssh-rsa', key) with pysftp.Connection(host, username, password, cnopts=cnopts) as sftp: ...

方式三:第一次連線忽略Public Key,連線後再將Server傳過來的Key儲存下來

if cnopts.hostkeys.lookup(host) == None: print("發現新的SFTP站台,將允許該站台憑證 .....") # 將新的憑證存到變數裡 hostkeys = cnopts.hostkeys print(hostkeys.values()) # 將憑證檢查暫時關閉,避免第一次無法連線, cnopts.hostkeys = None with pysftp.Connection(host, username=username, password=password, cnopts=cnopts) as sftp: # 加入新的憑證 if hostkeys != None: print("連線到該新的SFTP站台並儲存該站台憑證") hostkeys.add(host, sftp.remote_server_key.get_name(), sftp.remote_server_key) hostkeys.save(pysftp.helpers.known_hosts())

補充:

如果該server並非使用標準的port 22,可以在pysftp.Connection()方法加上port=21參數來指定port。

範例程式(使用方式三)

import pysftp host = '??????????????' username = '?????????????' password = '???????????' cnopts = pysftp.CnOpts() hostkeys = None if cnopts.hostkeys.lookup(host) == None: print("發現新的SFTP站台,將允許該站台憑證 .....") # 將新的憑證存到變數裡 hostkeys = cnopts.hostkeys # 將憑證檢查暫時關閉,避免第一次無法連線, cnopts.hostkeys = None with pysftp.Connection(host, username=username, password=password, cnopts=cnopts) as sftp: # 加入新的憑證 if hostkeys != None: print("連線到該新的SFTP站台並儲存該站台憑證") hostkeys.add(host, sftp.remote_server_key.get_name(), sftp.remote_server_key) hostkeys.save(pysftp.helpers.known_hosts()) # 切換路徑 sftp.cwd('/aaron-test') # 目前所在路徑 print(sftp.pwd) # 取得目錄詳細內容 directory = sftp.listdir_attr() # 印出結果 for attr in directory: print(attr.filename, attr, sftp.isdir(attr.filename)) # 建立目錄 if not sftp.exists('hello'): sftp.mkdir('hello') # 上傳檔案 sftp.put('a.txt', 'c.txt') # 下載檔案 sftp.get('c.txt', 'b.txt') # 取得目錄所有內容 print(sftp.listdir())

練習

  1. 寫一sftp程式,可以顯示該目錄下的所有目錄和檔案,以及改目錄下的子目錄內所有內容
  2. 寫一sftp程式,可以下載該目錄下的所有檔案