1.消除硬編碼
第一個就是它有硬編碼的情況,什么是硬編碼,什么是硬編碼就是說在代碼里面,你用的一些變量它是寫死的,比如說我們剛才調用connect APId的時候它的,ip地址端口用戶名和密碼都是我們寫死的,什么192.168.3.106,用戶名,密碼,如果它的對端的這個端口它變了,或者說是密碼用戶名一般不會變。它的密碼改變我們是不是要去修改代碼,如果在實際工作中這樣是非常不方便的,而且是有一定風險的,修改代碼就意味着它可能是bug產生的邊緣。所以說我們最好把這個可配置的代碼,和變量分離開來。就是說消除硬編碼的一個辦法就是讓它可配置。
2.異常捕捉
其次就是異常的捕捉,我們可以看到剛開始我們想列了,那個設置hot key機制時候,它調用connect方法,就拋出來一個sshaexception這個異常,但是我們並沒有對它進行處理。這樣的話就會在 實際的工作中它就非常的不好,甚至是有一些風險,因為不捕獲這個異常的話,可能你的代碼,就沒辦法在執行下去了,然后你寫了這個軟件可能就當掉了實際生產環境下,是一個非常嚴重的問題。
3.封裝
另外就是進行一下封裝,我們看到Paramiko它是對這個,它其實就是對ssh協議的一個封裝,然而我們在實際的使用Paramiko的過程中,可以針對自己項目的需要。對它進行二次封裝,就是說我封裝成我們大家,一起,團隊的人它更方便的使用它,甚至它可以不知道Paramiko這個的存在,而調用你封裝的接口。來進行一個更方便的操作。
那我們就看實際的過程中我們是怎樣來解決這幾個問題的,首先就是消除硬編碼的問題,我們引入另外一個ConfigParser這個庫,ConfigParser就是可以把這個配置很方便的讀進來。
config = ConfigParser.ConfigParser()
然后它有一個read的API就是讀取文件。
那現在我們就一起來建立一個文件,叫做config.ini
[ssh]
host=192.168.3.105
port=22
usr=allen
pwd=123
timeout=1.0
然后我們read這個config.ini
config.read(‘config.ini’)
那么這些硬編碼的地方,就可以換成對應的配置
client.connect(hostname= config.get(‘ssh’,’host’), port= config.getint(‘ssh’,’ port’), username= config.get(‘ssh’,’ username’), password= config.get(‘ssh’,’ password’), timeout= config.getfloat(‘ssh’,’ timeout’))
我們可以來運行看一下
這樣我們把這些變量給替換成用這個配置來解析出來它實際的值。我們就是用這個ConfigParser來完成的,現在它運行的是非常的好,然后我們就把這些實際的參數給用配置給它隱藏起來,如果將來我們配置一旦更改的時候我們只需要更改這個config.ini就可以,然后我們來看一下,如何進行異常的捕獲。
首先這個connect它會拋出這個異常的時候我們其實就應該用Python的try來捕獲它,然后用這個except Exception,e:可以把異常給打印出來。
try:
self.client.connect(hostname=self.host, port=self.port, username=self.usr, password=self.pwd, timeout=self.timeout)
return True
except Exception,e:
print e
這個時候呢一旦開啟的時候我們記得要把它給close掉。避免造成資源的浪費
self.client.connect(hostname=self.host, port=self.port, username=self.usr, password=self.pwd, timeout=self.timeout)
return True
except Exception,e:
print 'caught ', e
try:
self.client.close()
return False
except:
pass
其實這樣的話就把這個,簡單的看一下異常的捕獲,其實這個地方拋出捕獲的時候我們就在這把它給捕獲了,其實這個exec_command它也是會拋出異常。
接下來我們就對它進行一個封裝,如何封裝,封裝它是一個面向對象的一個特點,就會面向對象方法的一個特點,所以說我們把一些細節給隱藏起來,怎么隱藏呢,就是通過類。
我們可以新建一個ParamikoClient這個類。
class ParamikoClient:
然后其實我們在它的初始化函數中就可以把config這個文件名給傳進來。
def __init__(self, ini_file):
然后就可以進行一些初始化的工作,這個config要變成main自身的變量,這個Client也是變成它的一個成員,這個類的對象的一個成員。
self. config= ConfigParser. ConfigParser ()
self. Config. read(' config.ini ')
self. Client= paramiko.SSHClient()
self. Client= set_missing_host_key_policy(paramiko.AutoAddPolicy())
然后我們還可以,定義它的connect方法,connect方法的時候就可以把這部分全部,拷貝過來。
self.client.connect(hostname=self.host, port=self.port, username=self.usr, password=self.pwd, timeout=self.timeout)
return True
except Exception,e:
print 'caught ', e
try:
self.client.close()
return False
except:
pass
然后最終這樣就可以最后我們在封裝一個如何執行命令的
def run_command(self, cmd_str):
stdin, stdout, stderr = self.client.exec_command(cmd_str)
for line in stdout:
print line
這樣一個類我么我們就做好了我們在用這個類來建立一個ParamikoClient。
client = ParamikoClient('config.ini')
我們調用它的connect方法來接,
client.connect()
然后
client.run_command('date')
它把直接就把這個指令結果輸出來了,我們還可以運行一下剛才輸的查詢遠程機器的這個內存信息的指令。
client = ParamikoClient('config.ini')
client.connect()
client.run_command('cat/proc/meminfo')
我們這樣就看到到了這個從它編碼,到進行一個更優雅實現的這么一個過程。
其實還有一個跟好的做法就是把這個ParamikoClient這個類單獨放到一個文件里面,封裝性會更好。