Archive

Posts Tagged ‘tips’

Магия в zsh

November 4th, 2008 1 comment

Захотелось мне в этот чудесный выходной понедельник поагитировать за свой любимый шелл. Чем, кстати, вообще может похвастаться какой-либо шелл, имея в конкурентах такого монстра, как bash? Ведь в bash есть все, что может только пожелать обычный пользователь. А, собственно, и нечем. Поэтому разработчикам zsh пришлось пойти на хитрость и добавить в свое детище некоторое количество магии :)

Большая ее порция досталась подсистеме автодополнения. Вот таким можно сделать дополнение имен файлов:
zsh menu completion
(выбрать нужный вариант можно табом по старинке, курсорными клавишами или стандартными emacs-хоткеями)

А вот так – дополнение опций:

Еще одна моя любимая магическая штуковина в автодополнении выглядит так: допустим, нужно подправить файл /usr/local/etc/rc.d/mysql. Пользователь bash бы ввел такую команду:
vim /usr/l[TAB]/e[TAB]/r[TAB]/m[TAB]
В zsh все несколько проще, а именно:
vim /u/l/e/r/m[TAB]
После нажатия [TAB] все элементы пути будут дополнены. Если вариантов несколько, можно будет вручную выбрать нужный.

Ну вот, я вам передал примерно 0.65 процента магии zsh. Помимо автодополнения, ее залежи находятся в подсистеме подстановок (man zshexpn), но там я сам не очень уверенно ориентируюсь. Все-таки одна из прелестей zsh заключается в том, что мне необязательно учиться им пользоваться – для начала можно ограничиться только bash-совместимым подмножеством функций, регулярно натыкаясь на приятные мелочи в реализации привычных вещей.

Дальнейшее чтение:
обзор zsh от Алексея Федорчука,
Собрание хаков и идиом zsh: zsh lovers.

Categories: SHELL, UNIX, tips Tags: , , ,

Заговор от битых кластеров (добавляем информацию для восстановления архивов с помощью par2)

April 10th, 2008 14 comments

В этой заметке я предложу способ чтения данных с поцарапанных, погрызанных собакой или обработанных шредером компакт-дисков.

Итак, к делу: регулярно, при записывании данных на диск, остается некоторое количество свободного места. Лет 5 назад можно было положить диск на полочку, пометив, что еще 30 мегабайт можно забить каким-нибудь хламом, но сейчас стоимость болванки – 10 рублей, такой аргумент не действует. И, соответственно, привычку оставлять место “на потом” надо искоренять. Мне кажется, наиболее разумным было бы добавить на диск данные для восстановления – т.н. корректирующие коды Рида-Соломона, которые могут пригодится в случае, если диск будет поврежден.

Собственно весь заговор выглядит следующим образом:
#sudo aptitude install par2
#man par2
#cd backups
#ls
dump.sql.gz
#par2 create -v -r10 -n1 -m500 dump.sql.gz
#ls
dump.sql.gz dump.sql.gz.par2 dump.sql.gz.vol000+100.par2

Эта команда добавит 10% избыточной информации к данным, запишет все это в один файл, при этом программе par2 разрешено использовать 500 мегабайт оперативной памяти. Файлы *.par2 следует записать на диск вместе с дампом.

Мне эта программа понравилась, я захотел ее проверить в боевых условиях. Сделал архив размером около 400 Мб, добавил данные для восстановления – еще 200Мб – *.par2 файлы (50% избыточность, по умолчанию – 5%). Все это я записал на CD-RW, в котором потом сделал, простите, дырку. В итоге стандартными средствами удавалось прочитать только первые 150 Кб данных. Чтобы восстановить файл нужно сначала все считать пускай с ошибками – для этого есть программа dd_rescue, которая является практчески полным аналогом dd с одним исключением – она умеет игнорировать ошибки чтения:

диск с дыркой

