找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 9312|回复: 22

[脚本] 原创:计算星期几的脚本

[复制链接]
发表于 2007-11-30 15:33:42 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?注册

×
由于ros没有星期的数据,给定时调度方面造成一些困扰,虽然也可以换一个思路实现,比如给每天做一个调度,执行间隔为7天,但是显得很烦琐
搜索了很久,也没有找到类似的解决办法,于是经过一些思考就写了一个计算星期几的脚本,经测试达到了预期的设想,由于是在学习期间,也是为了练习一下写脚本的基本功

练习中的心得:任何变量在使用前必须先经过赋值初始化,否则会产生意想不到的结果,我在这方面走了不少弯路,最后才发现是这个问题,新手可以作为一个借鉴



##############################################################
#脚本名称:week                                               #
#脚本功能:计算当前日期是星期几                               #
#脚本用法:在其他脚本中运行/sys scr run week                  #
#         然后用变量$WEEK取得计算结果,0为星期天             #
#脚本作者:hcb                                                #
#创建日期:2007-11-30                                         #
##############################################################

:global WEEK 0
#-------------------------------------------------------
#取当前日期,变成数字YY(年),MM(月),DD(日)
:set str (jan,feb,mar,apr,may,jun,jul,aug,sep,oct,nov,dec)
:set tmp [/sys clock get date]
:set YY [:tonum([:pick $tmp 7 11])]
:set DD [:tonum([:pick $tmp 4  6])]
:set n 1
:set MM $n
:set s [:pick $tmp 0  3]
:foreach i in=$str do={
  :if($s=$i) do={:set MM $n}
  :set n ($n + 1)
  }
#------------------------------------------------------
#以2000年1月1日星期6为基准,
#计算2000年1月1日到现在经过了多少天
#基准年
:set y1 2000
#基准年1月1日是星期几
:set w1 6
#基准初始天数,即星期几-1
:set day ($w1 - 1)
#计算到现在的总天数
:set d 0
:for y from=$y1 to=$YY do={
  :set m2 12
  :if($y=$YY) do={:set m2 $MM}
  :for m from=1 to=$m2 do={
    :set temp "若是本月,则该月取现在天数,本行是注释"
    :if($m=$m2) do={:set d $DD}\
    else={
      :set temp "若是2月,要考虑平月闰月,本行是注释"
      :if($m=2) do={
        :set temp "润年是四年一润,本行是注释"
        :if($y -($y/4)*4=0) do={:set d 29} else={:set d 28}
        }
      :if($m!=2) do={
        :set tmp "若是小月,则该月天数为30天,否则是31天,本行是注释"
        :if($m=4||$m=6||$m=9||$m=11) do={:set d 30} else={:set d 31}
        }
      }
    :set tmp "总天数加该月天数,本行是注释"
    :set day ($day + $d)
    }
  }
#----------------------------------------------------------
#计算总天数除以7的余数就是星期几
#这是一个特殊的算法,由于ROS没有求余的运算,又不支持小数,故如此
:set WEEK ($day -($day/7)*7)
#----------脚本结束---------

[ 本帖最后由 hcb 于 2007-12-1 13:40 编辑 ]
routeros
发表于 2007-11-30 16:04:03 | 显示全部楼层
强啊,顶一下
routeros
回复

使用道具 举报

发表于 2007-11-30 17:19:46 | 显示全部楼层
在那个地方可以看到效果呀
routeros
回复

使用道具 举报

 楼主| 发表于 2007-11-30 17:26:59 | 显示全部楼层
在你的脚本里面使用变量$WEEK,其值就是星期的几,数字从0到6
可以把上面的脚本复制建立一个脚本,名为week, (其实也可以任意叫其他名字,调用时选正确就是了)
然后在终端里运行
/sys scr run week
:put $WEEK

这样就显示了结果,看看对不对
routeros
回复

使用道具 举报

发表于 2007-12-2 01:05:30 | 显示全部楼层
帮你顶起来,虽然暂时还用不上,不过还是收藏了起来,还有谢谢你上次的帮助.
routeros
回复

使用道具 举报

发表于 2007-12-2 03:13:23 | 显示全部楼层
其实ROS应该有星期的数据,只是不知如何输出,不然filter里不会有星期的设置
routeros
回复

使用道具 举报

