Scripting: how to find last backup (part 2)

Итак, пусть по какой-то причине команда

/files print

выдает файлы не в порядке их создания. В конце концов, в документации нигде не написано – что она должна так выдавать и не факт, что в следующей прошивке такая закономерность останется.

Значит тогда нужно смотреть время создания бэкапа и выбрать тот, у которого время больше.

Опять-таки, считаем, что время на роутере выставлено правильно и синхронизируется с ntp сервером.

Давайте сперва глянем на свойства любого файла. Для этого сперва выполним команду

/file print

и потом в столбике # подсмотрим номер для любого из бэкапов:

# NAME TYPE SIZE CREATION-TIME 
 0 skins directory jan/01/1970 02:00:03
 1 20150602-2214-cleared.rsc script 9.8KiB jun/02/2015 21:15:03
 2 pub directory jun/02/2015 21:15:02
 3 cert_export_ca.crt .crt file 1342 apr/07/2016 16:41:27
 4 cert_export_ca.key .key file 1858 apr/07/2016 16:41:27
 5 dude dude store may/13/2016 07:42:31
 6 autosupout.old.rif .rif file 781.0KiB jun/16/2016 23:22:21
 7 autosupout.rif .rif file 847.9KiB jun/27/2016 15:24:16
 8 CCR-Home-20161107-1507.backup backup 371.4KiB nov/07/2016 15:07:26
 9 current.rsc script 28.2KiB nov/07/2016 15:08:36
10 CCR-Home-20161107-1751.backup backup 371.4KiB nov/07/2016 17:51:54
11 CCR-Home-20161107-1753.backup backup 371.4KiB nov/07/2016 17:53:48

Мне понравился бэкап с номером 8. Глянем его свойства:

:put [/file get 8]

Видим что-то такое:

.id=*d0d1c;creation-time=nov/07/2016 15:07:26;name=CCR-Home-20161107-1507.backup;size=380340;type=backup

Тут перечислены все свойства и их значения, с которыми мы можем работать потом в скрипте. Легко догадаться, что свойство “creation-time” – это и есть время создания бэкапа. Тип свойства – строка:

:put [:typeof ([/file get 8]->"creation-time")]

возвращает

str

К сожалению в RouterOS нет специального типа для даты-времени. Кто-то может сказать, что в документации Микротик черным по-белому написано

time – date and time value;

Но тут есть доля лукавства. Реально этот тип хранит данные в виде “число_дней+время”, например, “10:45:00” или “10d15:30:10”. Он не позволяет хранить именно дату. Функция :totime позволяет преобразовать текст типа “10d15:30:10” во внутренний формат time. Зачем? Просто время в текстовом виде мы не можем сравнить, но можем сравнивать время в формате time. Этим мы чуть позже воспользуемся.

А пока вопрос, что же делать с “creation-time”?

Давайте вытянем из него отдельно дату создания, отдельно время создания. Для этого воспользуемся функцией pick.

Итак выведем само время creation-time:

:put ([/file get 8]->"creation-time")

Видим результат

nov/07/2016 15:07:26

Готовим пальцы рук и ног и считаем – дата у нас занимает первые 11 символов (то есть от 0 и до 10 включительно), время – 8 символов, с 12 по 19 включительно.

При этом помним, что в pick указываются позиции ОТ и ДО, но ДО именно ДО, не включительно. Именно поэтому чтобы вывести отдельно дату и время мы вторую цифру увеличиваем на 1:

:put [:pick ([/file get 8]->"creation-time") 0 11]

:put [:pick ([/file get 8]->"creation-time") 12 20]

Дату и время вытянули.

Теперь как их сравнивать?

Для времени просто – преобразуем из строки во внутренний формат с помощью totime и просто сравниваем как обычные числа.

Для даты сложнее. Чуть-чуть. Просто напишем отдельную функцию сравнения дат – я ее уже написал и ее можно увидеть тут – func_cmp2dates . В принципе ничего сложного, те же pick. Чтобы воспользоваться этой функцией, загрузите ее себе в хранилище скриптов и потом в любом скрипте, где ее нужно вызвать, выполните в самом начале команду:

:global cmp2dates [:parse [/system script get func_cmp2dates source]]

Это строка по сути создает функцию cmp2dates на основе кода скрипта func_cmp2dates.

Для ее вызова потом в любом месте Вашего скрипта просто вызываете, например:

[$cmp2dates date1="sep/13/2016" date2="oct/12/2015"]

Для удобства на сайте заведен список таких скриптов-функций – List of scripts, и примеры вызова скриптов можно подсмотреть тут – Examples

Ну и сводим всё воедино:

#####################################
# Script: func_getlastbackup 
# Input: None 
# Output: return name of last backup using creation-time 
#####################################
#use external functions
:global cmp2dates [:parse [/system script get func_cmp2dates source]]

#local variables
:local resName ""
:local resDate ""
:local resTime ""

#получаем список бєкапов
:local arrBackups ([/file find type=backup])

#перебираем бэкапы
:foreach id in $arrBackups do={
 #для каждого из них получаем список его свойств
 :local backup [/file get $id]
 #достаем имя, время и дату создания бэкапа
 :local curName ($backup->"name")
 :local curCreationTime ($backup->"creation-time")
 :local curDate [:pick $curCreationTime 0 11]
 :local curTime [:pick $curCreationTime 12 20]
 #первоначально у нас не с чем сравнивать - запоминаем первый бекап
 :if ($resName="" ) do={
  :set $resName $curName
  :set $resDate $curDate
  :set $resTime $curTime
 }
 #сравниваем запомненный бекап с текущим и если он новее - запоминаем его
 :local cmp [$cmp2dates date1=$curDate date2=$resDate]
 :if ($cmp=1 or ($cmp=0 and [:totime $curTime]>[:totime $resTime])) do={
  :set $resName $curName
  :set $resDate $curDate
  :set $resTime $curTime
 }
}
:return $resName

Вуаля и

beer