星期日, 10月 25, 2015

Paramiko在Python執行 SSH 小記

最近因為工作的關係, 要在 JupyterHub 上面執行一些部署 script, 因為使用 jupyter 的關係, 所以就開始使用 python 來進行相關執行動作.

剛開始的做法是 使用 shell script 在主機上面執行, 確認可以自動安裝完成, 接下來就是在 JupyterHub 上面藉由執行 python notebook 來達成 執行 遠端 shell script 的目的.

Jupyter / JupterHub 的好處就是可以馬上執行, 並看到輸出的結果
我常用到的是 2 種 block
  • Markdown -- 用來說明之後要進行的程式目的
  • Cell - 根據開啟的 kernel 決定執行的程式語言, 我目前都是使用 python 3
螢幕快照 2015-10-24 下午5.32.25.png

既然使用 shell script 沒有問題, 接下來就是考慮如何用 python 去遠端執行指令了, 這個時候當然是想到 SSH. 既然要遠端執行指令, 那必要的要素就有:
  • 遠端的主機 FQDN 或是 IP
  • 遠端主機的登入使用者名稱
  • SSH Key

Google 了一下, python 在 ssh 的方案, 找了很多方式, 後來是使用 paramiko 這個方式

根據上述三個要素, 所以就先準備了 3 個 Markdown 還有 3 個 cell 來記錄相關資料讓等下的python 應用

  • 使用 REMOTEHOST 變數記錄遠端機器的 IP 或是 FQDN
  • 使用 USERNAME 變數記錄遠端的使用者名稱
  • 使用 KEYPATH 記錄使用者 SSH Key 私鑰路徑, 我最後有設計一個 block 把 Key 刪除
輸入完執行結果如下
螢幕快照 2015-10-24 下午5.45.26.png

接下來就是 paramiko 的執行方式

# 匯入 paramiko
import paramiko
# 定義 ssh 為使用 paramiko.SSHClient()
ssh = paramiko.SSHClient()
# 設定自動加入 遠端主機的 SSH Key
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

# define where is the SSH DSA key, use SSH key to connect remote host
# 如果是 使用 DSA Key 請用以下的設定
# key = paramiko.DSSKey.from_private_key_file('./sshkey/id_dsa')

# if your use .pem key, please comment above line and use below
# 如果是 使用 RSA 或是 .pem 的 key 使用以下的設定
key = paramiko.RSAKey.from_private_key_file(KEYPATH)

# 設定連接 ssh 的主機名稱, 使用者名稱, ssh 私鑰路徑
ssh.connect(hostname=REMOTEHOST, username=USERNAME, pkey=key)

# 如果遠端是採取帳號密碼驗證使用以下的方式
# ssh.connect(hostname="127.0.0.1", username="openSUSE", password="Password_there")


# Test uptime command with remote host
# 測試遠端指令
ssh_stdin, ssh_stdout, ssh_stderr = ssh.exec_command('uptime')

# 列出結果
print(ssh_stdout.read())
這個是在 jupyter 執行的結果
螢幕快照 2015-10-24 下午6.14.03.png

輸出的結果算是有點差強人意, 接下來就去看如何處理輸出

如果今天執行的是 ls -l 這樣的指令
ssh_stdin, ssh_stdout, ssh_stderr = ssh.exec_command('ls -l /share')
print()
print(ssh_stdout.read())
print()

螢幕快照 2015-10-24 下午6.19.20.png

輸出的結果真的不好閱讀
b'total 1010272\n-rwxr-xr-x 1 2000 libuuid   5636574 Sep  4  2014 kernel-9.3.xen\n-rw-r--r-- 1 2000 libuuid 865739683 Sep  4  2014 obj.tar.gz\n-rw-r--r-- 1 2000 libuuid 162685234 Sep  4  2014 src.tar.gz\n'

所以改變一下處理的方式, 使用 readlines() 還有透過 .join 的方式來處理
ssh_stdin, ssh_stdout, ssh_stderr = ssh.exec_command('ls -l /share')
print()
print( '\n'.join( ssh_stdout.readlines() ) )
print()

螢幕快照 2015-10-24 下午6.21.54.png
這樣的結果就比較好閱讀了

total 1010272

-rwxr-xr-x 1 2000 libuuid   5636574 Sep  4  2014 kernel-9.3.xen

-rw-r--r-- 1 2000 libuuid 865739683 Sep  4  2014 obj.tar.gz

-rw-r--r-- 1 2000 libuuid 162685234 Sep  4  2014 src.tar.gz


今天的小記就先到這邊, 看來我的 python 還要好好加油

~ enjoy it

2 則留言:

Chen Kenny 提到...

passphrase 輸入解決了?

Chun-Hung Huang 提到...

按照目前的架構, 先做 沒有 passphrase 的方式 :-)