#sudo dd_rescue -Av -b 1048576 -B 1048576 /dev/scd0 brokencd.iso(-A – заполняь нулями те участки файла, которые считать не удалось, v – verbose, -b – размер блока данных, -B – размер блока данных для проблемных областей диска)
# sudo mount -o loop brokencd.iso mnt # монтируем получившийся образ диска
# cp mnt/* dump; cd dump # копируем содержимое
# par2 r archive.par2 # приводим в изначальный вид

На этом эксперимент завершился – все данные с диска восстановлены. Даже скучно.
Но пример, мне кажется, весьма красноречив :)

Categories: UNIX, tips Tags: , , , ,

SSH для бэкапов и мониторинга: ограничиваем доступ.

March 4th, 2008 1 comment
“Бэкап – акт проявления трусости” (c) народная мудрость

Я труслив :) Во-первых, я делаю бэкапы. Во-вторых, я их боюсь передать без шифрования и, в третьих, иногда и храню их зашифрованными.

Как правильно организовать передачу бэкапов с одного сервера на другой? Дампы этого блога у меня передаются по http. Они зашифрованны, да и особо ценных данных здесь нет, поэтому http меня не смущает. А как поступить с данными по-важнее? Конечно, ssh. А как при этом запретить пользователю выполнять какие-либо действия, кроме как копирования к себе бэкапа? Представим себе, что бэкап-сервер находится во вражеском дата-центре или просто вы не можете проконтролировать к нему доступ (в т.ч. физический). Нас выручит опция command файла authorized_keys.

Например, если необходимо предоставить доступ только к файлу backup.tgz, то в authorized_keys в самом начале соответствующей строки можно дописать следующее “command=’cat backup.tgz’”. Теперь при каждом коннекте будет автоматически выполняться команда cat backup.tgz, вам остается только перенаправить вывод в файл. Если дампов несколько, то можно написать небольшой скриптик вида:#!/bin/sh
read file
case "$file" in
"foo") cat foo.tgz ;;
"bar") cat bar.tgz ;;
esac
И прописать его в качестве команды по умолчанию. Да, не лишним было бы добавить опции no-port-forwarding, no-pty и все прочие no-*

Теперь копировать файл с удаленной машины можно вот такой командой:echo "foo" | ssh backup@server > foo-`date +%Y-%m-%d`.tgz

Кроме как для бэкапов, такое же решение может подойти и для мониторинга. Когда нагиос стучится на удаленный сервер, чтобы собрать какую-либо статистику, полный ssh-доступ ему не нужен.

По-моему, все, что я описал примитивно по сложности и вместе с тем весьма надежно. Так может быть прекратим без надобности дописывать authorized_keys на серверах? Одна запись для себя, любимого, одна для бэкапов, одна для мониторинга.. ой, еще каких-то две.. дальше продолжать? :)

Кстати, а есть ли способы более тонко настраивать уровень доступа к ssh?

Categories: SHELL, UNIX, tips Tags: , , ,

HTTP сервер в одну строку: версия 2.0

August 30th, 2007 49 comments

Идея с HTTP сервером на bash мне не дает покоя.

Вернуться к ней меня побудила.. попытка воспользоваться старой версией: получалсь не очень :)

Поэтому решил довести его до ума. Что-то дописал, что-то выкинул, полчилось следующее:
:;while [ $? -eq 0 ];do nc -vlp 8080 -c'(r=read;e=echo;$r a b c;z=$r;while [ ${#z} -gt 2 ];do $r z;done;f=`$e $b|sed 's/[^a-z0-9_.-]//gi'`;h="HTTP/1.0";o="$h 200 OK\r\n";c="Content";if [ -z $f ];then($e $o;ls|(while $r n;do if [ -f "$n" ]; then $e "<a href=\"/$n\">`ls -gh $n`</a><br>";fi;done););elif [ -f $f ];then $e "$o$c-Type: `file -ib $f`\n$c-Length: `stat -c%s $f`";$e;cat $f;else $e -e "$h 404 Not Found\n\n404\n";fi)';done

