Показаны сообщения с ярлыком shell. Показать все сообщения
Показаны сообщения с ярлыком shell. Показать все сообщения

вторник, 13 апреля 2010 г.

Watchdog для контроля состояния линка

Для контроля состояния линка будем пинговать шлюз провайдера. Утилита ping, идущая вместе с FreeBSD и Linux, нам не подходит, т.к. не выдает никаких сообщений при отсутствии ответа проверяемого хоста. То есть нам требуется поведение присущее ping из windows, выводящей в аналогичном случае «timeout». После недолгих поисков утилита oping оказалась идеальным кандидатом.
Собственно шаблон скрипта с подробными комментариями:

#!/bin/sh
# $1 - проверяемый IP-адрес
# $2 - режим работы скрипта

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

# Выходим если не задан проверяемый IP
if [ -z $1 ]; then exit 1; fi

# Проверка режима работы
if [ -z $2 ]
then
# Отслеживание падения линка

# Создаем временный файл для хранения статуса линка
SAVE=$(mktemp)
# Ловим сигнал завершения и удаляем файл статуса
trap 'rm -f $SAVE; exit 0;' INT TERM QUIT
# Пингуем заданный IP-адрес с интервалом в 5 секунд
# и с помощью xargs вызываем самого себя, передавая
# результат пинга и имя файла состояния как параметры
# командной строки.
oping -4 -i 5 $1 | \
sed \
-e '1d' -e '/^--- /d' \
-e '/packets transmitted/d' \
-e '/^$/d' -u | \
xargs -n 1 --delimiter='\n' -I'{}' $0 none check "{}" $SAVE \
>> /var/log/vpn-watchdog.log
# Удаляем файл статуса
rm -f $SAVE
elif [ $2 = check -a ! -z $4 ]
then
# Watchdog
# $3 - результат пинга
# $4 - имя файла состояния

# Получение состояния линка
STATUS=$(echo $3 | grep -oE '(ms|timeout)$')
# Сравнение
if [ ! -z "$STATUS" ]
then
# Определение состояния линка и исключение
# ложного срабатывания
if [ "$STATUS" = timeout -a "$(cat $4)" != $STATUS ]
then
# Реакция на событие
echo -n "$(date +'%Y-%m-%d %H-%M-%S') TIMEOUT - Restarting... "
# Далее идет несколько строк команд
# ...
echo " done!"
fi
# Сохраняем текущее состояние для последующей проверки
echo -n $STATUS > $4
fi
fi
Достоинства данного подхода: не требуется вызывать из крона по расписанию, мониторинг идет непрерывно и, если требуется, время реакции на событие может составить одну-две секунды.

суббота, 14 ноября 2009 г.

Запрет запуска второй копии скрипта

Пример кода с пояснениями

#!/bin/sh

pid_file=/tmp/script-name.pid

#########################
# Создаем файл с правом только на чтение
# и вписываем туда идентификатор процесса (pid)
umask 333
(echo $$ > "$pid_file") 2>/dev/null

#########################
# Если процесс уже запущен, то попытка записи pid
# в файл будет завершена с ошибкой
if [ $? -ne 0 ]
then
umask 22

echo "Already started :("
exit 1
fi

umask 22
#########################
# Что-то долго делаем...
#########################

#########################
# Удаляем файл с pid
rm -f "$pid_file"

суббота, 14 марта 2009 г.

xargs: многопоточная обработка

Благодаря посту Владимира Бредникова узнал, что xargs благодаря двум ключам помогает организовать многопоточную обработку файлов:

-n X
Ограничивает количество передаваемых вашей программе аргументов. По умолчанию xargs передаёт программе довольно большое число аргументов, поэтому для обработки одного файла за один раз нужно указывать эту опцию.
-P X
Устанавливает количество одновременно выполняемых процессов. По умолчанию xargs запускает только один процесс, но в нашем случае нужно увеличить это число до количества процессоров.
Например, в паре с утилитой find можно в несколько потоков обработать множество картинок, размер которых больше одного мегабайта
$ find ~/Photos -iname '*.jpg' -and -size +1M -print0 | \
xargs -0 -n 1 -P 2 -I'{}' convert '{}' -resize '800x600>' -quality 100 '{}'
P.S. Надо почаще заглядывать в man :)

четверг, 25 декабря 2008 г.

Узнать SOA обратной зоны

Сегодня спросили как узнать интервал между обновлениями обратных зон провайдеров. Ответом послужила такая конструкция

host -t soa `whois aa.bb.cc.dd | \
grep -Ei "(inetnum|netrange):" | \
tail -n 1 | sed -E 's/^.+:[ ]*//' | \
xargs ipcount | grep -oE '[0-9]+(\.[0-9]+)*/' | \
sed -E 's/\///' | head -n 1 | \
awk -F . '{ print $4 "." $3 "." $2 "." $1 }' | \
sed -E 's/^\.//;s/$/.in-addr.arpa/'`
где aa.bb.cc.dd - любой ip-адрес интересующего провайдера.