发表于 2007-12-3 09:42:04 | 显示全部楼层
怎么我检测出来一只都是 0 的?
今天已经星期一了,可是我检测到还是0啊,脚本照上面复制的,
运行
:set shendown1 [/system clock get date]
:set shendown2 [/system clock get time]
:set shendown3 [/sys scr run week]
:set shendown ("现在时间是: " . $shendown1 . " " . $shendown2 . " 星期" . $WEEK)
:log info $shendown
检测出来的星期一直是0
未命名.jpg
是我哪里搞错了吗?
routeros
回复

使用道具 举报

 楼主| 发表于 2007-12-3 10:06:27 | 显示全部楼层
我在应用的过程中,也发现了这一问题,后来变通的解决了

那就是ROS的脚本执行顺序的问题,当主脚本调用另外一个子脚本的时候,主脚本并没有停下来等待子脚本完成,而是继续执行主脚本的下一语句,实际上是并发的在运行两个脚本,子脚本运行始终是要多花时间的,而这时在主脚本中引用全程变量的值并没有被改变,所以得不到正确的结果
ROS的脚本,和常规的其他程序脚本还是有一些另类的

解决的办法是在调用子脚本的后面加一条等待语句,等待子脚本的完成,到底等待多久,要取决于子脚本的运行时间,但在不影响应用的情况下,多等待一下是比较稳妥的

把你上面的代码换成下面的就可以了:

:set shendown1 [/system clock get date]
:set shendown2 [/system clock get time]
/sys scr run week
#停留1秒钟,等待星期的计算完成,或者时间改短点也行
:delay 1
:set shendown ("现在时间是: " . $shendown1 . " " . $shendown2 . " 星期" . $WEEK)
:log info $shendown
routeros
回复

使用道具 举报

发表于 2007-12-3 11:41:34 | 显示全部楼层
嗯,应用成功了,谢谢.
1.jpg

[ 本帖最后由 17941487 于 2007-12-3 11:45 编辑 ]
routeros
回复

使用道具 举报

 楼主| 发表于 2007-12-8 09:23:44 | 显示全部楼层
今天发现一个错误,今天(2007-12-08)的星期数算出来居然是错误的
一步一步的排查,发现 tonum命令有bug, (或者是我的用法不对?)
发现有时tonum得不到正确结果
在控制台做如下测试
Terminal vt102 detected, using multiline input mode
[admin@MikroTik] > :put [:tonum "01"]
1
[admin@MikroTik] > :put [:tonum "02"]
2
[admin@MikroTik] > :put [:tonum "03"]
3
[admin@MikroTik] > :put [:tonum "04"]
4
[admin@MikroTik] > :put [:tonum "05"]
5
[admin@MikroTik] > :put [:tonum "06"]
6
[admin@MikroTik] > :put [:tonum "07"]
7
[admin@MikroTik] > :put [:tonum "08"]

[admin@MikroTik] > :put [:tonum "09"]

[admin@MikroTik] > :put [:tonum "10"]  
10
[admin@MikroTik] >
发现"08" "09"两个得不到结果
为避免这个错误,就对原来的代码进行一点改进,把前面的0去掉再转换
原来的
:set DD [:tonum([:pick $tmp 4  6])]
改为
:set s [:pick $tmp 4 6]
:if([:find $s "0"]=0) do={:set s [:pick $s 1 [:len $s]]}
:set DD [:tonum($s)]
结果纠正了该错误

完整的代码为:
##############################################################
#脚本名称:week                                                #
#脚本功能:计算当前日期是星期几                                         #
#脚本用法:在其他脚本中运行/sys scr run week                     #
#                      :delay 1s                            #
#         然后用变量$WEEK取得计算结果,0为星期天                    #
#脚本作者:hcb                                                 #
#创建日期:2007-11-30                                          #
##############################################################

:global WEEK 0
#-------------------------------------------------------
#取当前日期,变成数字YY(年),MM(月),DD(日)
:set str (jan,feb,mar,apr,may,jun,jul,aug,sep,oct,nov,dec)
:set tmp [/sys clock get date]
:set YY [:tonum([:pick $tmp 7 11])]
:set s [:pick $tmp 4 6]
:if([:find $s "0"]=0) do={:set s [:pick $s 1 [:len $s]]}
:set DD [:tonum($s)]
:set n 1
:set MM $n
:set s [:pick $tmp 0  3]
:foreach i in=$str do={
  :if($s=$i) do={:set MM $n}
  :set n ($n + 1)
  }