Теперь по URL http://ваш_ip:8080/ можно получить доступ ко всем файлам, находящимся в текущим каталоге. Очевидных и прямолинейных способов сменить каталог нет. Как и раньше, протестировано и работает под Linux, bash 3.2.13, и с хоббитовским netcat v1.10 с поддержкой опции -с (запустите netcat -h и посмотрите. Как минимум в Ubuntu, Debian и Fedora Core такая опция есть).

Теперь строка занимает 434 байт, что на 212 больше, чем прошлая версия. И мне кажется, что я с толком потратил эти байты: новый сервер обрабатывает ошибку 404, кроме того, теперь он работает без задержки, которая раньше требовалась для того, чтобы была возможность его остановить с помощью Ctrl-C. Для успешных запросов сервер отдает нормальные заголовки, с размером файла и даже с его MIME-типом. Например:

dainichi@fujitsu:~/backup$ echo "GET /6.1-RELEASE-i386-disc1.iso HTTP/1.1" | nc localhost 8080 | head -n3
HTTP/1.x 200 OK
Content-Type: application/x-iso9660
Content-Length: 529784832

Для удобства можно сохранить его в файл и написать в .bash_profile примерно следующее:alias share='sh ~/bash_httpd.sh'

Да, были попытки его еще уменьшить, но они не увенчались успехом. Есть такой вариант, но он даже больше:
w=while;d=done;e=echo;r=read;echo "true; $w [ @? -eq 0 ];do nc -vlp 8080 -c'($r a b c;f={$e @b|sed 's/[^a-z0-9_.-]//gi'{;h=}HTTP/1.x};o=}@h 200 OK#};c=}Content};if [ -z @f ];then($e @o;ls|(while $r n;do $e }@n
};done));elif [ -f @f ];then $e }@o@c-Type: {file -ib @f{#@c-Length: {stat -c%s @f{#};cat @f;else $e }@h 404 Not Found##404#};fi)';done"|tr "@{}#" '$`"
'|sh
Оставил его, потому что выглядит страшно, детей пугать – самое то :)

Если у вас получится сэкономить еще пару байтов, то милости просим в комментаторскую :)

UPD: 03.09.2007: Код обновлен, в него вошли исправления, которые сделал тов. jetxee, за которые ему большое спасибо.

UPD: 03.09.2007: Я удивлен тому факту, что эта заметка попала в топ news2, спасибо dik’у за то, что добавил ее. Я рад, что она многим показалась интересной.

UPD: 07.09.2007: Товарищ Ed очень здорово прооптимизировал код. Вот, что у него вышло:
while :;do nc -p8080 -vnlc'r=read;e="echo -e";$r a b c;while [ -n "`$e $a|tr -d "\r\n"`" ];do $r a;done;f=`$e $b|sed s/.//`;h="HTTP/1.0";z="404 Not Found\n";[ -z $f ]&&(ls|while $r n;do [ -f $n ]&&$e "$n";done)||([ -f $f ]&&($e "$h 200 OK\r\nContent-Type: `file -ib $f`\n";cat $f)||$e "$h $z\n$z")';done

Работоспособность проверялась автором на таблетке Nokia N800, а у меня в Kubuntu 7.04 что-то не заработало. Сегодня вечером буду разбираться :)

p.s. Мне теперь стыдно из-за того, что сам не догадался использовать && и || вместо if..then. :(

p.p.s. stay tuned!

UPD 18.08.2008: О, написали про это безобразие на Хабре, назвали меня извращенцем. Хулиганьё!! :)

Программерские загогулины [2]

August 23rd, 2007 8 comments

Очередная программерская загогулина, на этот раз решение сразу не дам :)

Допустим, надо выполнить какую-либо команду на нескольких хостах, перечисленных в файле. Пишу:

