學(xué)習(xí)新東西當(dāng)要用到我們的3W方法了(what? why? how),下面我們來學(xué)習(xí)下?ros?的api,
地址:https://wiki.mikrotik.com/wiki/Manual:API??
API都是全英的,初學(xué)者建議盡量去看英文版,中文翻譯很多時(shí)候不能做到原汁原味,下面是中文版:
正文:
目錄?
1簡介
2通訊協(xié)議
2.1 API詞
2.1.1 命令詞
2.1.2 屬性詞
2.1.3 API 屬性詞?
2.1.4 查詢語句?
2.1.5回復(fù)語句
2.2 API 特定命令說明
3初始登錄
4 標(biāo)簽(.Tags )
5 API命令說明?
5.1 查詢詞說明?
5.2 OID
6 API命令例子
6.1 /system/package/getall
6.2 /user/active/listen
6.3 /cancel, simultaneous commands
7 客戶端程序例子?
8 參考?
8.1 API examples in the Wiki
8.2 API examples on the MikroTik Forum
8.3 API exmaples elsewhere
簡介:
應(yīng)用程序編程接口(API),允許用戶創(chuàng)建定制的軟件解決方案與RouterOS的
溝通,收集信息,調(diào)整配置和管理路由器。API緊隨命令行界面(CLI)的語法。
它可以用來創(chuàng)建轉(zhuǎn)換或自定義的配置工具,以幫助管理使用RouterOS的路由器。
使用API需要RouterOS版本3.x或更高的版本。
默認(rèn)情況下,API使用端口8728,默認(rèn)服務(wù)是禁用的。通訊服務(wù)的名稱是API,請
在IP-SERVER里開啟,服務(wù)管理的詳細(xì)信息,請參閱相應(yīng)的手冊部分。
通訊協(xié)議:
?????應(yīng)用程序與路由器的通信是通過發(fā)送和接收路由器的一個(gè)或多個(gè)編碼的句子來
完成的。一個(gè)句子是以零字符結(jié)尾的單詞序列。詞是句子以某種方式編碼-(編碼
長度是數(shù)據(jù)的一部分),路由器發(fā)送和接收回復(fù)并發(fā)送這些句子。每個(gè)句子發(fā)送到路由器
使用API沒有特定的順序,每個(gè)命令字是以零字符標(biāo)記結(jié)束的。當(dāng)路由器
接收到完整的句子(命令字,或多個(gè)屬性的話,零字符結(jié)束),它就開始執(zhí)行命令,
并將結(jié)果返回給應(yīng)用程序。
API語句:
詞是句子的一部分。每個(gè)詞長都用某種方式編碼-詞長編碼跟隨詞的內(nèi)容就是一個(gè)句子。詞的長度應(yīng)為將要發(fā)送的字節(jié)計(jì)數(shù)(不包括詞長編碼)。
詞長編碼如下:
Value of length# of bytesEncoding
0 <= Len <= 0x7F1Len, lowest byte??詞長度
0x80 <= Len <= 0x3FFF2Len | 0x8000, two lower bytes??
0x4000 <= Len <= 0x1FFFFF3Len | 0xC00000, three lower bytes
0x200000<=Len <= 0xFFFFFFF4Len | 0xE0000000
Len >= 0x1000000050xF0 and Len as four bytes
對應(yīng)的10進(jìn)制:
長度字節(jié)數(shù)詞長編碼
0 <= 長度<=1271長度低位
128?<= 長度<= 163832位或(長度?,32768) 取低2位
16384<= 長度<= 20971513位或(長度?,12582912)取低3位
2097152 <= 長度?<= 2684354554位或(長度?,3758096384)
長度?>= 2684354565{240} +到字節(jié)集(長度)
[if !supportLists]v?[endif]每個(gè)詞的編碼長度,然后緊接著許多字節(jié)的詞內(nèi)容(詞長編碼+詞內(nèi)容);
[if !supportLists]v?[endif]字組合成句子,以零字符結(jié)束;
[if !supportLists]v?[endif]最高長度可以達(dá)到0x7FFFFFFFFF,最高占用4字節(jié);
[if !supportLists]v?[endif]詞長編碼字節(jié)(Len)總是在最前面(網(wǎng)絡(luò)順序);
[if !supportLists]v?[endif]如果單詞的第一個(gè)字節(jié)是> =0xF8,那么它是一個(gè)保留的控制字節(jié)。未知的控制字節(jié)API客戶端接收后無法繼續(xù),因?yàn)樗恢廊绾谓忉屢韵伦止?jié);
[if !supportLists]v?[endif]目前,控制字節(jié)不使用;
[if !supportLists]v?[endif]句子一般情況是這樣的:<詞長編碼><詞的內(nèi)容>,主要有5種類型:命令語句,屬性語句,API屬性語句,查詢語句,回復(fù)語句;
命令語句(Command word)
?
在句子的第一個(gè)字是由名字(屬性)和零長度的詞終止字的命令。命令字的名稱應(yīng)以'/'開始。命令中的名字,與命令行界面輸入的一樣,要注意的API中的命令不能有空格,需要用以'/'替換,比如查看網(wǎng)卡信息 "/int pri" 在API里就必須這樣"/int/pri",不然無法識別;
注意:發(fā)送的命令必須嚴(yán)格按照這樣的順序:
[if !supportLists]??[endif]編碼長度
[if !supportLists]??[endif]內(nèi)容前綴"/"
[if !supportLists]??[endif]命令行的轉(zhuǎn)換命令(空格用"/"替換)
API特定的命令:
???getall
???login
???cancel
命令連接例子:
/login
/ip/address/getall
/user/active/listen
/interface/vlan/remove
/system/reboot
?
2.1.2屬性語句(Attribute word)
?????每個(gè)命令都有其自己的屬性列表,命令內(nèi)容決定屬性。
屬性結(jié)構(gòu)由5部分組成,順序如下:
編碼長度
內(nèi)容前綴( ! - = )
屬性名稱
分離符號( ! - = )
屬性值(可以被忽略,說明這個(gè)屬性沒有值)
注意:為了編碼方便,一個(gè)命令里的多個(gè)屬性賦值可以在一句里完成
???????屬性值可以為空
沒有編碼的長度前綴的例子:
=address=10.0.0.1 ???????
=name=iu=c3Eeg ???????
=disable-running-check=yes
注意:屬性詞和API參數(shù)的順序并不重要,不應(yīng)依賴;
2.1.3 API屬性語句
?
API屬性語句的結(jié)構(gòu)必須嚴(yán)格按照下面的順序:
編碼長度
內(nèi)容與名稱前綴"=."
屬性名稱
名稱后綴符"="
屬性值
system/resource/print ?
=.proplist=uptime,cpu-load,uptime.oid,cpu-load.oid ?
目前只有這樣的API屬性的標(biāo)簽。
注意:如果句子包含了屬性語句標(biāo)簽,返回的每一個(gè)句子和從路由器標(biāo)記句子將標(biāo)記相同的標(biāo)簽,關(guān)于標(biāo)簽后面的章節(jié)有單獨(dú)的介紹;
2.1.4查詢語句??
?????查詢語句支持對參數(shù)進(jìn)行一定范圍內(nèi)的模糊查詢,在下面的章節(jié)中有單獨(dú)介紹;
例如句子使用查詢詞的屬性:
/interface/print
?type=ether
?type=vlan
?#|!
查詢語句以符號"?"開始,目前查詢語句只支持"print"命令;
警告:查詢語句始終是在最前面;
2.1.5回復(fù)語句
?
回復(fù)語句只能由路由器發(fā)送,它僅發(fā)送完整的句子,由客戶端發(fā)送響應(yīng)。
[if !supportLists]n?[endif]回復(fù)語句的第一個(gè)字是以"!"開始的;
[if !supportLists]n?[endif]發(fā)送的每一句話產(chǎn)生至少一個(gè)答復(fù)(如果連接沒有得到終止);
[if !supportLists]n?[endif]每一句的最后答復(fù)是答復(fù)的第一個(gè)字"!done";
[if !supportLists]n?[endif]錯(cuò)誤和異常情況以"!trap"開始;
[if !supportLists]n?[endif]開始數(shù)據(jù)回復(fù)以"!re"開始;
[if !supportLists]n?[endif]如果連接被關(guān)閉,RouterOS發(fā)送"!fatal"作為致命的原因進(jìn)行答復(fù)并且關(guān)閉連接;
2.2 ?API語句
?????API語句是使用API通信的主要對象
[if !supportLists]n?[endif]空的句子被忽略;
[if !supportLists]n?[endif]句子是以字符"0"作為結(jié)束標(biāo)志的;
[if !supportLists]n?[endif]客戶端登陸后發(fā)送句子有數(shù)量和大小的限制;
[if !supportLists]n?[endif]屬性語句沒有順序區(qū)別,比如.proplist屬性語句的順序和計(jì)數(shù)就是多變的;
句子結(jié)構(gòu)如下:
?
[if !supportLists]n?[endif]第一句話應(yīng)該包含命令字;
[if !supportLists]n?[endif]應(yīng)包含結(jié)束標(biāo)志字符{0};
[if !supportLists]n?[endif]可以包含0個(gè)或多個(gè)屬性詞,沒有特定的順序,不管什么屬性詞必須在句子里發(fā)送,屬性詞的順序并不重要;
[if !supportLists]n?[endif]可以包含沒有一個(gè)或幾個(gè)查詢詞,查詢詞在句子的順序是很重要的;
?
?
注:零長度的詞(字節(jié)'0')終止了一句,如果沒有提供,路由器將無法測試句字的有效性,只能把收到的句子當(dāng)做句子的一部分;
?
?
初始登錄
/login
?!done
=ret=ebddd18303a54111e2dea05a92ab46b4
/login
=name=admin
=response=001ea726ed53ae38520c8334f82d44c9f2
?!done
?
注意:每個(gè)命令和響應(yīng)結(jié)束都有一句空的語句;
[if !supportLists]n?[endif]首先,客戶端發(fā)送"/ login"命令
[if !supportLists]n?[endif]路由器的回復(fù)包含"=ret=需要的參數(shù)"
[if !supportLists]n?[endif]客戶端發(fā)送第二個(gè)"/login"命令,接著是用戶名("=name=username")和密碼("=response=response")驗(yàn)證命令;
[if !supportLists]n?[endif]在錯(cuò)誤的情況下,答復(fù)包含= RET =錯(cuò)誤消息。
[if !supportLists]n?[endif]在成功登錄客戶端的情況下,就可以開始發(fā)出命令。
標(biāo)簽(.tag)
[if !supportLists]n?[endif]它是可以同時(shí)運(yùn)行多個(gè)命令,而不必等待前一個(gè)完成。如果API的客戶端是這樣做的,需要區(qū)分命令的反應(yīng),它可以使用在命令句子'.tag'API的參數(shù)。
[if !supportLists]n?[endif]如果你有“.tag”命令句與非空值的參數(shù),然后'.tag'參數(shù)完全相同的值將包含在該命令生成的所有答復(fù)。
[if !supportLists]n?[endif]如果不包括'.tag'參數(shù),或它的值是空的,那么這個(gè)命令所有的反應(yīng)將不會有“.tag”參數(shù)。
命令描述?
[if !supportLists]n?[endif]/cancle (取消)
[if !supportLists]n?[endif]可選參數(shù):=tag=tag?,取消所有正在運(yùn)行的命令;
[if !supportLists]n?[endif]不能取消本身
[if !supportLists]n?[endif]所有取消的命令都是中斷操作,并且在通常情況下會產(chǎn)生'!trap'和'!done' 的回復(fù);
[if !supportLists]n?[endif]請注意,"/cancel "是單獨(dú)的命令,可以有它自己獨(dú)特的'.tag'參數(shù),它是不相關(guān)'=.tag'這個(gè)命令的參數(shù);
[if !supportLists]n?[endif]listen?(監(jiān)聽)
[if !supportLists]n?[endif]listen是在控制臺print 命令可用的情況下使用,它沒有預(yù)期中的效果(即可能無法正常工作);
[if !supportLists]n?[endif]!re數(shù)據(jù)回復(fù)句子會產(chǎn)生特定的項(xiàng)目列表中的一些變化;
[if !supportLists]n?[endif]當(dāng)項(xiàng)目被刪除或以其他任何方式清除,數(shù)據(jù)回復(fù)句子( '!re')的屬性值會包含'=.dead=yes' ;
[if !supportLists]n?[endif]此命令不會終止。終止使用取消命令"/cancle"
[if !supportLists]n?[endif]getall?(獲取全部信息)
[if !supportLists]u?[endif]getall命令是在控制臺print命令可用的情況下使用,自3.21版本以后的getall命令是print命令的別名。
[if !supportLists]u?[endif]回復(fù)包含=.id=項(xiàng)目內(nèi)部編號屬性
[if !supportLists]n?[endif]print??(顯示)
[if !supportLists]n?[endif]API的print命令和控制臺的print命令的不同主要有以下幾個(gè)方面:
[if !supportLists]u?[endif]雖然參數(shù)不支持,但可以使用查詢詞(見下文)篩選項(xiàng)目。
[if !supportLists]u?[endif]傳回的項(xiàng)目可能有額外的屬性。
[if !supportLists]u?[endif]返回的屬性的順序是沒有定義的。
[if !supportLists]u?[endif]如果列表中包含重復(fù)的條目,這些條目的處理沒有被定義。
[if !supportLists]u?[endif]如果屬性格式目前是在.proplist里,但項(xiàng)目里沒有這個(gè)屬性,該項(xiàng)目沒有這個(gè)屬性的值,(?名稱將評估該項(xiàng)目為假)
[if !supportLists]u?[endif]如果沒有設(shè)置.proplist參數(shù),將打印所有的屬性,甚至那些比較耗時(shí)的項(xiàng)目(如文件內(nèi)容性能記數(shù)),因此推薦使用.proplist參數(shù),設(shè)置=detail= argument,雖然可能會有遺漏,但是換回的卻是高性能。
查詢
print命令接受限制返回的句子設(shè)置的查詢詞。此功能是自RouterOS的3.21開始的。
[if !supportLists]n?[endif]查詢詞以符號"?'開始。
[if !supportLists]n?[endif]查詢詞的順序是在最前面的,從第一個(gè)字開始模糊查詢。
[if !supportLists]n?[endif]對查詢列表中每個(gè)項(xiàng)目進(jìn)行評估,如果查詢成功,項(xiàng)目被處理,如果查詢失敗,項(xiàng)目將被忽略。
[if !supportLists]n?[endif]查詢評估在堆棧使用布爾邏輯值。最初,堆棧包含無限量的“真”值。在評估結(jié)束時(shí),如果堆棧包含至少一個(gè)“假”值,查詢失敗。
[if !supportLists]n?[endif]查詢詞按照下列規(guī)定操作:
查詢詞??????????????????????描敘
?name ??????????????????如果項(xiàng)目屬性名稱的值不為空,堆棧壓入真,否則壓入假
?-name ?????????????????如果項(xiàng)目屬性名稱的值為空,堆棧壓入真,否則壓入假
?name=x或 ?=name=x ???如果項(xiàng)目屬性名稱的值=x,堆棧壓入真,否則壓入假
?
?>name=x ??????????????如果項(xiàng)目屬性名稱的值>x ,堆棧壓入真,否則壓入假
?#操作符 ???適用于操作在堆棧的值。
[if !supportLists]n?[endif]操作字符串是從左向右計(jì)算的。
[if !supportLists]n?[endif]任何其他的字符或單詞的末尾的十進(jìn)制數(shù)字序列被解釋為一個(gè)堆棧指數(shù)。最高值指數(shù)0。
[if !supportLists]n?[endif]后跟一個(gè)字符的索引,壓入該指數(shù)值的副本
[if !supportLists]n?[endif]指數(shù)是由單詞的末尾替換所有值與該指數(shù)的值。
[if !supportLists]n?[endif]!操作符是反義字符,替換堆頂值為反義值;
[if !supportLists]n?[endif]&操作符是邏輯"與"操作符,從堆棧彈出2個(gè)值,進(jìn)行邏輯與操作并將結(jié)果壓于入堆棧
[if !supportLists]n?[endif]|操作符是邏輯"或"操作符, 從堆棧彈出2個(gè)值,進(jìn)行邏輯“或”操作并將結(jié)果壓于入堆棧
[if !supportLists]n?[endif].索引后什么都不做
[if !supportLists]n?[endif].另一個(gè)字符后壓入副本值到堆頂。
例子:
取得所有的以太網(wǎng)和VLAN接口:
/interface/print
?type=ether
?type=vlan
?#|
獲取所有有備注的路由:
/ip/route/print
?>comment=
OID
print命令可以返回屬性是在SNMP OID值。此功能出現(xiàn)在3.23版本以后。
在控制臺,OID值可以運(yùn)行'print oid'命令看出。在API這些屬性有".OID"結(jié)束的名稱,并可以加入他們的名字的值用".proplist"檢索。一個(gè)例子:
/system/resource/print ?
=.proplist=uptime,cpu-load,uptime.oid,cpu-load.oid ??
?!re ?
=uptime=01:22:53 ?
=cpu-load=0 ?
=uptime.oid=.1.3.6.1.2.1.1.3.0 ?
=cpu-load.oid=.1.3.6.1.2.1.25.3.3.1.2.1 ?
?!done ?
命令試?yán)?/b>?:
/system/package/getall
/system/package/getall
?!re
=.id=*5802
=disabled=no
=name=routeros-x86
=version=3.0beta2
=build-time=oct/18/2006 16:24:41
=scheduled=
?!re
=.id=*5805
=disabled=no
=name=system
=version=3.0beta2
=build-time=oct/18/2006 17:20:46
=scheduled=
... 更多?!re 回復(fù)句子?...
?!re
=.id=*5902
=disabled=no
=name=advanced-tools
=version=3.0beta2
=build-time=oct/18/2006 17:20:49
=scheduled=
?!done
?
/user/active/listen
/user/active/listen
?!re
=.id=*68
=radius=no
=when=oct/24/2006 08:40:42
=name=admin
=address=0.0.0.0
=via=console
?!re
=.id=*68
=.dead=yes
加上/cancel的例子:
/login
?!done
=ret=856780b7411eefd3abadee2058c149a3
/login
=name=admin
=response=005062f7a5ef124d34675bf3e81f56c556
?!done
-- first start listening for interface changes (tag is 2)
/interface/listen
.tag=2
-- disable interface (tag is 3)
/interface/set
=disabled=yes
=.id=ether1
.tag=3
-- this is done for disable command (tag 3)
?!done
.tag=3
-- enable interface (tag is 4)
/interface/set
=disabled=no
=.id=ether1
.tag=4
-- this update is generated by change made by first set command (tag 3)
?!re
=.id=*1
=disabled=yes
=dynamic=no
=running=no
=name=ether1
=mtu=1500
=type=ether
.tag=2
-- this is done for enable command (tag 4)
?!done
.tag=4
-- get interface list (tag is 5)
/interface/getall
.tag=5
-- this update is generated by change made by second set command (tag 4)
?!re
=.id=*1
=disabled=no
=dynamic=no
=running=yes
=name=ether1
=mtu=1500
=type=ether
.tag=2
-- these are replies to getall command (tag 5)
?!re
=.id=*1
=disabled=no
=dynamic=no
=running=yes
=name=ether1
=mtu=1500
=type=ether
.tag=5
?!re
=.id=*2
=disabled=no
=dynamic=no
=running=yes
=name=ether2
=mtu=1500
=type=ether
.tag=5
-- here interface getall ends (tag 5)
?!done
.tag=5
-- stop listening - request to cancel command with tag 2, cancel itself uses tag 7
/cancel
=tag=2
.tag=7
-- listen command is interrupted (tag 2)
?!trap
=category=2
=message=interrupted
.tag=2
-- cancel command is finished (tag 7)
?!done
.tag=7
-- listen command is finished (tag 2)
?!done
.tag=2
客戶端例子:?
[if !supportLists]n?[endif]this is simple API client in Python2
[if !supportLists]n?[endif]example for Python3
[if !supportLists]n?[endif]usage: api.py ip-address username password
[if !supportLists]n?[endif]after that type words from keyboard, terminating them with newline
[if !supportLists]n?[endif]Since empty word terminates sentence, you should press enter twice after last word before sentence will be sent to router.
#!/usr/bin/python
import sys, posix, time, md5, binascii, socket, select
class ApiRos:
????"Routeros api"
????def __init__(self, sk):
????????self.sk = sk
????????self.currenttag = 0
????def login(self, username, pwd):
????????for repl, attrs in self.talk(["/login"]):
????????????chal = binascii.unhexlify(attrs['=ret'])
????????md = md5.new()
????????md.update('\x00')
????????md.update(pwd)
????????md.update(chal)
????????self.talk(["/login", "=name=" + username,
???????????????????"=response=00" + binascii.hexlify(md.digest())])
????def talk(self, words):
????????if self.writeSentence(words) == 0: return
????????r = []
????????while 1:
????????????i = self.readSentence();
????????????if len(i) == 0: continue
????????????reply = i[0]
????????????attrs = {}
????????????for w in i[1:]:
????????????????j = w.find('=', 1)
????????????????if (j == -1):
????????????????????attrs[w] = ''
???????????????else:
????????????????????attrs[w[:j]] = w[j+1:]
????????????r.append((reply, attrs))
????????????if reply == '!done': return r
????def writeSentence(self, words):
????????ret = 0
????????for w in words:
????????????self.writeWord(w)
????????????ret += 1
????????self.writeWord('')
????????return ret
????def readSentence(self):
????????r = []
????????while 1:
????????????w = self.readWord()
????????????if w == '': return r
????????????r.append(w)
????def writeWord(self, w):
????????print "<<< " + w
????????self.writeLen(len(w))
????????self.writeStr(w)
????def readWord(self):
????????ret = self.readStr(self.readLen())
????????print ">>> " + ret
????????return ret
????def writeLen(self, l):
????????if l < 0x80:
????????????self.writeStr(chr(l))
????????elif l < 0x4000:
????????????l |= 0x8000
????????????self.writeStr(chr((l >> 8) & 0xFF))
????????????self.writeStr(chr(l & 0xFF))
????????elif l < 0x200000:
????????????l |= 0xC00000
????????????self.writeStr(chr((l >> 16) & 0xFF))
????????????self.writeStr(chr((l >> 8) & 0xFF))
????????????self.writeStr(chr(l & 0xFF))
????????elif l < 0x10000000: ???????
????????????l |= 0xE0000000 ????????
????????????self.writeStr(chr((l >> 24) & 0xFF))
????????????self.writeStr(chr((l >> 16) & 0xFF))
????????????self.writeStr(chr((l >> 8) & 0xFF))
????????????self.writeStr(chr(l & 0xFF))
????????else: ??????????????????????
????????????self.writeStr(chr(0xF0))
????????????self.writeStr(chr((l >> 24) & 0xFF))
????????????self.writeStr(chr((l >> 16) & 0xFF))
????????????self.writeStr(chr((l >> 8) & 0xFF))
????????????self.writeStr(chr(l & 0xFF))
????def readLen(self): ?????????????
????????c = ord(self.readStr(1)) ???
????????if (c & 0x80) == 0x00: ?????
????????????pass ???????????????????
????????elif (c & 0xC0) == 0x80: ???
????????????c &= ~0xC0 ?????????????
????????????c <<= 8 ????????????????
????????????c += ord(self.readStr(1)) ???
????????elif (c & 0xE0) == 0xC0: ???
????????????c &= ~0xE0 ?????????????
????????????c <<= 8 ????????????????
????????????c += ord(self.readStr(1)) ???
????????????c <<= 8 ????????????????
????????????c += ord(self.readStr(1)) ???
????????elif (c & 0xF0) == 0xE0: ???
????????????c &= ~0xF0 ?????????????
????????????c <<= 8 ????????????????
????????????c += ord(self.readStr(1)) ???
????????????c <<= 8 ????????????????
????????????c += ord(self.readStr(1)) ???
????????????c <<= 8 ????????????????
????????????c += ord(self.readStr(1)) ???
????????elif (c & 0xF8) == 0xF0: ???
????????????c = ord(self.readStr(1)) ????
????????????c <<= 8 ????????????????
????????????c += ord(self.readStr(1)) ???
????????????c <<= 8 ????????????????
????????????c += ord(self.readStr(1)) ???
????????????c <<= 8 ????????????????
????????????c += ord(self.readStr(1)) ???
????????return c ???????????????????
????def writeStr(self, str): ???????
????????n = 0; ?????????????????????
????????while n < len(str): ????????
????????????r = self.sk.send(str[n:])
????????????if r == 0: raise RuntimeError, "connection closed by remote end"
????????????n += r ?????????????????
????def readStr(self, length): ?????
????????ret = '' ???????????????????
????????while len(ret) < length: ???
????????????s = self.sk.recv(length - len(ret))
????????????if s == '': raise RuntimeError, "connection closed by remote end"
????????????ret += s
????????return ret
def main():
????s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
????s.connect((sys.argv[1], 8728)) ?
????apiros = ApiRos(s); ????????????
????apiros.login(sys.argv[2], sys.argv[3]);
????inputsentence = []
????while 1:
????????r = select.select([s, sys.stdin], [], [], None)
????????if s in r[0]:
????????????# something to read in socket, read sentence
????????????x = apiros.readSentence()
????????if sys.stdin in r[0]:
????????????# read line from input and strip off newline
????????????l = sys.stdin.readline()
????????????l = l[:-1]
????????????# if empty line, send sentence and start with new
????????????# otherwise append to input sentence
????????????if l == '':
????????????????apiros.writeSentence(inputsentence)
????????????????inputsentence = []
????????????else:
????????????????inputsentence.append(l)
if __name__ == '__main__':
????main()
例子運(yùn)行實(shí)例:
debian@localhost:~/api-test$ ./api.py 10.0.0.1 admin ''
<<< /login
<<<
>>> !done
>>> =ret=93b438ec9b80057c06dd9fe67d56aa9a
>>>
<<< /login
<<< =name=admin
<<< =response=00e134102a9d330dd7b1849fedfea3cb57
<<<
>>> !done
>>>
/user/getall
<<< /user/getall
<<<
>>> !re
>>> =.id=*1
>>> =disabled=no
>>> =name=admin
>>> =group=full
>>> =address=0.0.0.0/0
>>> =netmask=0.0.0.0
>>>
>>> !done
>>>
參考資料?
[if !supportLists]§?[endif]API command notes
API examples in the Wiki
[if !supportLists]§?[endif]in PHP#1
[if !supportLists]§?[endif]in PHP using PEAR2#2
[if !supportLists]§?[endif]in Delphi#1
[if !supportLists]§?[endif]in Delphi#2
[if !supportLists]§?[endif]in C
[if !supportLists]§?[endif]in C using winsock
[if !supportLists]§?[endif]API in C++
[if !supportLists]§?[endif]in C#
[if !supportLists]§?[endif]in Flash Actionscript 3
[if !supportLists]§?[endif]in Ruby on rails
[if !supportLists]§?[endif]in VB .NET
[if !supportLists]§?[endif]in java
[if !supportLists]§?[endif]in NodeJS
[if !supportLists]§?[endif]Python3
API examples on the MikroTik Forum
[if !supportLists]§?[endif]in Perlby Hugh
[if !supportLists]§?[endif]in Delphiby Rodolfo
[if !supportLists]§?[endif]in Delphi #2by Chupaka
[if !supportLists]§?[endif]in NodeJSby Trakkasure
[if !supportLists]§?[endif]in VBby lucho512
[if !supportLists]§?[endif]on PHP for sparks frameworkby vthinkteam
API exmaples elsewhere
[if !supportLists]§?[endif]in .NET (C#) high-level api solutionby danikf
[if !supportLists]§?[endif]in PHPby boen_robot
Retrieved from "http://wiki.mikrotik.com/wiki/Manual:API"
看完API后,對ros會有一個(gè)基本的認(rèn)識,下面來看一些常用命令的解釋:
-------------------------------------------------------------------------------
..:上級目錄
/:返回到根目錄
ip:ip選項(xiàng)
print:打印數(shù)據(jù)配置信息
interface:接口
add:新增配置項(xiàng)
address:地址
set:修改配置參數(shù)
enable/disable:相關(guān)項(xiàng)目的允許/禁止
export/import:導(dǎo)出/導(dǎo)出配置腳本
password:修改密碼
-------------------------------------------------------------------------------
ROS常用命令:
===============================================================================
①返回上一層目錄..
②補(bǔ)全命令TAB
③重啟/關(guān)機(jī) /sy reboot /sy showdown
④備份路由/sy BACKUP 回車 save name=文件名
⑤恢復(fù)路由/sy BACKUP 回車 load name=文件名
⑥恢復(fù)原始狀態(tài)/sy reset
裝上了ros3.2之后:
第一步,配置IP:
先查看IP配置,如果有默認(rèn)的配置,請用remove命令刪除,如:
[admin@MikroTik]/ip address>pri
[admin@MikroTik]remove 0
[admin@MikroTik]>ip
[admin@MikroTik]/ip>addr
[admin@MikroTik]/ip address>add address 192.168.1.1/24 interface ether1
[admin@MikroTik]/ip address>add address 10.10.1.7/16 interface ether2
接互聯(lián)網(wǎng)的網(wǎng)卡為10.10.1.7那塊
第二步,為了讓網(wǎng)卡更直觀些,更改網(wǎng)卡名稱:
[admin@MikroTik]/interface> set 0 name=lan
[admin@MikroTik]/interface> set 1 name=wan
這里的0,1兩個(gè)數(shù)字是以你在/interface print中看到的網(wǎng)卡資料的每行最前面那個(gè)數(shù)字為準(zhǔn)。
[admin@MikroTik] /interface>print
Flags: X - disabled, D - dynamic, R - running
# ?????NAME ??TYPE ???MTU
0 R ???wan ????ether ???1500
1 R ???lan ??????ether ???1500
好的,再看看
[admin@MikroTik]/ip address>print
Flags:X-disabled, I-invalid, D-dynamic
# ???ADDRESS ???????????????NETWORK ????????????BROADCAST ??????????INTERFACE
0 ????192.168.1.1/24 ???????192.168.1.0 ????????192.168.1.155 ??????????lan
1 ????10.10.1.7/16 ???????????10.10.0.0 ???????????10.10.255.255 ??????????wan
當(dāng)然,這個(gè)可做可不做,屬于可選項(xiàng),嘿嘿。
第三步,設(shè)置網(wǎng)關(guān):
[admin@MikroTik]/ip route >add gateway=10.10.1.2
網(wǎng)關(guān)地址就是你WAN口網(wǎng)卡對應(yīng)的網(wǎng)關(guān)。
可用下面命令查看:
[admin@MikroTik]/ip route >pri
第四步,打開IP轉(zhuǎn)發(fā):
[admin@MikroTik]/ip firewall> nat add action=masquerade out-interface=WAN chain=srcnat
OK,到現(xiàn)在為止,如果不考慮網(wǎng)絡(luò)安全的話,你內(nèi)網(wǎng)的機(jī)器只要把IP設(shè)為192.168.1.2-192.168.1.255這個(gè)網(wǎng)段,
網(wǎng)關(guān)指向192.168.1.1的話,應(yīng)該上網(wǎng)了。
TIPS:
關(guān)機(jī)命令:/system shutdown
設(shè)置復(fù)位:/system reset
ROS自帶了DNS,并且能緩存你最近查詢過的DNS記錄,好,下面我們就來
開啟ROS自帶的DNS功能:
[admin@MikroTik]/ip dns>set primary-dns=61.128.192.68 secondary-dns=61.128.128.68 allow-remote-requests=yes cache-size=8192
說明:
primary-dns 主DNS服務(wù)器IP
secondary-dns輔DNS服務(wù)器IP
allow-remote-requests參數(shù):(yes | no)是否允許來自遠(yuǎn)方的DNS查詢請求,既然他要為局域網(wǎng)服務(wù),我們當(dāng)然要設(shè)置為YES
cache-size參數(shù):(整數(shù): 512-10240; 默認(rèn)值: 2048KiB) DNS緩存的大小
添加靜態(tài)DNS項(xiàng)
[admin@MikroTik]/ip dns> static add name=www.163.com address=220.181.28.42
name (文本文字) - 你需要添加的域名
address (IP地址) - 上面這個(gè)域名對應(yīng)的IP
查看靜態(tài)DNS項(xiàng)
[admin@MikroTik]/ip dns>static print
修理靜態(tài)DNS項(xiàng)
[admin@MikroTik] /ip dns> static set 0 name=news.163.com
參數(shù):
--你要修改的項(xiàng)在靜態(tài)列表中的位置,整數(shù),上面是0
name --你需要改成的域名
address --你需要修改成的IP地址
把我們剛才添加的域名從www.163.com改成news.163.com,又或者www.163.com被更改了IP,那么我們就用/ip dns static set 0 address=1.2.3.4,說一下,set后面這個(gè)0就是你用/ip dns> static print顯示出來的每行最前面的那個(gè)數(shù)字。
刪除靜態(tài)DNS項(xiàng):
[admin@MikroTik] /ip dns>static remove 0
緩存管理
查看當(dāng)前緩存中的內(nèi)容:
[admin@MikroTik] /ip dns> cache print
清空當(dāng)前緩存中的內(nèi)容:
[admin@MikroTik] /ip dns> cache flush
當(dāng)然,你添加的靜態(tài)表項(xiàng)不會被清空。