#------------------------------------------------------
#以2000年1月1日星期6为基准,
#计算2000年1月1日到现在经过了多少天
#基准年
:set y1 2000
#基准年1月1日是星期几
:set w1 6
#基准初始天数,即星期几-1
:set day ($w1 - 1)
#计算到现在的总天数
:set d 0
:for y from=$y1 to=$YY do={
  :set m2 12
  :if($y=$YY) do={:set m2 $MM}
  :for m from=1 to=$m2 do={
    :set temp "若是本月,则该月取现在天数,本行是注释"
    :if($m=$m2) do={:set d $DD}\
    else={
      :set temp "若是2月,要考虑平月闰月,本行是注释"
      :if($m=2) do={
        :set temp "润年是四年一润,本行是注释"
        :if($y -($y/4)*4=0) do={:set d 29} else={:set d 28}
        }
      :if($m!=2) do={
        :set tmp "若是小月,则该月天数为30天,否则是31天,本行是注释"
        :if($m=4||$m=6||$m=9||$m=11) do={:set d 30} else={:set d 31}
        }
      }
    :set tmp "总天数加该月天数,本行是注释"
    :set day ($day + $d)
    }
  }
#----------------------------------------------------------
#计算总天数除以7的余数就是星期几
#这是一个特殊的算法,由于ROS没有求余的运算,又不支持小数,故如此
:set WEEK ($day -($day/7)*7)

[ 本帖最后由 hcb 于 2007-12-8 09:27 编辑 ]
routeros
回复

使用道具 举报

发表于 2007-12-9 13:28:16 | 显示全部楼层
好东西,收藏了。
routeros
回复

使用道具 举报

 楼主| 发表于 2007-12-9 19:31:46 | 显示全部楼层
再改一句有潜在问题的
原来
#基准初始天数,即星期几-1
:set day ($w1 - 1)
改为
#基准初始天数,即星期几-1
:if($w1>0) do={:set day ($w1 - 1)} else={:set day 6}
routeros
回复

使用道具 举报

发表于 2007-12-10 12:40:31 | 显示全部楼层
怎么我换了上面的反而显示不出来的?
2.jpg.jpg

1.jpg
routeros
回复

使用道具 举报

 楼主| 发表于 2007-12-10 13:36:13 | 显示全部楼层
忘记了,要先对变量赋值,否则出错,这是ROS脚本的特点,一不小心就忘记了
:set day 0
:if($w1>0) do={:set day ($w1 - 1)} else={:set ady 6}
对于该例子中特定的
:set w1 6
你照原来的那样也没问题的,但如果基准改成其他日子,正好是星期天的话,原来的就有问题
routeros
回复

使用道具 举报

发表于 2007-12-11 01:28:19 | 显示全部楼层
:foreach i in="mon,tue,wed,thu,fri,sat,sun" do={
/ip fir fil add chain=output protocol=icmp \
time=(0 . s . "-" . 23 . h . 59 . m . , . $i) action=add-dst-to-address-list \
address-list=$i address-list-timeout=30s comment=(week . $i)
}
/ping 4.3.2.1 count=2
/ ip firewall address-list
:global week [get [find address=4.3.2.1 dynamic=yes] list]
remove [find address=4.3.2.1 dynamic=yes]
:foreach i in="mon,tue,wed,thu,fri,sat,sun" do={
/ip fir fil remove (week . $i)
}
:log info ([/sys clo get time] . " " . $week . " " . [/sys clo get date]



:if ([/sys sch find start-time=startup]!="") do={
:set tt [/sys sch get [/sys sch find start-time=startup] on-event]
/sys scr set [/sys scr find name=$tt] source=([/sys scr get [/sys scr find name=$tt] source] . "\n:global week 8")
} ELSE={
/sys sch add name="startup" on-event=script-startup start-time=startup
/sys scr add name=script-startup source=":global week 8"
}

俺来写一个
routeros
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

QQ|Archiver|手机版|小黑屋|软路由 ( 渝ICP备15001194号-1|渝公网安备 50011602500124号 )

GMT+8, 2024-11-17 20:36 , Processed in 0.121289 second(s), 5 queries , Gzip On, Redis On.

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表