cat file | (
while read host; do
ssh user@$host "command"
done
)

Ошибка, однако! В чем?
Кто сможет разобраться в уме, не запуская код, тому респект и уважуха :)

UPD:

Решил человек, скрывающийся под ником gds:

поток из “cat file” будет выкушан только первой запущенной командой “ssh …”?

gds, респект тебе уважуха :)

Удаленный рабочий стол. UNIX-way :)

August 6th, 2007 5 comments

Как всегда, существует уйма способов запускать графические программы удаленно. Не все из них основаны на туннелинге X-трафика, но именно с ним играться интересней всего.

Приступим :)

Собственно, на практике страшная фраза “сделать туннелинг Х-протокола” обозначает, что нужно добавить опцию X к ssh. Получается, что в простейшем случае запустить удаленную графическую программу можно так:
ssh -X user@host firefox

Kdesktop от других программ ничем не отличается:
ssh -X user@host kdesktop

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

Я это сделал так:
xinit /usr/bin/ssh -X user@host startkde -- :1
Набирать команду следует из обычной, неиксовой консоли (Ctrl-Alt-F1), и работать она будет только в случае, если на удаленной машине уже лежит наш публичный ключик, т.к. не будет возможности ввести пароль. (что такое публичный ключ). Полный путь к ssh на некоторых дистрибутивах обязателен.

Теперь сочетанием клавиш Ctrl-Alt-F7 и Ctrl-Alt-F9 можно переключаться между локальным и удаленным рабочим столом (хотя F9 для удаленной машины – это лично у меня, у вас может быть также F8 или F10). Да, и делать это лучше только если соединение между машинами быстрое, иначе нервных расстройств не избежать :)

Этот пост написан с рабочего десктопа, но через ноутбучную оперу :)

А что интересного с помощью ssh удавалось сделать вам?

UPD через 20 мин: Отправил ноутбук в ребут и через некоторое время понял, что работаю на удаленной машине. 5 секунд паники, 10 – на сохранение и минута чтобы понять, что я ошибся :) Вобщем, для людей со слабым сердцем не рекомендую так работать, а сам я теперь осторожен, как сапер на минном поле :)

Categories: UNIX, tips, общее Tags: , , , ,

codepage horror

June 29th, 2007 1 comment

Иногда мне снятся сны. Бывает, что кошмары. Что такое кошмар для админа? Это когда видишь свой сайт – все работает, все грузится, но кодирЛЮХВ КВЯНЕК ЗИЕОЕИВ!!!

На работе сегодня этот кошмар воплотился: вселился бес в базу и попутал все кодировки. Попутал на славу, так что первый дамп пришлось расшифровать в два приема: utf8->koi и cp1251->koi, а со вторым развлечение было поизощреннее. С каждой перестановкой буквы прыгали издевательски с места на место, подмигивали и смеялись, доводя мой ЙЛЗХмоск до кипения. Но битву они все-так проиграли. После пятой перекодировки cp1251->koi8r из поганцев сгинул злой дух и оборотились они текстом складным и залился дамп в базу и вернулись: юзерам – счастье, а админу – крепкий сон :)

p.s.

А на #freebsd народ показал такой фокус:


#str="трали-вали"; for((i=0; $i<20; i++)); do str=`echo "$str" | iconv -f CP1251 -t KOI8-R`; done;
#echo $str
трали-вали

return 0;

June 27th, 2007 No comments

Я вернулся :)
За время учебного отпуска нагулял отличное рабочее настроение!

В первый рабочий день обратил внимание на небольшой юбилей: 1 год и 4 дня исполнилось моему процессу screen, запущенному на работе, которым я активно пользуюсь по 40 часов в неделю. Слава героям!!

Попутно веду свою маленькую коллекцию программерских загогулин, вот очередной экземпляр:


#!/usr/bin/perl
$var1 = "one|two|three";
$var2 = join('|', split ('|', $var1));