вторник, 2 декабря 2008 г.

Генерирование паролей. Акт второй.

#!/bin/sh
dd if=/dev/urandom count=6 bs=1 2>/dev/null | uuencode -m - | sed -n 2p

среда, 18 июня 2008 г.

Массовое переименование файлов с помощью утилиты find

Иногда бывает жизненно необходимо переименовать кучу файлов. Например заменить пробелы в названии файлов и директорий на нижний знак подчеркивания.
Сохраняем приведенный ниже скрипт в файл с именем mass-replace.sh

#!/bin/sh

# Определяем глубину вложенности директорий
depth=$((`find "$1" -type d -print | \
sed -E 's/[^\/]+//g' | \
sort | tail -n 1 | \
wc -c`+1));
# Макрос, переименовывающий файлы и директории
replacer='new="`dirname "{}"`/`basename "{}" | sed "s/ /_/g"`"; if [ "$new" != "{}" ]; then mv "{}" "$new"; fi;';
# Обходим все уровни вложенности
while [ $depth -ge 0 ];
do
# Находим и заменяем
find "$1" -depth $depth -and -name '* *' -print -exec sh -c "$replacer" \;
# Меняем уровень вложенности
depth=$(($depth-1));
done;
Сделаем файл исполняемым
$ chmod +x mass-replace.sh
В качестве аргумента скрипту передается путь до обрабатываемой директории
$ ./mass-replace.sh ~/Warez/Music

понедельник, 16 июня 2008 г.

Делаем EncFS более дружелюбным к пользователю (Ubuntu)

  1. Устанавливаем EncFS
    $ sudo aptitude install encfs
  2. Добавляем текущего пользователя в группу fuse, если он еще не в этой группе
    $ sudo adduser $USERNAME fuse
  3. Создаем директории
    $ mkdir ~/.Encrypted
    $ mkdir ~/"Secret Documents"
    В «~/.Encrypted» будут храниться зашифрованные данные, а в «~/Secret Documents» - монтироваться EncFS. Не забывайте что EncFS требует абсолютные пути, т.е. они должны начинаться с «/».
  4. Создаем и монтируем шифрованное хранилище
    $ encfs ~/.Encrypted ~/"Secret Documents"
    Будет задано несколько вопросов с вариантами ответов и подсказками.
  5. Размонтируем его
    $ fusermount -u ~/"Secret Documents"
  6. Создадим два скрипта, призванные упростить работу с созданным хранилищем.
    • Скрипт №1 будет выполнять роль внешней программы авторизации, вызываемой EncFS.
      Файл: ~/bin/req-pass.sh
      #!/bin/sh
      /usr/bin/zenity --entry --title=Пароль --text='Введите пароль' --hide-text
    • Скрипт №2 упрощает монтирование и размонтирование шифрованного хранилища.
      У скрипта два параметра
      mount
      Монтирует зашифрованное хранилище
      umount
      Размонтирует зашифрованное хранилище
      Файл: ~/bin/encfs-user.sh
      #!/bin/sh

      if [ ! -z "$HOME" ];
      then
      ENC=$HOME/.Encrypt;
      DIR="$HOME/Secret Documents";
      MOUNT="`/bin/grep -E '^encfs[[:space:]]+'$DIR'\>' /proc/mounts`";

      case "$1" in
      mount)
      if [ -z "$MOUNT" ];
      then
      # Назначаем скрипт №1 внешней программой авторизации для encfs
      /usr/bin/encfs --extpass=$HOME/bin/req-pass.sh $ENC $DIR;
      if [ $? -eq 0 ];
      then
      /usr/bin/zenity --info --title=Сообщение --text='Том с документами успешно подключен';
      else
      /usr/bin/zenity --warning --title=Предупреждение --text='Возникла ошибка при попытке подключения тома с документами';
      fi;
      else
      /usr/bin/zenity --warning --title=Предупреждение --text='Том с документами уже подключен'
      fi;
      ;;
      umount)
      if [ ! -z "$MOUNT" ];
      then
      /usr/bin/zenity --question --title=Вопрос --text='Вы действительно хотите отключить том с документами?'
      if [ $? -eq 0 ];
      then
      /bin/fusermount -u $DIR;
      if [ $? -eq 0 ];
      then
      /usr/bin/zenity --info --title=Сообщение --text='Том с документами успешно отключен';
      else
      /usr/bin/zenity --warning --title=Предупреждение --text='Возникла ошибка при попытке отключения тома с документами';
      fi;
      else
      /usr/bin/zenity --info --title=Сообщение --text='Том с документами не был отключен';
      fi;
      else
      /usr/bin/zenity --warning --title=Предупреждение --text='Том с документами уже отключен'
      fi;
      ;;
      esac;
      fi;
  7. Проверим работу скрипта в консоли.
    Смонтируем хранилище
    $ ~/bin/encfs-user.sh mount
    Скрипт запросит пароль и в всплывающем окне выведет результат работы скрипта.
    Теперь размонтируем
    $ ~/bin/encfs-user.sh umount
  8. Осталось создать ярлыки в оконном менеджере для запуска скрипта. :)

