目录
前章我讲了如何使用python的routeros模块连接ros api执行ros命令,本章将讲解ros api的语法是怎使用的,并结合python一起做例子。
有兴趣的可以提前看一下ros api官方文档
一、前言
ros api官言文档只是简单地讲解了api的用法 ,最后给了一堆开发语言的例子,对于编程基础很弱的初学者一脸懵进来,一脸灰出去。所以我觉得很我必要写一下。
后面写的例子都是基于python routeros模块来操作ros api的
相关ros api知识可以看官网 mikrotik API 使用说明,我这里使用的是python routeros模块进行开发,目前最新稳定版本为0.1.1
二、命令字Command word
2.1 说明
句子中的第一个单词必须是命令,然后是属性单词和零长度单词或终止单词。命令字的名称应以“ /”开头。命令名紧随CLI,用'/'代替空格。有一些特定于API的命令。
命令字的结构严格按顺序排列:
- 编码长度
- 内容前缀/
- CLI转换的命令
简单来说:命令行写的命令是用空格的,现在改为斜杠“/”代替空格即可
ps:值得注意的是在ros api支持菜单级命令,脚本命令是不支持的,比如像大中小括号,冒号开头的命令,是不能直接写在命令中的。
如果非要写可以写在 /System Scripts 中,或者ppp的Profile的Scripts属性中
ros api执行的命令结果会和菜单命令有些出入,需要注意一下。
2.2 例子
创建一个名为t1的python文件,如果不懂可以看回前章《RouterOS py api(四): python通过ros aip执行命令》
from routeros import *
import prettyprinter
# 使用API方式登录routerOS,调用routeros login()
ros = login("hua", "123", "192.168.3.6")
# ros对象执行相关命令返回元组
tup1 = ros("/ip/address/print")
# 输出整个返回结果
# prettyprinter.pprint(tup1)
print("所使用的IP地址为:")
# 拆解
for dict in tup1:
print(dict["address"])
ros.close()
执行结果
所使用的IP地址为:
192.168.2.6/24
192.168.128.6/24
192.168.3.6/24
10.10.10.2/32
三、属性词 Attribute word
3.1 说明
每个命令字都有自己的属性字列表,具体取决于内容。
属性词结构按以下顺序由5部分组成:
- 编码长度
- 内容前缀等于符号- =
- 属性名称
- 分隔等号- =
- 属性值(如果有)。该属性可能没有值
例子
=address=10.0.0.1
=name=iu=c3Eeg
=disable-running-check=yes
说白就就意思就是: 如果是属性前面要加等于“=”号,属性值也用“=”号赋,格式就是
“=属性名=[值]”
# []号表示可以为空
值得注意的是:当使用print命令有属性的时候,不能使用 “=属性名=[值]” 这样方式,将在第4小节进行讲解。
3.2 例子
比如找到项目号为0你在线用户,创建一个新的python,名字随便,输入如下代码
from routeros import *
# 使用API方式登录routerOS,调用routeros login()
ros = login("hua", "123", "192.168.3.6")
# ros对象执行相关命令返回元组
result = ros("/ppp/active/get", '=number=0', '=value-name=name')
print(result)
ros.close()
运行结果为
({'ret': 'p11'},)
四、查询词Query word
句子可以具有限制其范围的其他查询参数。
查询词以“?”开头。
查询词的顺序很重要。 从第一个单词开始评估查询。
将对列表中的每个项目评估查询。 如果查询成功,则处理项目,如果查询失败,则忽略项目。
使用一堆布尔值评估查询。 最初,堆栈包含无限数量的“ true”值。 评估结束时,如果堆栈包含至少一个“假”值,则查询失败。
查询词根据以下规则进行操作:
查询 说明 例子 ?name pushes 'true' if item has value of property name, 'false' if it does not.
如果项目具有属性名称的值,则推``true'',否则则为``false''。
查看包含属性为 address
print(ros("/ppp/active/print", '?address'))
?-name pushes 'true' if item does not have value of property name, 'false' otherwise.
如果项目不具有属性名称的值,则推送``true'',否则推送``false''。
查看不包含属性 address 的项目
print(ros("/ppp/active/print", '?-address'))
?name=x
?=name=xpushes 'true' if property name has value equal to x, 'false' otherwise.
如果属性名称的值等于x,则推送'true',否则推送'false'。
查看名字为p11的在线用户
print(ros("/ppp/active/print", '?name=p11'))
?<name=x
pushes 'true' if property name has value less than x, 'false' otherwise.
如果属性名称的值小于x,则推送'true',否则推送'false'。
查看接收流量小于100M的,默认是字节所以要加多6个0 print(ros("/interface/print", '?<rx-byte=100000000'))
?>name=x pushes 'true' if property name has value greater than x, 'false' otherwise.
如果属性名称的值大于x,则推送'true',否则推送'false'。
查看接收流量大于100M的,默认是字节所以要加多6个0
print(ros("/interface/print", '?>rx-byte=100000000'))?#operations 将操作应用于堆栈中的值。
- 操作字符串从左到右求值。
- 十进制数字序列后跟任何其他字符或单词结尾被解释为堆栈索引。 最高值的索引为0。
- 索引后跟一个字符,将值的副本推送到该索引处。
- 单词结尾处的索引将所有值替换为该索引处的值。
- ! 字符用相反的值代替最高值。
- & 弹出两个值并推送逻辑'and'操作的结果。
- | 弹出两个值并推送逻辑“或”运算的结果。
- . 在索引之后什么也不做。
- . 之后另一个字符将复制最高价值。
例子我这里就不讲了
五、routeros模块query方法查询
要查询操作除了上面的之外,还要以直接使用python routeros模块query方法。
5.1 query方法说明
根据python routeros模块说明文档,指定属性可以使用如下
- query.has(*args) 查询某个属性名字是否存在,如 ros.query("/ppp/active/print").has("uptime")
- query.hasnot(*args) 查询不包含某属性名字的。
- query.equal(**kwargs) 查询属性名为某个值项目
- query.lower(**kwargs) 查询小于某个属性值的项目
# 查上传流量小于100M的项目 query = {'rx-byte': (1024*1024*100)} result = ros.query("/interface/print").lower(**query) print(result)
- query.greater(**kwargs) 查询大于某个属性值的项目
Python中,(*)会把接收到的参数形成一个元组,而(**)则会把接收到的参数存入一个字典
5.2 例子
我就拿一个典型的例子,查询在线用户p11时长,如果用命令执行是这样的
# 查看用户p11在线时长
[hua@MikroTik] > :put [ ppp active get [find name=p11] value-name=uptime ]
01:07:37
这里用到get和find的的组合,因为有小括号,我们不能直接转ros api,所以可以分2次执行;先执行find再执行get
from routeros import *
# 使用API方式登录routerOS,调用routeros login()
ros = login("hua", "123", "192.168.3.6")
# ros对象执行相关命令返回元组
resultUserID = ros("/ppp/active/find", '=where=name=p11')
resultUserUptime = ros("/ppp/active/get", '=number=0', '=value-name=uptime')
print(resultUserUptime[0]['ret'])
ros.close()
执行结果为:
01:18:00
上面结合有点麻烦,可以直接使用query的查询功能,代码如下:
from routeros import *
# 使用API方式登录routerOS,调用routeros login()
ros = login("hua", "123", "192.168.3.6")
# ros对象执行相关命令返回元组
resultUserUptime = ros.query("/ppp/active/print").equal(name="p11")
print(resultUserUptime[0]['uptime'])
ros.close()
执行结果为:1h22m12s
六、其它
其它部分用得比较少,有兴趣的可以看一下ros api 官方文档,相信你现在应该有能力看懂了
七、注意事项
7.1 用api执行脚本返回值为空的问题
在API执行脚本的时候,要返回结果给python用“:return” ,不能使用“:put”,否则返回值为空!
7.2 用api执行脚本中有fetch命令问题
当ros脚本把 fetch命令结果赋值给变量,会变成空值,而使用ros命令执行则表示正常。所以当脚本中有fetch要特别注意。