在?python?中有一個?telnetlib,它的作用就是建立一個通到主機的?telnet連線實體,?然后向主機傳送命令?(就像用鍵盤輸入一樣?)并從該連線接收數據。利用它,?我們可以把示范?1的所有內容從?"人?-機?'交流變成'機?-機?'交流,這樣也可以做到處理?pop3?郵箱的工作。不過既然我們已經試過了?pop3,這一次可以試用真的?telnet?埠?23?做些好玩的東西。?
# telnetdo.py #!/usr/bin/env python def telnetdo(HOST=None, USER=None, PASS=None, COMMAND=None): #定義一個函數, 這將要用它會很容易 import telnetlib, sys if not HOST: #如果沒有給出所要的資料,則要求用戶輸入 try: HOST = sys.argv[1] #記得吧, 序列是從 0開始數的,而sys.argv[0]會是你程式的名字 USER = sys.argv[2] PASS = sys.argv[3] COMMAND = sys.argv[4] except: print "Usage: telnetdo.py host user pass 'command'" return msg = ['Debug mesages:\n'] #這個用來存起所有從主機傳回的訊息, 作除錯時很有用 tn = telnetlib.Telnet() #準備一個 telnet 連線的實體 try: tn.open(HOST) #連接端綁定到主機 HOST 去 except: print "Cannot open host" return msg.append(tn.expect(['login:'],5)) #等待主機傳回含有 'login:'字符的訊息,等候時限為 5秒 tn.write(USER+'\n') #向主機送出字串 USER + '\n',如 USER 是 # 'pcheung' 則等于 'pcheung\n' if PASS: #就像是在鍵盤打入一樣。 msg.append(tn.expect(['Password:'],5)) #如果有 password 要打的話就送出密碼字串, tn.write(PASS+'\n') #但首先要等主機傳回含有 'Password:'字樣的訊息 msg.append(tn.expect([USER],5)) #因為通常登入后主機會顯示出登入者名稱,我們在主機回應中找這 #樣的字符,如有的話則代表登入成功了 tn.write(COMMAND+'\n') #向主機發出指令 msg.append(tn.expect(['%'],5)) #等 5秒,如果程式完成了一般我們會收到 # shell prompt 吧,假設為 '%' tn.close() #關閉連線 del tn return msg[len(msg)-1][2] #把收到的訊息通通傳回去。 #(注意 msg 中第 2個元素才是真的訊息, #其他是附加資訊。 44 if __name__ == '__main__' #這是 python 常用的技巧:如果 telnetdo.py 程式 #是從 command prompt #引發的話則 __name__ 的內容為 __main__,相反 #如果是從別的程式用 import telnetdo 的話則 # __name__ 會變成 'telnetdo' print telnetdo() #這樣寫的好處是從此 telnetdo 會成為你的擴展 #模組,你可以在別的程式中 #用telnetdo.telnetdo(HOST,USER,PASS,COMMAND)來調用它!
這個程式用法如下:
> chmod +x telnetdo.py
> telnetdo.py 'somehost' 'glace' 'xxxxxx' 'ls?? -lF'
(0,
(somehost)\015\012\015\015\012\015login: ')
(0,
(0,
somehost\015\012Last login: Wed?? Mar??? 6 18:21:01 GMT 2002 by
UNKNOWN@xxx.xxx.xxx.xxxyou have?? mail\015\012somehost:glace%')
total 320
-rw-r--r--??? 1 glace??? user??????? 139788 Feb??? 8 17:54 PQR2.1.txt
drwxr-xr-x??? 3 glace??? user????????? 4096 Feb?? 10 16:45 mytts/
drwxr-xr-x??? 3 glace??? user????????? 4096 Jan?? 29 19:03 sample/
drwxr-xr-x??? 2 glace??? user????????? 4096 Jan??? 6 16:38 tex/
drwxr-xr-x??? 2 glace??? user????????? 4096 Sep??? 5? 2001 tmp/
drwxr-xr-x??? 2 glace??? user??????????? 29 Feb?? 23? 2001 tools/
drwxr-xr-x??? 2 glace??? user??????????? 26 Feb??? 6 18:43 trash/
somehost:glace%
可以看到執行的結果和一些附加的資訊。這就是遠端執行程式了。就算沒有 rsh,照用可也。 哈,很方便吧。不過你應該留意到了程式執行時只等候了 5秒,就是說如果你要向主機發出像'find . -name xxx?? -print'這樣的命令應該等不到執行完這個 telnet session 就會被關閉了。不過仔細想一下,這要緊嗎?我們現在所能做到的和真正人手 telnet 的差別并不大,想一想你會怎樣解決長時間執行的問題?沒錯,就是 'nohup'和背景作業了。 就是說只要把程式呼叫改成: telnetdo.py 'apocal' 'pcheung' 'xxxxxx' 'nohup?? myprogram_or_scrīpt&' 就行了。如此一來,就算對方主機的 shell prompt 是 '>'或是 '>>>'都沒有關系了。
(注意安全性并非是這類范例程式的著重點, 因此并不建議在實際工作中用它.)?
python中telnetlib模塊的使用
python下能支持telnet的模塊telnetlib是內置模塊,直接import就可以了,其基本的使用方法也是比較簡單的。
#encoding=utf-8 def do_telnet(Host, username, password, finish, commands): import telnetlib '''''Telnet遠程登錄:Windows客戶端連接Linux服務器''' # 連接Telnet服務器 tn = telnetlib.Telnet(Host, port=23, timeout=10) tn.set_debuglevel(2) # 輸入登錄用戶名 tn.read_until('login: ') tn.write(username + '\n') # 輸入登錄密碼 tn.read_until('password: ') tn.write(password + '\n') # 登錄完畢后執行命令 tn.read_until(finish) for command in commands: tn.write('%s\n' % command) #執行完畢后,終止Telnet連接(或輸入exit退出) tn.read_until(finish) tn.close() # tn.write('exit\n') if __name__=='__main__': # 配置選項 Host = '10.255.254.205' # Telnet服務器IP username = 'administrator' # 登錄用戶名 password = 'dell1950' # 登錄密碼 finish = ':~$ ' # 命令提示符 commands = ['echo "test"'] do_telnet(Host, username, password, finish, commands)
其中port和timeout是可選的參數,而timeout的只是在初始化socket連接時起作用,而一旦連接成功后如果出現等待那就不會起作用了,比如使用read_until方式獲取內容時返回的內容與指定的內容沒有吻合,那么就會造成提示等待的情況,這時timeout是不會起作用的,而這個socket連接會一直保持著,永生不死。
那么如何解決這個問題呢,其實還有一種比較原始的方法,就是使用sleep方法來代替read_until方法,這樣就不會出現種情況,因為到點就會自己輸入,最多也就是最后得不到想要的結果,但是這個方式很不穩定,兼容性也不好;另一種方法是使用線程來啟動這個函數,然后對子線程進行超時設置,這樣就可以達到間接控制這個telnet連接的目的了。
import threading pars = replace_db_keyworlds(vars_dict, pars) configs = pars.split(r'@') host = configs[0].encode() user = configs[1] passwd = configs[2] finish = configs[3] commands = configs[4].split(r'\n') th1 = threading.Thread(target=do_telnet, args=(host.encode('utf-8'), user.encode('utf-8'), passwd.encode('utf-8'), finish.encode('utf-8'), commands)) th1.start() th1.join(20) ##20秒超時時間
還有一個需要注意的是,傳遞給Telnet方法的字符串都會被解一次碼,所以如果你傳遞過去需要write的字符串是已經解碼的unicode的話,那么就會報錯的,所以在傳遞發送的字符串之前還是先編成utf-8為妥,其它字符不知道支持不,我只試了utf-8,也沒看源碼。
此外,貌似還有一個pexpect的第三方模塊可以支持telnet等一系列的協議連接,并支持交互式的通信,只是這個模塊夠用就沒學習了,這里先備注一下。
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
