Поиск по этому блогу

понедельник, 28 мая 2012 г.

Bash. Скопировать последний файл с удаленного ресурса

Задача. Скопировать с удаленного ресурса самый старый файл. В исходной директории может лежать сегодняшний файл, может вчерашний, а может вообще не лежать...
Полезно в тех случаях, когда резервное копирование идет ночью, т.е. backup+копирование на резервный сервер может пройти до 00.00, а может не успеть и точную дату нашего backup файла мы не знаем.
bash скрипт. for, if, find...


#!/bin/bash 
1. Монтируем удаленный ресурс
# размонтировать
umount /mnt/mnt_bckp/
# примонтировать
mount -o domain=Домен,username=Имя пользователя,password=Пароль //IP адрес/папка /mnt/mnt_bkp/

2. Определяем переменные
SOURCE_DIR=/mnt/mnt_bkp/backup/*.tgz  #директория откуда копируем с маской
DEST_DIR=/mnt/backup/*.tgz                       # директория куда копируем с 

                                                                                  # указанием   маски 
BACKUP_DIR="/mnt/backup/"                      # директория куда копируем
ARH_FILE=""

let im_copy=0 # признак того, что нашли нужный нам файл (если ресурс не один)
                   # или дополнительная проверка, что такой файл у нас уже лежит

3. Копируем. Для копирования используем команду find с опцией -mtime, нам нужны файлы созданные (измененные) за последние nn дней. Также для вывода можно использовать команду ls, которая вернет список файлов (использовать с опцией сортировки по дате создания).
Заводим еще одну глобальную переменную
dcopy=2  # копии за последние два дня
# опции команды find
# -mtime -5 - созданные или изменённые за последние 5 дней
# -atime -10 - время последнего обращения более 10 дней

###### Работаем с резервом ########
# имена файлов тоже содержат дату (поэтому не заморачивалась с сортировкой)
for i in $(find $SOURCE_DIR -type f -mtime -$dcopy);
do
  ARH_FILE=$i; #последний файл
done
echo "Последний архивный файл " $ARH_FILE
echo date
#  копируем  можно с доп.условием 

if  [[ ( "$ARH_FILE" != "" )  && ( $im_copy==0 ) ]] ; then
  echo "Файл есть. Начинаю копирование c сервера... " $ARH_FILE 
  # копируем с шары
  scp $ARH_FILE $BACKUP_DIR
  let im_copy=1
  else
  echo "Нет новых файлов за последние " $dcopy " дня."
  #exit
fi
echo $(date +%c)

Точно так же можно работать с удаленным сервером по ssh (если этот сервер вам доверяет)
SSH_HOST=XX.XX.XX.XX # IP адрес удаленного сервера
SSH_SOURCE_DIR=/mnt/backup/*.tgz
SSH_ARH_FILE=""

###### Работаем с сервером по SSH ########
# получить последний архив c рабочего сервера
for i in $(ssh $SSH_HOST "find $SSH_SOURCE_DIR -type f -mtime -$dcopy");
do
  SSH_ARH_FILE=$i; #последний файл
done
echo "На сервере " $SSH_HOST " последний архивный файл  " $SSH_ARH_FILE

if [ "$SSH_ARH_FILE" != "" ]; then
 echo "Файл есть. Начинаю копирование c " $SSH_HOST  " сервера... " $SSH_ARH_FILE
 scp  root@$SSH_HOST:$SSH_ARH_FILE $BACKUP_DIR #copy from server ssh
 let im_copy=1
 else
 echo "Нет новых файлов за последние " $dcopy " дня"
  #exit
fi

4. Разархивировать полученный файл
tar -xzf $ARH_FILE
echo $(date +%c)

Немного мат.части.
find - поиск файла по заданным условиям
Некоторые ключи
-name — искать по имени файла, при использовании подстановочных образцов параметр заключается в кавычки.
-type — тип искомого: f=файл, d=каталог, l=ссылка (link).
-user, -group — владелец: имя пользователя или UID, имя группы или GID
-atime — время последнего обращения к файлу.
-ctime — время последнего изменения владельца или прав доступа к файлу.
-mtime — время последнего изменения файла.
-newer другой_файл — искать файлы созданные позже, чем другой_файл.
-delete — удалять найденные файлы.
-exec command {} \; — выполняет над найденным файлом указанную команду; обратите внимание на синтаксис.
-ok — перед выполнением команды указанной в -exec, выдаёт запрос.
-depth — начинать поиск с самых глубоких уровней вложенности, а не с корня каталога.
-prune — используется, когда вы хотите исключить из поиска определённые каталоги.


Работа с функциями
function goaway {
   exit
}
#вызов
goaway

Функция с параметрами 
function param {
  echo $1
 }

#Вызываем и передаем один параметр Hello
Param Hello



Синтаксис цикла For 
for i in $( ls ); do
  echo item: $i
done

 
Синтаксис цикла while:
COUNTER=0 
while [ $COUNTER -lt 10 ]; do 
echo The counter is $COUNTER 
 let COUNTER=COUNTER+1 
done 

Синтаксис if...then...else 
if [ "foo" = "foo" ]; then
 echo "это ИСТИНА"
else
 echo "это ЛОЖЬ"
fi


AND                  &&                  -a
OR                     ||                    -o

"опции -a и -o соединяют выражения как логическое И и ИЛИ соответственно"
Пример [ ! \( "a" = "$HOME" -o 3 -lt 4 \) ]


Сравнения
<               -lt               less then
>               -gt              greater then 
<=            -le               less or equal
>=            -ge              greate or equal
==            -eq              equal
=                                                   равно
!=             -ne              not equal 


Оператор -z проверяет, не пуста ли строка
if [ $ARH_FILE -z ]; then
 echo "Пустая строка " $ARH_FILE
else
 echo "Не пустая строка " $ARH_FILE 
fi


Экран \  для символов <, >, (, )
Важно!!! Так как операторы < и > используются для перенаправления вывода, то в скрипте их надо экранировать  \< или \>.


[ $im_copy \< 1 ] 
Также экранировать следует круглые скобки, вместо () пишем \(\)


Использование [[ 
Сложные условия без экрана, с использованием двойных скобок [[, каждое условие отделяется круглыми скобками ()
 [[ ( "$ARH_FILE" != "" )  && ( $im_copy==0 ) ]]

let
для вычисления выражений 1+1*2... используется функция let
 let COUNTER=COUNTER+1 
 let res=(15+18)*100 


Почитать
http://linuxland.itam.nsc.ru/howto/Bash-Prog-Intro.html -Из серии must-read

http://www.ibm.com/developerworks/ru/library/l-bash-test/ - от IBM

http://www.opennet.ru/docs/RUS/bash_scripting_guide/x6646.html - OpenNet

Просто линуксовый сайт
http://rus-linux.net - rus-linux.net