= bubbalog =Дневникът на моето стадо

Скриптове за автоматичен бекъп на файлове и директории

Saturday 10.01.2009 14:44 EEST · Публикувано от в = FreeBSD =

То от това заглавие май не става много ясно какво е заданието, но нека поясня. Става дума са следното: имам няколко файла, които искам да бекъпвам в случай, че се променят или изтрият. До момента използвах един прост едноредов скрипт (ако може така да се нарече) наречен backuper.sh и поставен в crontab

#!/bin/sh
tar czvf /dir/za/arhiwiranite/log_`date +’%Y-%m-%d-%H-%M-%S’`.tar.gz /target/za/arhivirane

с който просто архивирах една цяла директория с логове, но това е крайно неудобно, защото се генерира огромно количество файлове, които после ако и требе да прегледаш… Трябваше ми скрипт, който да проверява даден файл, да проверява дали е променян и ако да – да направи копие на файла. Но как да стане? Като начало погуглих малко за сравняване по големина, дата и пребродих какви ли не разни безобразни идеи, но нито една не ми се стори подходяща, освен един малук скрипт за проверка на големината на файла, който извеждаше като резултат : “Файла е ОК” или “Размера на файла е превишен!!!”, но като цяло притежаваше идейната структура, която ми трябваше:

#!/bin/sh
SIZE=`ls -ltr /ime/na/target/fail.neshtosi|awk ‘{print $5}’`
if [ $SIZE -ge 700 ] ##say..size exceeds 700
then
echo “FILE SIZE EXCEEDED!!”
else
еcho “FILE SIZE OK”
fi

В течение на времето обаче все възникваше въпроса – “Какво да се използва за база за сравнение?” ?! Ако се използва статичен файл – той винаги ще е различен от таргета и няма да стане. Може да се използва и последния копиран, но как да се прихване името му, при положение, че е динамично генерирано с дата и час, за да се избегне презастъпването на многото файлове които ще се натрупат ако не следиш повече от няколко седмици… Тогава се сетих за един мой познат от София, с който разменяме по някоя дума ако има нужда от помощ. Та той ме насочи в посоката да ползвам “md5 checksum” за сравняване на файла: и един бит в него да се смени чексума вече става различен, което е достатъчна база за сравнение. Даде ми даже малко насоки – примерно какво да правя, за да подхвана скрипта и как се прави проверка на чексума. Първо се прави файл, който да запази получения чексум:

#md5sum /ime/na/fail.neshtosi > /ime/na/checksum_fajla.md5

а после как и да се провери:

#md5sum -c /ime/na/checksum_fajla.md5

като върнатия резултат може да е:

/ime/na/fail.neshtosi: OK

или

/ime/na/fail.neshtosi: FALSE

Именно и това щеше да се окаше основата за самия скрипт. Но имаше един малък проблем: Freebsd не разполагаше с командата md5sum. Неговия аналог се казваше md5 – до тук добре, но нямаше параметъра , който се използваше за сравнение… Трябваше да намеря начин да се докопам до тази команда за FreeBSD, нямаше как да я няма мамкаму… Пропускам всичкото гуглене и направо казвам решението: инсталирането на /usr/ports/coreutils. С това се прибавяха редица команди (basename, cat, chgrp, chmod, chown, chroot, cksum, comm, cp, csplit, cut, date, dd, df, dir, dircolors, dirname, du, echo, env, expand, expr, factor, false, fmt, fold, groups, head, hostid, hostname, id, install, join, kill, link, ln, logname, ls, md5sum, mkdir, mkfifo, mknod, mv, nice, nl, nohup, od, paste, pathchk, pinky, pr, printenv, printf, ptx, pwd, readlink, rm, rmdir, seq, sha1sum, shred, sleep, sort, split, stat, stty, su, sum, sync, tac, tail, tee, test, touch, tr, true, tsort, tty, uname, unexpand, uniq, unlink, uptime, users, vdir, wc, who, whoami, yes) измежду които беше и така желаната от мен gmd5sum. Защо е с “g” отпред ли? Ми ба ли му мамата, оказа се, че всички изброени по-горе са така, можеби за да не се бъркат с оригиналните системни, ма нали работи…