пятница, 18 апреля 2008 г.

К чему приводит забывчивость

Сегодня с одного старого сервера снес оболочку bash вместе с несколькими ненужными программами и ребутнул систему. После удаленного входа в консоль cюрпризом стало невозможность поднять свои привилегии до суперпользователя командой su из-за отсутствия назначенной ему оболочки bash.
Выходом стал стал ключ -m команды su

su -m
Выдержка из man su: «-m оставляет переменные окружения пользователя нетронутыми. Запускается назначенная исходному пользователю оболочка вместо оболочки конечного пользователя и не меняется текущая директория.»

суббота, 15 марта 2008 г.

Украшаем командную строку в csh/tcsh

Вид командной строки в csh/tcsh задается несколькими переменными окружения. Главная из них - prompt. По умолчанию приглашение командной строки имеет вид

%
что нас совершенно не устраивает. Введем команду
set prompt="%m%# "
где %m - имя компьютера, %# - символ > (или первый символ переменной promptchars) для обычных пользователей или символ # (или второй символ переменной promptchars) для суперпользователя.
Увидим, что приглашение изменилось
machine> 
Мы перестаем путаться в в удаленных сессиях. Далее добавим имя текущего пользователя (%n) и полное имя директории, где мы сидим в данный момент (%/)
set prompt="%n@%m [%/]%# "
Вид меняется на
user@machine [/usr/local/etc]> 
Наше приглашение стало более информативной. Но полный путь занимает слишком много места. Меняем %/ на %c, урезающий отображаемый путь до имени текущей директории
set prompt="%n@%m [%c]%# "
и у нас получилось
user@machine [etc]> 
что уже выглядит лаконичнее. Добавим текущее время (счастливые могут пропустить :)
set prompt="%T %n@%m [%c]%# "
и вуаля
23:01 user@machine [etc]> 
По правде говоря, лично меня символ > в конце приглашения раздражает. Для смены символа используем переменную promptchars
set promptchars="$#"
Первый символ подставляется вместо %# если вы обычный пользователь, а второй - если вы суперпользователь.
Теперь записываем полученный результат в ~/.tcshrc или в /etc/csh.cshrc.

Ниже приведен список допустимых подстановок (подробности в man csh):
%/
Текущая рабочая директория.
%~
Текущая рабочая директория, но домашная директория текущего пользователя представлено тильдой ~ и домашние директории остальных пользователей представлены как ~user. Подстановка ~user действует только в случае если оболочка (shell) уже использует ~user в имени пути в текущей сессии.
%c[[0]n], %.[[0]n]
Отслеживает конечный компонент пути к текущей рабочей директории или n конечных компонентов, при заданном n. Если n начинается с 0 количество пропущенных компонентов предваряет конечные в формате /<skipped>trailing. Если установлена переменная оболочки ellipsis, пропущенные компоненты будут представлены как ...trailing. Подстановка ~ действует аналогично %~, но будет игнорироваться при количестве конечных компонентов больше одного.
%C
Аналогично %c, но без подстановок ~.
%h, %!, !
Номер события в текущей истории.
%M
Полное имя машины.
%m
Сокращенное имя машины. Отображается часть до первой точки.
%S (%s)
Включить (отключить) стандартный режим.
%B (%b)
Включить (отключить) режим жирного шрифта.
%U (%u)
Включить (отключить) режим подчеркивания.
%t, %@
Время в 12-часовом (AM/PM) формате.
%T
Аналогично %t, но в 24-часовом формате (зависит от переменной ampm оболочки).
%p
Точное время суток в 12-часовом (AM/PM) формате, с секундами.
%P
Аналогично %p, но в 24-часовом формате (зависит от переменной ampm оболочки).
\c
c будет распознан как код символа.
%%
Символ %.
%n
Имя пользователя.
%j
Количество запущенных в оболочке работ (jobs).
%d
День недели в текстовом формате.
%D
День недели в числовом формате.
%w
Месяц в текстовом формате.
%W
Месяц в числовом формате.
%y
Год в двухзначном формате.
%Y
Год в четырехзначном формате.
%l
tty оболочки.
%L
Очищает от конца приглашения до конца экрана или строки.
%$
Подставляет значение переменной оболочки или окружения с именем, заданным сразу после $ (например %$PATH).
%#
> (или первый символ из переменной оболочки promptchars) для обычных пользователей и # (или второй символ из promptchars).
%{string%}
Включает строку как управляющая escape последовательность. Может использоваться для изменения атрибутов терминала (например для раскраски приглашения) и может не воздействовать на положение курсора. Не может быть последней последовательностью в приглашении.
%?
Возвращает код ошибки команды, запущенной непосредственно перед приглашением.