3 заметки с тегом

Скрипты

Как рулить инсталляциями server core

2 декабря 2013, 17:18

Нашёл мега-полезную ссылку про то, как можно жить с server core. Прямо так и называется: «Сore 2012: Руководство по выживанию». Много всяких полезных штук — как настраивать сетку, как просматривать логи и так далее, через powershell.

Удалённое выполнение команд по ssh

20 ноября 2013, 16:57

В свете полученных знаний из ссылок в предыдущем посте решил начать жить по-новому. А именно — бэкапные файлы с фри на фрю складывать не по SMB или FTP, как раньше, а по scp или ssh. Подумал, и решил, что удобнее будет через ssh — туда загоняется поток через pipe, а на удалённой стороне из pipe складывается в локальнный (для удалённого сервера-хранилища бэкапов) файл. Проверил даже скорость — в конкретной сети гиговый файл через SMB скопировался за  1 минуту 48 секунд, а то же самое, но через ssh — за 1 минуту 35 секунд. Профит налицо :-)

Запустил mcedit и начал ваять. Со скриптом бэкапа системы проблем не возникло:

# cat system_backup.sh
#!/bin/sh
backup_dir="/home/backup_operator/backups/os/buhserver-ttr"
keyfile="/home/gateway/service/keyfile.ppk"
username="backup_operator@backup-ttr"

DATE=`date +%Y.%m.%d`

dump -0 -L -u -C 32 -f — / | gzip -5 | ssh -q -i ${keyfile} ${username} "cat > ${backup_dir}/${DATE}_root.dump.gz"
dump -0 -L -u -C 32 -f — /usr | gzip -5 | ssh -q -i ${keyfile} ${username} "cat > ${backup_dir}/${DATE}_usr.dump.gz"
dump -0 -L -u -C 32 -f — /var | gzip -5 | ssh -q -i ${keyfile} ${username} "cat > ${backup_dir}/${DATE}_var.dump.gz"
dump -0 -L -u -C 32 -f — /home | gzip -5 | ssh -q -i ${keyfile} ${username} "cat > ${backup_dir}/${DATE}_home.dump."

keyfile — это private key для авторизации на удалённом сервере, backup_operator — имя пользователя на том сервере, а backup-ttr — имя самого сервера, где у нас бэкапы хранятся. Получается следующее — dump дампит раздел в stdout, откуда это перегоняется в gzip через pipe, откуда перегоняется вот в эту конструкцию:

ssh -q -i ${keyfile} ${username} "cat > ${backup_dir}/${DATE}_root.dump.gz"

Т. е. мы подключаемся к серверу backup-ttr, и выполняем там команду "cat > {backup_dir}/${DATE}_root.dump.gz". Которая читает из stdin сжатый gzip'ом и прокинутый по сети поток и сохраняет его в файл {backup_dir}/${DATE}_root.dump.gz.

В общем, тут всё просто. А вот с бэкапом почты пришлось повозиться. Было принято решение не просто каждый день сваливать полный бэкап почтовой базы и удалять старые копии, а сделать инкрементный бэкап. А для этого нужно производить определённые манипуляции на стороне хранилища бэкапов. Можно, конечно, сделать второй скрипт, и запускать его по крону на стороне хранилища. Но «Шурик, это же не наш метод!». Это придётся контролировать две точки выполнения одной операции — бэкапа почты, так как задействованы будут два скрипта, два крона, два компа и т. д.

Суть задачи такова. Допустим, у нас в день 1 выполняется полный бэкап почтовой базы. В день 2 — только то, что изменилось или добавилось со времени исполнения 1-го бэкапа, отработавшего в день 1. В день 3 — только изменения с момента бэкапа в день 2, и так далее до конца недели. Допустим, за первую неделю у нас сделано 7 архивов, с именами, соответственно, mail1.tgz, mail2.tgz, ... mail7.tgz. Где mail1.tgz — это полная копия базы, а остальные — дельты изменений. Неделя закончилась, надо как-то сделать ротацию бэкапов. То есть, куда-то деть эти 7 архивов. Можно их тупо удалить. Но как-то хочется, чтобы у нас хотя бы двухнедельная история бэкапов хранилась. Самое простое — эти архивы переименовать. Например, по схеме mail1.tgz.bak, mail2.tgz.bak и так далее. Тут-то и началось самое интересное.

Сначала решил сделать как-нибудь так:

for i in `ssh -q -i ${keyfile} ${username} "ls ${backup_dir}/*.gz"`
do
ssh -q -i ${keyfile} ${username} "mv ${i} ${i}.bak"
done