След като имах вече ясна идея се захванах с редактирането на вече изтегления скрипт за проверка на големината. От съвсем общите ми знания по програмиране заключих, че променливата SIZE се определя от изхода на командата

ls -ltr /win/programs/p.txt

а после

awk ‘{print $5}’

извличаше от изхода някаква данна, която която сравняваше на реда

if [ $SIZE -ge 700 ] ##say..size exceeds 700

Но какво подяволите значеше това? Какво значеше {print $5} ? Тогава си спомних, че в C/C++ (пробвах се да го уча преди време) “print” не означава “принтиране на принтер”, а “извеждане на екрана на някакъв резултат”. Значи, от резултата awk взимаше нещо, което беше свързано с 5… Тогава проложих коомандата на конкретен файл – /etc/fstab и получих:

# ls -ltr /etc/fstab
-rw-r–r– 1 root wheel 295 Jan 8 10:44 /etc/fstab
#

С малко броене е лесно да се досетите вече. 5 беше точно колонката, която показваше големината на файла… и тогава дойде крайното осмисляне на моя нов скрипт. Нахвърлях идеята на хартишка и седнах да преработя файла, като получих и крайния резултат:

#!/bin/sh
MD5=`gmd5sum -c /ime/na/fail.md5|awk ‘{print $2}’`
if [ $MD5 = OK ]
then
gmd5sum /ime/na/target/fail.neshtosi > /ime/na/fail.md5
else
cp /ime/na/target/fail.neshtosi /tam/kadeto/shte/pazite/log_`date +’%Y-%m-%d-%H-%M’`.txt && gmd5sum /ime/na/target/fail.neshtosi > /ime/na/fail.md5
fi

Мисля, че можеете да разберете какво точно трябва да прави, но ако някой все пак не разбере – обяснявам с 2 думи: Проверява чексума и ако е ОК – само опреснява чексума. Ако е различна от ОК – копира таргет файла като му прибавя дата и час на копиране и прави нов чексум файл. Всичко работеше перфектно, и следваше да се постави в crontab за да върши работата, за която е предназначен… Което е и втората част на този разказ.

За да не се оплитам в излишни писаници, което не е целта ще спомена само, че в момента когато го поставих за изпълнение в кронтаба – не направи това, което исках от него. Нито правеше, нито ъпдейтваше fail.md5, и на всяка минута копираше и правеше нов fail_data-chas.neshtosi без да се интересува същия лие, променен ли е… Направо побеснях. Как може от команден ред всичко да е наред, а от кронтаба да не ще? Тук пак се размениха няколко реплики с моя познат, като една от насоките беше да се сложат абсолютни пътища към командите. А от гугленето и ровенето по форумите така и никъде нищо не намерих по въпроса. Но какво означаваше това… Взирах се в кода, взерах се с празен поглед докато не ми светна! Какво беше единственото, което правеше скрипта? Копираше, но не правеше/ъпдейтваше fail.md5. А защо? Можеби, защото единствената команда, която ползваше от системата беше “ср” … Значи май наистина не знаеше къде точно е gmd5sum

Развръзката и решението на дилемата последваха много бързо. Разгледах директорията в която бяха инсталирани новите команди (/usr/local/bin) и видях, че има gcp – аналог на нормалното cp. Замених едното с другото и чудо! Скрипта тотално умря от кронтаба. Което беше просто превъзходно, защото от команден ред пак си работеше и доказа теорията за незнание на пътя до командите… Добавих пред сяка команда чистия път и затиктака като добре смазах будилник… Просто превъзходно! Сега вече можех да заспя спокойно…

Но така ли щеше да бъде? Всеки път да пиша безумно много “път” ако пиша друг скрипт? Може би не… Реалната причина за да не работи скрипта от кронтаб се оказа всъщност и адски проста. Просто в реда PATH= в който се казваше къде да си търси командите не съществуваше /usr/local/bin. Когато го добавих, изтрих написаните в скрипта пътища и всичко си заспа бе каквито и да било повече ядове.

Остави коментар

Писането на кирилица е задължително!
Коментари, които не са на кирилица ще бъдат изтрити без предупреждение.
Всеки коментари съдържащи 1 или повече линка, ще бъдат публикувани след одобрение.