0X00 前言
在早前用別人的工具時,發現有些大佬會用到交互式shell,那時候就挺好奇的,但是一直都沒有看一下怎么做到的。
今天在翻p牛的博客的時候,看到他早之前寫的一個工具就有用到交互式shell,看了看源碼,發現是用到了一個叫做cmd的模塊。
就想寫篇博文記錄一下,也好補充一下自己python標簽的文章~
0X01 簡介
cmd模塊是python中包含的一個公共模塊,用於交互式shell和其它命令解釋器等的基類。我們可以基於cmd模塊自定義我們的子類,實現我們自己的交互式shell。
它的執行流程也挺簡單的,使用命令行解釋器循環讀取輸入的所有行並解析它們,然后把輸入行交給命令處理器來處理。命令行處理器接收並解析輸入行,這里先需要知道輸入行包括兩個部分:命令和參數。通過繼承和子類方法重載父類方法的特性,命令行處理器找到適合處理該命令的子類方法。
比如我們輸入的是hello baby,那么我們就重寫名為do_hello的函數。倘若處理方法返回True,則直接退出循環。
簡單的代碼示例:
1 from cmd import Cmd 2 import os 3 import sys 4 5 class Cli(Cmd): 6 def __init(self): 7 Cmd.__init__(self) 8 9 def do_hello(self,line): 10 print "hello",line 11 12 if __name__ == '__main__': 13 cli = Cli() 14 cli.cmdloop()
輸出效果
0x02 cmd的主要方法和屬性
在認識了cmd模塊的主要運行流程,下面就認識一下它的主要函數與及一些我們需要用到的屬性。
方法:
(1)cmdloop():類似與Tkinter的mainloop,運行Cmd解析器;
(2)onecmd(str):讀取輸入,並進行處理,通常不需要重載該函數,而是使用更加具體的do_command來執行特定的命令;
(3)emptyline():當輸入空行時調用該方法;
(4)default(line):當無法識別輸入的command時調用該方法;
(5)completedefault(text,line,begidx,endidx):如果不存在針對的complete_*()方法,那么會調用該函數,該函數主要是用於tab補充,且只能在linux下使用。
(6)precmd(line):命令line解析之前被調用該方法;
(7)postcmd(stop,line):命令line解析之后被調用該方法;
(8)preloop():cmdloop()運行之前調用該方法;
(9)postloop():cmdloop()退出之后調用該方法;
(10)help_command():對command命令的說明,其中command為可變字符
屬性:
(1)prompt:交互式提示字符,也就是剛才的(Cmd)可以換成我們自己想要的字符
(2)intro:在進入交互式shell前輸出的字符串,可以認定為標志語之類的。其實這個可以在preloop方法輸出也是一樣的
下面用一個比較完整的代碼來舉例:
1 from cmd import Cmd 2 import os 3 import sys 4 5 6 7 class Client(Cmd): 8 u"""help 9 這是doc 10 """ 11 prompt = 'pyFun>' 12 intro = 'Welcom to pyFun!' 13 14 def __init(self): 15 reload(sys) 16 sys.setdefaultencoding('utf-8') 17 Cmd.__init__(self) 18 19 def do_hello(self,arg): 20 print 'hello',arg 21 22 def do_exit(self,arg): 23 print 'Bye!' 24 return True #返回True,直接輸入exit命令將會退出 25 26 def preloop(self): 27 print "print this line before entering the loop" 28 29 def postloop(self): 30 # print 'Bye!' 31 print "print this line after leaving the loop" 32 33 def precmd(self, line): 34 print "print this line before do a command" 35 return Cmd.precmd(self, line) 36 37 def postcmd(self, stop, line): 38 print "print this line after do a command" 39 return Cmd.postcmd(self, stop, line) 40 41 if __name__ == '__main__': 42 try: 43 os.system('cls') 44 client = Client() 45 client.cmdloop() 46 except: 47 exit()
運行效果:
0x03 一些情況下的使用
下面針對一些特定情況進行一些示例
1,當輸入空行的時候,我們可以重載emptyline()來處理:
def emptyline(self): print 'please input command!'
2,自定義我們自己的交互式提示字符串
prompt = 'pyFun>'
3,自定義我們的歡迎語:
intro = 'Welcom to pyFun!'
4,使程序能夠正常接收ctrl+c的退出方式
try: os.system('cls') client = Client() client.cmdloop() except: exit()
在我按下ctrl+c之后能夠正常退出不報錯
5,當輸入無法識別的命令時,使用default(line)來處理:
0x04 總結
其實模塊很簡單,大伙理解都不會超過十分鍾就明白了,但是要寫文章截圖,認真去講清楚才是最費時間的。但這樣學到的東西才是最深刻的。
這篇算是開坑,以后會一直去學習、記錄一些python有趣的庫。