Archive

Archive for the ‘tips’ Category

Магия в 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: , , ,

О прозрачности в командной строке [pv]

December 4th, 2007 4 comments

Эта запись будет посвящена программе с лаконичным названием pv. А слово “прозрачность” пусть не ассоциируется у вас с пресловутыми compiz-fusion, тут все гораздо интереснее :)

Итак, чем плох избитый пример c передачей файлов через netcat? Мне, например, не удобно то, что нет возможности наблюдать за процессом. В самом деле, возможности юниксовых шеллов в этом плане довольно скромные: с помощью tee можно сохранить поток в файл, который потом наблюдать через tail или следить за его размером командой ‘watch ls’. Этого достаточно для отладки, но мало для комфортной работы.

Поэтому программа pv просто не могла не появиться. Все очень в духе UNIX – маленькая утилитка, которая пропускает через себя поток данных и в STDERR отправляет некоторую статистику по ним. Но _как_ она это делает! Покажу на примерах:

Всегда хотел узнать:
dainichi@fujitsu:~$ cat /dev/toilet_paper | pv >/dev/shreder
1.01GB 0:00:02 [ 569MB/s] [ <=> ]

Ага, больше десяти рулонов в секунду..

Прикинемся взрослой программой с выводом а-ля wget:
dainichi@fujitsu:~$ cat file | pv -s `stat -c %s file` | nc so.far.away 1234
236kB 0:00:05 [ 346КB/s] [==================> ] 72%

Ограничим скорость обработки файла, чтобы mplayer не тормозил:
dainichi@fujitsu:~$ cat big_log | pv -L 100к | log_processor > report

Пример из мана – архивирование каталога и одновременное отображение прогрессбара
(tar cf - . | pv -n -s `du -sb . | awk '{print $1}'` \
| gzip -9 > out.tgz) 2>&1 | dialog --gauge 'Progress' 7 70

И, напоследок, скриншот с домашней страницы проекта:
скриншот с домашней странички проекта pv

Здорово? :) По-моему, да :)

Кстати. а какие еще способы “очеловечить” интерфейс командной строки вы знаете?

UPD Андрей Афанасенко поделился ссылкой вот на такое чудо:

Написана эта программа на bash и во многих случаях ее использовать гораздо удобнее, чем pv.

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: О, написали про это безобразие на Хабре, назвали меня извращенцем. Хулиганьё!! :)

Что получится, если скрестить fuse и ssh? ‮[файловая система sshfs]

August 29th, 2007 No comments

А получится sshfs.
sshfs позволит вам монтировать каталоги на удаленных машинах по протоколу SFTP; пользоваться им настолько просто, что даже рассказать в этой заметке практически нечего: ни тебе интрижки с накладыванием патчей и сборкой пакета, ни тебе объектного языка конфигурационных файлов. Тоска, одним словом.

Но для sshfs это, вобщем-то, плюс. Итак, начнем с установки пакета и добавления себя в группу fuse, делается это так:
apt-get install sshfs
sudo adduser your_name fuse

Команда adduser в таком контексте ничего, кроме добавления уже существующего пользователя в группу не делает, так что не нужно смущаться от ее неожиданного выхода на сцену. После этого нам нужно перелогиниться, чтобы изменения в /etc/group вступили силу.

Мне пришлось выполнить еще одну операцию: сменить группу у устройства /dev/fuse. Я думаю, это особенность лично моего дистрибутива, но если у вас тоже попытки монтирования будут завершаться ошибкой “что-то там permission denied”, то вот вам команда:
chgrp fuse /dev/fuse
По-хорошему, ее надо прописать куда-нибудь в автозагрузку, например, в /etc/rc.local.

Теперь все готово для монтирования:
mkdir mount_point
sshfs remoteuser@remotehost:/some/folder ~/mount_point
ls mount_point

Ну вот, собственно, и все, можно работать.

Теперь настало время рассказать об одном ограничении: кроме нас, никто в системе не сможет воспользоваться примонтированным каталогом. Сама возможность пустить туда других пользователей есть, но корректность операций записи не гарантируется (могут быть повреждены атрибуты файла – владелец и пр.). Поэтому перед тем, как открывать доступ к важным данным лучше все-таки поставить эксперимент на копии. Также несколько странные результаты будет выдавать команды du и df, но по-моему, это я уже придираюсь :)

В итоге, мы имеем отличную замену scp/sftp или fish (встроенная в mc и konqueror оболчка для sftp) для случаев, когда нужно выполнить действия посложнее, чем копирование.

Дальнейшее чтение: FAQ по sshfs, Другие основанные на fuse файловые системы

Categories: UNIX, tips Tags: , , ,

Удаленный рабочий стол. 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: , , , ,

Интернет от 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: , , , ,

Редактирование множетва файлов (diff, patch)

December 2nd, 2006 No comments

В случае, если необходимо сделать мелкие исправления сразу в множестве не идеинтичных файлов, могут очень помочь утилиты diff/patch.

Например, сегодня нужно было исправить e-mail адреса в конфигах десяти разных инсталляциях одной программы. Можно было ручками пройтись и тупо редактировать файлы, но это не интересно. Вот, как это можно сделать:

mkdir _wrk && cd _wrk - создать временный каталог
cp ~/installation1/file . - скопировать в него один из файлов.
cp file file.bak - сохранить старую версию
vim file - внести необходимые изменения
diff file.bak file > ~/patch - создать патч.

cd ~ - перейти в каталог, в котором наохдятся все инсталляции
find -name file -print0 | xargs -n1 -J % echo "patch " % " ~/patch" > script найти все файлы, которые нужно отредактировать и сохранить скрипт, который сделает все необходимые изменения

cat script - убедиться, что не нашлось ничего лишнего (например, тот же файл, но в бекапах)
sh script - поехали!

Далее, необходимо убедиться в том, что все ок и удалить *.orig файлы (резервные копии, оставленные программой patch. Сделать это можно командой find -name file.orig -rm).

При составлении патча нужно быть внимательным, т.к. легко перепутать исходный и резервный файлы и получить “перевернутый” патч, который будет пытаться делать в исходном файле изменения, которые необходимо сделать в отредактированном для получения исходного. Впрочем, программа patch корректно обрабатывает эту ситуацию и не даст испортить файл. Но все равно, лучше сразу сделать все нормально.

Categories: UNIX, tips Tags: , , ,