Опрос знакомых программистов показал, что предполагаемым значением $var2 является исходная строка ($var1). PERL думает иначе.

Вся мощь перла с его реально перегруженными функциями именно в этом моменте дала слабину: split в качестве первого аргумента принимает _только_ регулярное выражение, и, соответственно, символ ‘|’ воспринимается как логическое “или”.. Таким образом, в var2 будет “o|n|e||t|w|o”…

Пусть такое поведение и является документированным, меня оно все равно расстраивает..

Интернет от skylink в Linux (Kubuntu + Ubiquam U-300 через bluetooth)

January 5th, 2007 1 comment

В Linux просто замечательная поддержка bluetooth – интернет у меня заработал в течении 15 минут. Больше времени потребовалось на то, чтобы решиться :)

А команды будет всего три:

root@dainichi-laptop:~# sdptool search DUN
Inquiring ...
Searching for DUN on 00:16:39:ED:81:00 ...
Service Name: QC Dial-up Networking
Service RecHandle: 0x10000
Service Class ID List:
"Dialup Networking" (0x1103)
Protocol Descriptor List:
"L2CAP" (0x0100)
"RFCOMM" (0x0003)
Channel: 8
Language Base Attr List:
code_ISO639: 0x656e
encoding: 0x6a
base_offset: 0x100
Profile Descriptor List:
"Dialup Networking" (0x1103)
Version: 0x0100

Отсюда узнаем, что существует некое устройство с MAC 00:16:39:ED:81:00, которое предоставляет сервис доступа к сети на канале 8. Далее создаем rfcomm устройство – COM порт, работающий через bluetooth:

root@dainichi-laptop:~# rfcomm bind 0 00:16:39:ED:81:00 8
root@dainichi-laptop:~# dmesg | tail
[17179616.448000] Bluetooth: L2CAP socket layer initialized
[17179616.464000] Bluetooth: RFCOMM socket layer initialized
[17179616.464000] Bluetooth: RFCOMM TTY layer initialized
[17179616.464000] Bluetooth: RFCOMM ver 1.7

Если команда rfcomm ничего не вывела на STDOUT, значит, все отлично и можно приступать к установлению PPP соединения. Я это сделал так:

root@dainichi-laptop:~# kppp

Уже в kppp добавил модем (устройство: /dev/rfcomm0; скорость: 115200; управление потоком: hardware), указал телефон (#777), аутентификацию (PAP-CHAP), и логин/пароль (mobile/internet).

Собственно, с интернетом разобрались, напоследок немного увлекательнейших манов: sdptool, dund, hcitool, l2ping, rfcomm :)

Categories: UNIX, tips Tags: , , , ,

Hint [10]

December 23rd, 2006 No comments

[10] Все мы с пеленок знаем, что & значит запустить программу в фоновом режиме, но лично у меня случаи, когда такая форма запуска является оправданной встречаются редко. Хотя недавно я “открыл для себя” один из классов таких случаев – какие-либо действия с сетью, которые сами по себе не ресурсоемки, но могут выполняться долго вследствие больших таймаутов.

Вот так я проверяю список хвостов на “пингуемость”:

cat proxies | (IFS=”:\n”; while read ip port; do (if ping -w 1 -c 1 -q $ip>/dev/null; then echo “$ip:$port”; else echo “bad: $ip:$port”; fi)& done;) | tee proxies_pingable

В данном случае я запускаю в фоне сабшелл (if ping -w 1 -c 1 -q $ip>/dev/null; then echo “$ip:$port”; else echo “bad: $ip:$port”; fi), потому скрипт приступает к пингу следующего хоста, не дожидаясь, когда завершится проверка предыдущего. Выигрыш по времени пропорционален количеству хостов – если их 100, то практически стократный!
Правда, нужно быть аккуратным – если в списке 10 тысяч хостов, то это будет уже больше похоже на DoS.

Categories: UNIX, tips Tags: , , , ,