Но это получается 1 вызов ssh для получения списка файлов, и потом ещё в цикле 7 раз запускается ssh, чтобы переименовать каждый отдельный файл. Касичок кагбэ, неоптимальненко.

Камрады в интернете посоветовали сделать как-нибудь так:

ssh -q user@remoteserver 'ls -f /path/*.tgz | while read f; do "$"» };done'

Я попробовал, не прокатило. Полез искать точный синтаксис однострочного оформления циклов в shell. Нашёл несколько примеров, подставил, но ни один не прокатил. Я так понял, что приведённые примеры — в основном для линуксового bash, а у меня фрёвая /bin/sh, поэтому и не прокатывает. Потом нашёл обрывочные сведения, что циклы типа for, foreach, while — «is not single-line friendly». Но коллективный разум мне сурово возразил, что я не прав.

Копаясь дальше, я обнаружил, что реально, однострочные конструкции типа

ls | while read f;do echo ${f};done

работают, будучи запущены в /bin/sh и локально. Но не работают удалённо. Потом до меня дошло, что локально-то я запустил /bin/sh, и в ней пускаю все эти конструкции. Но по дефолту у пользователя backup_operator оболочка прописана /bin/csh, и синтаксис там может отличаться.

Не вопрос, топаем на удалённый сервер и делаем там:

pw usermod backup_operator -s /bin/sh

Меняем, иными словами, ему оболочку на sh вместо csh. После этого конструкция

ssh -i keyfile.ppk backup_operator@backup-ttr "ls /home/ | while read f; do echo ${f}; done;"

просто обязана была заработать. Но не заработала... А написала, что f: Undefined variable.

В процессе дальнейшего общения с коллективным разумом выяснилось следующее:

The shell will expand variables in double-quotes, but not in single-quotes.

что если команду для удалённого исполнения заключать в двойные кавычки, то оболочка подставляет значение переменной вместо имени переменной. А в этой ситуации нужно, чтобы имя переменной передавалось как есть на дальнюю сторону, и значение вычислялось и использовалось уже там. Поэтому эту команду нужно заключать в ОДИНАРНЫЕ кавычки. То есть, вот так:

ssh -i keyfile.ppk backup_operator@backup-ttr 'ls /home/ | while read f; do echo ${f}; done;'

Но есть и другой путь — просто ставить backslash перед символом переменной. То есть, можно сделать вот так:

ssh -i keyfile.ppk backup_operator@backup-ttr "ls /home/ | while read f; do echo \${f}; done;'

Мне так пришлось сделать, потому что по итогу потребовалось, чтобы в одной команде были и локальные и удалённые переменные. Т. е. финальная рабочая конструкция выглядит вот так:

ssh -i keyfile.ppk backup_operator@backup-ttr "cd ${backup_dir}; ls ./ | while read f; do mv \${f} \${f}.bak; done"

Сеть по bluetooth с помощью btpand

7 января 2010, 6:30
В упомянутом уже ThinkPad 600X сетки не было. Точнее, сетевая PCMCIA была, но товарищ не нашёл проводочек, который подключается одним концом к сетевухе, а другим — к коннектору RJ-45. Поскольку CDROM в ноуте старый и довольно глючный, пришлось что-то придумывать. Вариант был ровно один — поскольку USB-порт там один есть, остаётся только Bluetooth, ну, или всякие USB-сетевые, проводные или WiFi. Покупать для этого ноута USB-сетевую меня заломало — не такая уж важная птица, а адаптеров голобуго зуба у меня навалом.

Под фрёй 7.2 я настроил сетку с помощью LAN over PPP, настроил rfcomm_pppd и полетели. Запускалось оно несколько криво — из rc.local, и требовало ещё не менее трёхсекундной паузы для прописывания маршрутизации, но в общем, работало.

После перехода на 8-ую фрю начали наблюдаться проблемы — примерно через час прослушивания интернет-радио голубозубый линк отваливался, и не поднимался до тех пор, пока я не выдерну и не вставлю обратно bluetooth-адаптер на серверной стороне, с последующим перезапуском rfcomm_pppd с обоих сторон. Разбираться с этим бесполезно — никаких сообщений в логах нет, ничего не происходит, сервер по голубому зубу при обзоре устройств виден, и линк поднимается, но трафика по нему не идёт. Я такое уже видел, правда, с КПК, но побороть так и не смог. Решил перейти на btpand, раз уж он появился — это софтина, портированная во фрю из NetBSD (не прошло и 8 лет, как фря наконец-то начала вкуривать BT PAN, ггг).

Потестил btpand при ручном запуске. На сервере запускаем:

# ifconfig tap0 create
# btpand -d ubt0 -i tap0 -s NAP
# ifconfig tap0 192.168.2.1 netmask 255.255.255.0


На клиенте:

# ifconfig tap0 create
# btpand -d ubt0 -i tap0 -s NAP -a 00:18:e7:1a:24:9b
# ifconfig tap0 192.168.2.2 netmask 255.255.255.0


Ну, тут всё понятно — создаём интерфейс tap0, через который будет работать голубозубый линк, поднимаем сам линк, и затем конфигурируем интерфейсы — прописываем IP-адрес, на котором оно будет работать.

Проверяем наличие присутствия связи:

notebook# ping -c 4 192.168.2.1
PING 192.168.2.1 (192.168.2.1): 56 data bytes
64 bytes from 192.168.2.1: icmp_seq=0 ttl=64 time=22.778 ms
64 bytes from 192.168.2.1: icmp_seq=1 ttl=64 time=18.257 ms
64 bytes from 192.168.2.1: icmp_seq=2 ttl=64 time=39.277 ms
64 bytes from 192.168.2.1: icmp_seq=3 ttl=64 time=18.313 ms


Типа, работает, что ли? Афигеть... :-)

Ну чо, подадим на ноут интернет теперь — пропишем nameserver на ноуте в /etc/resolv.conf, а серверный голубозубый IP-шник в качестве шлюза и перенастроим правила файрвола, чтобы он ноут пускал в интернет:

# route add default 192.168.2.1

Проверяем:

notebook# ping ya.ru
PING ya.ru (77.88.21.8): 56 data bytes
64 bytes from 77.88.21.8: icmp_seq=0 ttl=57 time=85.294 ms
64 bytes from 77.88.21.8: icmp_seq=1 ttl=57 time=74.188 ms
64 bytes from 77.88.21.8: icmp_seq=2 ttl=57 time=217.258 ms


Круто! Грузим KDE и пытаемся открыть http://shoutcast.com Получаем облом. Сайт грузится, но не до конца, и запустить прослушивание чего-нибудь оттуда невозможно — даже плейлист не качается. Интуиция подсказывает, что раз что-то работает, а что-то нет при живом линке, то это проблемы с MTU. Начинаю гонять пинги разного размера, определяя, какой максимальный размер пинга пройдёт. Оказалось, что пинги размером 641 байт проходят, и больше — хрен. А MTU на интерфейсах tap0 выставился дефолтный в 1500. Мораль — надо копать. Накопал только вот это. Симптомы там у товарища в точности как у меня — MTU в районе 600 байт, иначе хеликоптер нихт. Но потом он перезагрузил телефон, к которому подключал комп по BT, и чудесным образом всё заработало с правильным MTU 1500. Но у меня такая маза не прокатила — сразу после перезагрузки оно вроде заработал с MTU 1500, но через пару минут всё отвалилось, в том числе ssh. Так что на текущий момент MTU 640 является обязательным.

Ну, теперь надо как-то организовать, чтобы вся эта хрень запускалась при старте системы. Условия у меня довольно специфические — в сервере BT-адаптер торчит всегда, а в ноуте — практически всегда, потому что я его в качестве плейера радива из интернета использую. Значит, надо либо в rc.local вписывать, что проще, но криво, либо написать rc-скрипт. Поскольку лёгких путей мы не ищем, то я выбрал второй вариант.

Скрипт будет принимать такие параметры:

btpand_enable — разрешено или нет запускать btpand (по умолчанию NO);
btpand_device — девайс bluetooth, с которого работаем;
btpand_interface — интерфейс, на котором работать (по умолчанию tap0);
**btpand_service
 — сервис, который мы используем (GN, NAP, PANU, по умолчанию NAP);
btpand_linkup — скрипт, выполняемый при установлении соединения;
btpand_linkdown — скрипт, выполняемый при разрыве соединения;
btpand_server — MAC-адрес сервера, к которому будем подключаться, если работаем как клиент;
btpand_iface_addr — это параметр для конфигурирования интерфейса — прописывания IP-адреса и пр. Синтаксис такой же, как и у параметров rc.conf типа «ifconfig_rl0» — эта строка просто скармливается ifconfig'у.

Скрипты linkup/linkdown мне нужны, чтобы прописывать шлюз по умолчанию. В других задачах, возможно, потребуется ещё что-нибудь делать. Это необязательный параметр. Как, в общем, и многие другие. Обязательным будет являеться только btpand_enable и btpand_iface_addr для обоих компов, и btpand_server — только при запуске на клиенте. Остальное либо не обязательно, либо конфигурируется по умолчанию, как параметр btpand_interface.

Собственно, родился такой несложный скрипт:
#!/bin/sh

