前言十步杀一人, 千里不流行。事了拂衣去, 深藏功与名。
李白 -- 《侠客行》
为了将之前所学总结一下(捏一捏,揉一揉,锤两下),于是用 python 写了一个简易的端口扫描器。
接下来会用几篇连载来介绍代码中所使用的几个重要模块和一些重要知识,具体有几篇还真预测不了,反正应该只多不少,因为我会尽我所能将最终代码中所涉及的知识点讲明白的(莫慌,蛋定)。
这里先献上最终的效果图。
图1 交互式命令行的效果图
图2 tkinter 界面效果图
cmd模块温馨小分享
给初学者的建议是在学习某工具(如 python 的某个模块)的时候,最直接的想法就是去找该工具所对应的官方文档,因为它最权威且知识点囊括最全。当然,如果官方文档看不太懂(晦涩),可以去借鉴网上其他前辈的文章,因为他们有些写得也很优秀。
简介
Cmd 类提供简单框架用于编写面向行的命令解释器。默认情况下使用 readline 来进行交互式操作、命令行编辑和命令完成。(你:不懂)
使用 Cmd 创建的命令函解释器循环读取输入的所有行并且解释他们,然后发送命令给一个合适的命令处理器。(你:不懂)
输入行解析为两个部分:命令和参数。如果用户输入 cmd param,它解释成命令 cmd 和参数 param,然后使用参数 param 作为参数调用我们重写的 do_cmd 方法。如果 do_cmd 命令处理器返回 Ture,那么程序就会无差错地退出;如果返回 False,程序会继续等待下一个命令的输入。(你:还是不懂)
莫慌,"简介" 这东西一开始是很难看懂的,结合下面的实例再回头看就 "柳暗花明" 了,先有个概念,下面将结合实例讲解。
Cmd 常用的方法和属性
下面将对 Cmd 类中的一些常用的方法和属性进行介绍。
① 方法
cmdloop() | 类似与 tkinter 的 mainloop,运行 Cmd 解析器 |
emptyline() | 当输入空行时调用此方法 |
default(line) | 当输入无法识别的 command 时调用该方法 |
precmd(line) | 命令 line 被解析之前调用该方法 |
postcmd(stop, line) | 命令 line 解析之后调用该方法 |
preloop() | cmdloop() 运行之前调用该方法 |
postloop() | cmdloop() 退出之后调用该方法 |
help_command() | 对 command 命令的说明,其中 command 为可变字符 |
② 属性
prompt | 交互式提示符 |
intro | 在进入交互式 shell 前输出的字符串,可以是标志语,工具的专属logo。PS:preloop 方法所实现的功能和这个差不多。 |
prompt 属性
prompt 属性可以使我们自定义自己的交互式提示符。
# -*- coding: utf-8 -*-"""@Run by : Python3@Author: ai_li@Date: 2020/6/28 1:47@File: tmp.py"""from cmd import Cmdclass Shell(Cmd): # 重写 __init__ 方法 def __init__(self): Cmd.__init__(self) self.prompt = "Port Scan >>"if __name__ == '__main__': shell = Shell() shell.cmdloop()
intro 属性
自定义标志语,或者可以定制工具的 logo(如上面的效果图)。
self.intro = "This is the Port Scanner V1"
emptyline 方法
当输入空行的时候,可以调用 emptyline 方法来处理。
def emptyline(self): print("Command line is empty")
default 属性
当输入的命令无法识别时(没有定义该命令),调用 default 方法来处理。
def default(self, line): print("Command was not defined")
快捷键 CTRL+C 退出
如果保持以上的代码,当想要结束程序的时候,使用 CTRL+C 会报错,然后退出。
这么粗鲁的退出程序一定,肯定,绝对,绝b,果然,当真不是我们侠客所为。
在这里,我们只需要在出错的地方小小地加上一个异常处理就可以完美避开错误,优雅地退出。
if __name__ == '__main__': shell = Shell() try: shell.cmdloop() except: exit()
自定义动作
自定义动作,就是我们自定的命令了,格式是:
def do_cmd(self,line): # 命令执行的动作
比如最后我们想定义一个 port 命令来输入要扫描的端口,scan 命令来输入我们要扫描的 IP 和 IP 段等等,这里我们可以定义一个退出的命令 exit。
def do_exit(self, line): return True
至于为什么是返回 True,不要问,请偷偷回去看前面的 简介。
尾声好了,这篇文章就写到这里。仅仅是对 Cmd 模块的几个方法和属性做了简单介绍而已,有兴趣可以自行深究,我比较蠢萌,就算了哈。
我是匠心,一个在清流旁慢慢磨剑的匠人,希望有一天能利刃出鞘,仗剑走江湖。
明明喜欢却不敢点个在看