介绍
本节包含一些有用的脚本,展示了所有可用的脚本特性。本节中使用的脚本示例使用最新的3.x版本。
创建文件
不能直接创建文件,但是有一个解决方案:
/file print file=myFile
/file set myFile.txt contents=""
检查接口上的IP是否改变
有些提供商提供动态IP地址。此脚本将比较动态IP地址是否更改。
:global currentIP;
:local newIP [/ip address get [find interface="ether1"] address];
:if ($newIP != $currentIP) do={
:put "ip address $currentIP changed to $newIP";
:set currentIP $newIP;
}
剥离掩码
如果需要一个没有子网掩码的IP地址(例如在防火墙中使用它),而" / IP address get [id] address"会返回IP地址和子网掩码,因此这个脚本很有用。
:global ipaddress 10.1.101.1/24
:for i from=( [:len $ipaddress] - 1) to=0 do={
:if ( [:pick $ipaddress $i] = "/") do={
:put [:pick $ipaddress 0 $i]
}
}
另一种更简单的方法:
:global ipaddress 10.1.101.1/24
:put [:pick $ipaddress 0 [:find $ipaddress "/"]]
解析主机名
许多用户要求在radius服务器、防火墙规则等方面使用DNS名称而不是IP地址。
下面是一个如何解析RADIUS服务器IP的示例。
假设已经配置了radius服务器:
/radius
add address=3.4.5.6 comment=myRad
下面是一个解析IP地址的脚本,将解析的IP地址与配置的IP地址进行比较,如果不相等,则替换它:
/system script add name="resolver" source= {
:local resolvedIP [:resolve "server.example.com"];
:local radiusID [/radius find comment="myRad"];
:local currentIP [/radius get $radiusID address];
:if ($resolvedIP != $currentIP) do={
/radius set $radiusID address=$resolvedIP;
/log info "radius ip updated";
}
}
将此脚本添加到调度器中,例如每5分钟运行一次
/system scheduler add name=resolveRadiusIP on-event="resolver" interval=5m
在多个文件中写入简单的队列统计
考虑队列命名是“一些文本”。可以通过“."后面的最后一个数字来搜索队列。
:local entriesPerFile 10;
:local currentQueue 0;
:local queuesInFile 0;
:local fileContent "";
#determine needed file count
:local numQueues [/queue simple print count-only] ;
:local fileCount ($numQueues / $entriesPerFile);
:if ( ($fileCount * $entriesPerFile) != $numQueues) do={
:set fileCount ($fileCount + 1);
}
#remove old files
/file remove [find name~"stats"];
:put "fileCount=$fileCount";
:for i from=1 to=$fileCount do={
#create file
/file print file="stats$i.txt";
#clear content
/file set [find name="stats$i.txt"] contents="";
:while ($queuesInFile < $entriesPerFile) do={
:if ($currentQueue < $numQueues) do={
:set currentQueue ($currentQueue +1);
:put $currentQueue ;
/queue simple
:local internalID [find name~"\\.$currentQueue\$"];
:put "internalID=$internalID";
:set fileContent ($fileContent . [get $internalID target-address] . \
" " . [get $internalID total-bytes] . "\r\n");
}
:set queuesInFile ($queuesInFile +1);
}
/file set "stats$i.txt" contents=$fileContent;
:set fileContent "";
:set queuesInFile 0;
}
生成备份并通过电子邮件发送
该脚本生成一个备份文件并将其发送到指定的电子邮件地址。邮件主题包含路由器的名称、当前日期和时间。
注意,在使用此脚本之前,必须先配置SMTP服务器。有关配置选项,请参见 /tool e-mail 。
/system backup save name=email_backup
/tool e-mail send file=email_backup.backup to="me@test.com" body="See attached file" \
subject="$[/system identity get name] $[/system clock get time] $[/system clock get date] Backup")
备份文件中包含密码等敏感信息。因此,要访问生成的备份文件,脚本或调度程序必须具有“敏感”策略。
使用string作为函数
:global printA [:parse ":local A; :put \$A;" ];
$printA
检查带宽并添加限制
该脚本检查接口上的下载是否超过512kbps,如果是,则添加队列以将速度限制为256kbps。
:foreach i in=[/interface find] do={
/interface monitor-traffic $i once do={
:if ($"received-bits-per-second" > 0 ) do={
:local tmpIP [/ip address get [/ip address find interface=$i] address] ;
# :log warning $tmpIP ;
:for j from=( [:len $tmpIP] - 1) to=0 do={
:if ( [:pick $tmpIP $j] = "/") do={
/queue simple add name=$i max-limit=256000/256000 dst-address=[:pick $tmpIP 0 $j] ;
}
}
}
}
}
阻止访问特定网站
如果想阻止某些网站,但不想使用web代理,可以用这个脚本。
本例查看DNS缓存中的“Rapidshare”和“youtube”条目,并将ip添加到名为“restricted”的地址列表中。在开始之前,必须设置一个路由器来捕获所有DNS请求:
/ip firewall nat
add action=redirect chain=dstnat comment=DNS dst-port=53 protocol=tcp to-ports=53
add action=redirect chain=dstnat dst-port=53 protocol=udp to-ports=53
添加防火墙
/ip firewall filter
add chain=forward dst-address-list=restricted action=drop
现在可以编写一个脚本每30秒运行一次。
脚本代码:
:foreach i in=[/ip dns cache find] do={
:local bNew "true";
:local cacheName [/ip dns cache all get $i name] ;
# :put $cacheName;
:if (([:find $cacheName "rapidshare"] >= 0) || ([:find $cacheName "youtube"] >= 0)) do={
:local tmpAddress [/ip dns cache get $i address] ;
# :put $tmpAddress;
# if address list is empty do not check
:if ( [/ip firewall address-list find list="restricted" ] = "") do={
:log info ("added entry: $[/ip dns cache get $i name] IP $tmpAddress");
/ip firewall address-list add address=$tmpAddress list=restricted comment=$cacheName;
} else={
:foreach j in=[/ip firewall address-list find list="restricted"] do={
:if ( [/ip firewall address-list get $j address] = $tmpAddress ) do={
:set bNew "false";
}
}
:if ( $bNew = "true" ) do={
:log info ("added entry: $[/ip dns cache get $i name] IP $tmpAddress");
/ip firewall address-list add address=$tmpAddress list=restricted comment=$cacheName;
}
}
}
}
解析文件添加ppp
该脚本要求文件中的条目采用以下格式:
username,password,local_address,remote_address,profile,service
例如:
janis,123,1.1.1.1,2.2.2.1,ppp_profile,myService
juris,456,1.1.1.1,2.2.2.2,ppp_profile,myService
aija,678,1.1.1.1,2.2.2.3,ppp_profile,myService
:global content [/file get [/file find name=test.txt] contents] ;
:global contentLen [ :len $content ] ;
:global lineEnd 0;
:global line "";
:global lastEnd 0;
:do {
:set lineEnd [:find $content "\r\n" $lastEnd ] ;
:set line [:pick $content $lastEnd $lineEnd] ;
:set lastEnd ( $lineEnd + 2 ) ;
:local tmpArray [:toarray $line] ;
:if ( [:pick $tmpArray 0] != "" ) do={
:put $tmpArray;
/ppp secret add name=[:pick $tmpArray 0] password=[:pick $tmpArray 1] \
local-address=[:pick $tmpArray 2] remote-address=[:pick $tmpArray 3] \
profile=[:pick $tmpArray 4] service=[:pick $tmpArray 5];
}
} while ($lineEnd < $contentLen)
检测新日志条目
这个脚本检查一个新的日志条目是否被添加到一个特定的缓冲区。
在这个例子中使用PPPoE日志:
/system logging action
add name="pppoe"
/system logging
add action=pppoe topics=pppoe,info,!ppp,!debug
日志缓冲区看起来类似这样:
[admin@mainGW] > /log print where buffer=pppoe
13:11:08 pppoe,info PPPoE connection established from 00:0C:42:04:4C:EE
现在可以编写一个脚本来检测是否添加了新条目。
:global lastTime;
:global currentBuf [ :toarray [ /log find buffer=pppoe ] ] ;
:global currentLineCount [ :len $currentBuf ] ;
:global currentTime [ :totime [/log get [ :pick $currentBuf ($currentLineCount -1) ] time ] ];
:global message "";
:if ( $lastTime = "" ) do={
:set lastTime $currentTime ;
:set message [/log get [ :pick $currentBuf ($currentLineCount-1) ] message];
} else={
:if ( $lastTime < $currentTime ) do={
:set lastTime $currentTime ;
:set message [/log get [ :pick $currentBuf ($currentLineCount-1) ] message];
}
}
检测到新项后,将其保存在message变量中,以后可以使用该变量解析日志消息,例如获取PPPoE client的mac地址。
允许使用 ntp.org 池服务作为NTP
此脚本解析两个NTP服务器的主机名,将结果与当前NTP设置进行比较,如果不一致则更改地址。由于RouterOS不允许在NTP配置中使用主机名,所以要使用该脚本。用了两个脚本,第一个定义了一些在其他脚本中使用的系统变量,第二个完成基本工作:
# System configuration script - "GlobalVars"
:put "Setting system globals";
# System name
:global SYSname [/system identity get name];
# E-mail address to send notifications to
:global SYSsendemail "mail@my.address";
# E-mail address to send notifications from
:global SYSmyemail "routeros@my.address";
# Mail server to use
:global SYSemailserver "1.2.3.4";
# NTP pools to use (check www.pool.ntp.org)
:global SYSntpa "0.uk.pool.ntp.org";
:global SYSntpb "1.uk.pool.ntp.org";
# Check and set NTP servers - "setntppool"
# We need to use the following globals which must be defined here even
# though they are also defined in the script we call to set them.
:global SYSname;
:global SYSsendemail;
:global SYSmyemail;
:global SYSmyname;
:global SYSemailserver;
:global SYSntpa;
:global SYSntpb;
# Load the global variables with the system defaults
/system script run GlobalVars
# Resolve the two ntp pool hostnames
:local ntpipa [:resolve $SYSntpa];
:local ntpipb [:resolve $SYSntpb];
# Get the current settings
:local ntpcura [/system ntp client get primary-ntp];
:local ntpcurb [/system ntp client get secondary-ntp];
# Define a variable so we know if anything's changed.
:local changea 0;
:local changeb 0;
# Debug output
:put ("Old: " . $ntpcura . " New: " . $ntpipa);
:put ("Old: " . $ntpcurb . " New: " . $ntpipb);
# Change primary if required
:if ($ntpipa != $ntpcura) do={
:put "Changing primary NTP";
/system ntp client set primary-ntp="$ntpipa";
:set changea 1;
}
# Change secondary if required
:if ($ntpipb != $ntpcurb) do={
:put "Changing secondary NTP";
/system ntp client set secondary-ntp="$ntpipb";
:set changeb 1;
}
# If we've made a change, send an e-mail to say so.
:if (($changea = 1) || ($changeb = 1)) do={
:put "Sending e-mail.";
/tool e-mail send \
to=$SYSsendemail \
subject=($SYSname . " NTP change") \
from=$SYSmyemail \
server=$SYSemailserver \
body=("Your NTP servers have just been changed:\n\nPrimary:\nOld: " . $ntpcura . "\nNew: " \
. $ntpipa . "\n\nSecondary\nOld: " . $ntpcurb . "\nNew: " . $ntpipb);
}
调度器条目:
/system scheduler add \
comment="Check and set NTP servers" \
disabled=no \
interval=12h \
name=CheckNTPServers \
on-event=setntppool \
policy=read,write,test \
start-date=jan/01/1970 \
start-time=16:00:00