# PROVIDE: btpand
# REQUIRE: DAEMON sdpd
# BEFORE: LOGIN
# KEYWORD: nojail

. /etc/rc.subr

name=«btpand»
rcvar=`set_rcvar`
command=«/usr/sbin/btpand»

load_rc_config $name

eval «${rcvar}=\${${rcvar}:-'NO'}»

btpand_interface=${btpand_interface:-«tap0»}
btpand_device=${btpand_device:-«ubt0hci»}
btpand_service=${btpand_service:-«NAP»}
btpand_server=${btpand_server:-«no»}
btpand_iface_addr=${btpand_iface_addr:-«dhcp»}
btpand_linkup=${btpand_linkup:-«no»}
btpand_linkdown=${btpand_linkdown:-«no»}

start_cmd=«btpand_start»
stop_precmd=«btpand_stopprecmd»
stop_postcmd=«/sbin/ifconfig ${btpand_interface} destroy»

btpand_start()
{
if [ ! -e /dev/${btpand_interface} ]
then /sbin/ifconfig ${btpand_interface} create
fi
/sbin/ifconfig ${btpand_interface} mtu 640
if [ «dhcp» = «${btpand_iface_addr}» ]
then /sbin/dhclient ${btpand_interface}
else /sbin/ifconfig ${btpand_interface} ${btpand_iface_addr}
fi
if [ «no» = «${btpand_server}» ]
then $command -d ${btpand_device} -s ${btpand_service} -i ${btpand_interface} > /dev/null 2>&1
else $command -d ${btpand_device} -s ${btpand_service} -i ${btpand_interface} \
-a ${btpand_server} > /dev/null 2>&1
fi
if [ ! «no» = «$btpand_linkup» ]
then sh ${btpand_linkup}
fi
}

btpand_stopprecmd()
{
if [ ! «no» = «$btpand_linkdown» ]
then sh ${btpand_linkdown}
fi
}

run_rc_command «$1»

Осталось это всё запустить. На сервере говорим:

# echo btpand_enable=«YES» >> /etc/rc.conf
# echo btpand_iface_addr=«192.168.2.1 netmask 255.255.255.0» >> /etc/rc.conf


На клиенте прописываем:

# echo btpand_enable=«YES» >> /etc/rc.conf
# echo btpand_iface_addr=«192.168.2.2 netmask 255.255.255.0» >> /etc/rc.conf
# echo btpand_server=«00:18:e7:1a:24:9b» >> /etc/rc.conf
# echo btpand_linkup=«/home/vasya/bt_linkup» >> /etc/rc.conf


И создаём файл /home/vasya/bt_linkup с таким содержанием:

#!/bin/sh
route add default 192.168.2.1


Перезапускаем сервер, перезапускаем ноут — судя по лампочкам на BT-адаптере, линк поднялся. Проверяем:

notebook# ping ya.ru
PING ya.ru (77.88.21.8): 56 data bytes
64 bytes from 77.88.21.8: icmp_seq=0 ttl=57 time=66.597 ms
64 bytes from 77.88.21.8: icmp_seq=1 ttl=57 time=93.634 ms
64 bytes from 77.88.21.8: icmp_seq=2 ttl=57 time=49.616 ms


Точно, поднялся. Ну, значит, топаем в KDE и запускаем чего-нибудь с Shoutcast'a бодрое на прослушивание! :-)

Область применения

Вообще-то, это можно юзать не только для связи двух компов с фрёй между собой. BT-сервис «LAN over PPP» — довольно специфический, виндовые драйвера, которые я пробовал, его просто не видят, так что когда я захотел ноут с виндой, не имеющий WiFi адаптера, но имеющий BT, подключить в интернет через LAN over PPP, настроенный на серваке, то круто обломался.

Да и мобильные устройства далеко не все умеют LAN over PPP. Например, у меня был КПК HP hx2190 — он мог подключаться к такому сервису на сервере, и ходить через него в интернет и прослушивать музыку. А вот коммуникатор HTC Touch уже к серваку подключиться не мог — его BT-стек не поддерживает этот сервис. Touch, конечно, может работать по WiFi, который у меня всё равно в квартире есть, но WiFi гораздо более прожорлив в смысле батарейки, так что BT сильно предпочтительней, тем более что разницы в скорости между BT и WiFi линках на коммуникаторе практически незаметно.

К тому же, в коммуникаторе нет сервиса Dial-up internet, он интернет умеет раздавать только через PAN. При наличии btpand можно спокойно подключить 8-ую фрю к коммуникатору и заюзать интернет через EDGE.
Bluetooth   FreeBSD   Скрипты