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

 

HTTP-сервер своими руками

Миниатюрный HTTP-сервер, собранный из подручных компонентов, остается одной из самых любимых тем современных гиков. Они готовы написать его буквально на всем, начиная от простого использования команды netcat на 80-порту и закачивая языком PostScript, используемым для форматирования текста перед выводом на принтер. Блоггер по имени Алексей Свечников взялся за эту тему и написал HTTP-сервер на bash размером всего 222 байта (http://alexey.sveshnikov.ru/blog/2006/12/23/http-сервер-размером-в-222-байта/). Сначала вся идея сводилась к горячо любимому UNIX-админами рудиментарному серверу с использованием nc, пример которого приведен ниже:

server$ nc -l -p 8080 < file
client$ x-www-browser
http://192.168.0.1:8080

Но затем пример оброс функционалом и превратился в HTTP-сервер, способный отдавать файлы по запросу и список файлов текущего каталога. Ниже приведена переработанная версия скрипта Алексея, которая корректно работает с google chrome и избавлена от бага с файлами, имеющими в названии символы в верхнем регистре:

$ while true; do nc -vv -l -p 8080 -c
'( read a b c; file=`echo $b | sed 's/
[^a-zA-Z0-9.]//g'`; if [ a$file = "a"
]; then ls -l; else cat $file; fi )';
sleep 1; done

Все это одна команда. Сервер отдает файлы текущего каталога, для запроса списка которых достаточно просто обратиться к корневому каталогу. После выбора файла добавляем его имя в адресную строку и благополучно скачиваем на свою машину. Некоторое время спустя Алексей реализовал более продвинутую версию сервера, которая умеет отдавать HTTP-заголовки (а для файлов вместе с размером и MIME-типом), обрабатывает ошибку 404 и отдает полноценный index.html. Ее однострочный оригинал и развернутый вариант, удобный для чтения и анализа, ты найдешь на прилагаемом к журналу диске.

Еще более гиковый вариант HTTP-сервера имеется на страничке Martin A. Godisch. Он пошел дальше всех остальных и воспользовался для написания сервера не каким-нибудь bash или awk, а языком программирования PostScript, который был разработан Adobe Systems для описания сложных графических объектов и подготовки печатных изданий. Исходный текст сервера слишком велик, чтобы продемонстрировать его на страницах журнала, но ты можешь получить его, обратившись к страничке http://people.debian.org/~godisch/pshttpd или заглянув внутрь нашего диска.

 

Демон закачек на базе CUPS

Менеджер печати CUPS, ставший стандартом в UNIX-системах, обладает несколькими очень привлекательными характеристиками, которые позволяют использовать его в качестве менеджера любых очередей, к которым необходим удаленный доступ и расстановка приоритетов. Если в твоем распоряжении имеется машина, которую ты собираешься использовать для закачки файлов, то CUPS позволит ей справиться с этой задачей без необходимости установки дополнительного софта и танцев с бубном. Алгоритм действий по превращению CUPS в демон закачек следующий:

1. Для начала напишем скрипт cwget.sh, который будет осуществлять закачку файлов и вызываться приведенным ниже CUPS-бэкендом:

$ sudo vi /usr/local/sbin/cwget.sh
#!/bin/sh
DOWNLOAD_DIR=$1
cd
mkdir -p "$DOWNLOAD_DIR"
cd "$DOWNLOAD_DIR"
/usr/bin/wget -nc -i "$2" >/dev/null 2>&1

Сделаем его исполняемым:

$ sudo chmod +x /usr/local/sbin/cwget.sh

2. Теперь создадим специальный CUPS-бэкенд, который будет принимать добавленные в очередь URL и отдавать их вышеописанному скрипту:

$ sudo vi /usr/lib/cups/backend/cwget
!/bin/sh
if [ $# -eq 0 ]; then
echo 'cups wget "Unknown" "Cups wget
downloader"'
exit 0
fi
# Каталог для закачек
DOWNLOAD_DIR=/var/tmp
umask 0
TMPFILE=/tmp/cwget$$
cat "$6" > $TMPFILE
/bin/chmod +r $TMPFILE
/usr/bin/sudo -H -u $2 /usr/local/sbin/cwget.
sh "$DOWNLOAD_DIR" "$TMPFILE"
rm /tmp/cwget$$

Дадим ему права на исполнение:

$ sudo chmod +x /usr/lib/cups/backend/cwget

3. Чтобы позволить коду бэкенда использовать sudo для запуска скрипта cwget.sh с рутовыми полномочиями, разрешим пользователю lp, с правами которого запускаются CUPS-задания, делать это без запроса пароля:

$ sudo visudo
lp ALL=(ALL) NOPASSWD:/usr/local/sbin/
cwget.sh

4. Настроим несколько принтеров через web-интерфейс, указав в качестве их бэкенда cwget (смотри скриншот «Виртуальные принтеры с cwget-бэкендом») и объединим их в класс, чтобы получить возможность одновременной закачки более чем одного файла.

5. Все, теперь можно отсылать задания (URL) на виртуальный принтер. Сделать это можно, например, так:

$ echo 'http://kernel.org/pub/linux/kernel/v2.6/linux-2.6.33.tar.bz2' | lpr -Ppcwget

 

Openbsd и безопасный голосовой чат из коробки

Open’овская утилита aucat, изначально созданная для проигрывания «сырых» звуковых файлов с расширением .au, со временем обросла функциональностью и сегодня может использоваться для многих целей, включая различные преобразования звукового потока в режиме реального времени, а также возможность применения в качестве полноценного аудиосервера, способного смешивать звуковые потоки, порождаемые другими инстанциями aucat. Известный в OpenBSD-кругах хакер по имени Райан Флэнири воспользовался этой возможностью для создания простой системы голосового чата, не требующей установки какого-либо дополнительного ПО. Идея, положенная в ее основу, такова:

1. Запустить aucat в режиме сервера на двух удаленных машинах. Работая в режиме сервера, aucat подключится к устройствам ввода и вывода звука и создаст UNIX-сокет, чтение из которого приведет к чтению данных из устройства ввода (микрофон), а запись — к записи в устройство вывода (колонки).

2. Запустить второй процесс aucat в обычном режиме на первой машине и перенаправить его вывод процессу aucat, работающему на второй машине с помощью ssh. В результате входной поток, полученный с микрофона и направленный сервером aucat в UNIX-сокет, будет прочитан aucat-процессом и перенаправлен на удаленную машину, где его прочитает удаленный aucat-процесс и запишет в UNIX-сокет собственного aucat-сервера. Так звук с микрофона первой машины попадет в колонки второй.

3. Повторить шаг 2 на второй машине, чтобы создать обратную связь. На уровне командной строки все это выглядит так:

user1@host1> aucat -l
user1@host1> aucat -o - | ssh \
user1@host2 aucat -i user2@host2> aucat -l
user2@host2> aucat -o - | ssh \
user2@host1 aucat -i

Однако именно в таком виде система не заведется. Оказывается, работая в серверном режиме, aucat привязывает создаваемый UNIXсокет к запустившему его пользователю (файл получает имя /tmp/aucat-ID-юзера/default), и когда клиентский процесс aucat подключается к серверу, он также использует ID текущего пользователя для обращения к сокету. Чтобы работать совместно, сервер и клиент aucat должны быть запущены одним пользователем.

В приведенном выше примере клиент aucat, запускаемый на машине host2 с помощью ssh, будет работать с правами пользователя user1, тогда как сервер на этой машине будет запущен с правами пользователя user2, поэтому звук до второй машины «не дойдет». Для этого, можно либо использовать аккаунты с одинаковым ID пользователя на обеих машинах, либо пойти на небольшой трюк и после запуска сервера создать ссылку на каталог /tmp/aucat-ID-юзера для другого пользователя. Вот как это сделать на обеих машинах:

u1@h1> user1_UID='id -ur user1'
u1@h1> user2_UID=`id -ur user2'
u1@h1> aucat -l; cd /tmp/
u1@h1> chmod 755 aucat-$user1_UID
u1@h1> ln -s aucat-$user1_UID aucat$user2_UID
u2@h2> user2_UID='id -ur user2'
u2@h2> user1_UID=`id -ur user1'
u2@h2> aucat -l; cd /tmp/
u2@h2> chmod 755 aucat-$user2_UID
u2@h2> ln -s aucat-$user2_UID aucat$user1_UID

Затем можно запускать перенаправление звука. Райан предостерегает, что по умолчанию ты получишь слишком большую задержку, и рекомендует установить минимальный размер буфера и снизить частоту дискретизации звукового потока до 11000 Гц:

user1@host1> aucat -b 1 -r 11000 -o - \
| ssh user1@host2 aucat -b 1 \
-r 11000 -i

 

Видеопамять как своп

Современные графические адаптеры оснащаются внушительным объемом высокоскоростной памяти, большая часть которой остается незадействованной во время обычной работы с системой. Ядро Linux позволяет использовать эту память для своих нужд, зарезервировав небольшой ее объем для стандартных VESAрежимов, а все остальное использовать для хранения файлов или создания своп-раздела. Проделать такое можно с помощью специального драйвера под названием Memory Technology Device (MTD), позволяющего адресовать не только оперативную память, но и память любого устройства, подключенного через шину PCI. Вся методика сводится к активации драйвера в ядре, выяснению адресного пространства видеопамяти и ее отображения в адресное пространство ядра. Итак, для начала активируем драйвер в ядре, для этого запустим «make menuconfig», перейдем в раздел Device Drivers и активируем следующие пункты меню:

$ sudo make menuconfig
Device Drivers --->
<M> Memory Technology Device (MTD)
support --->
<M> Direct char device access to
MTD devices
<M> Common interface to block
layer for MTD 'translation layers
<M> Caching block device access
to MTD devices
Self-contained MTD device
drivers --->
<M> Physical system RAM

Теперь необходимо найти видеопамять в адресном пространстве шины PCI. Для этого воспользуемся утилитой lspci и найдем графический адаптер:

$ lspci | grep VGA

Вывод должен выглядеть примерно так:

02:00.0 VGA compatible controller:
nVidia Corporation NV35 [GeForce FX
5900XT] (rev a1)

Узнаем детальную информацию о карточке:

$ lspci -vvv -s 02:00.0

Видеопамять разделена на несколько регионов, один из которых помечен как prefetcheble. Это и есть основное место хранения изображений, формируемых адаптером для вывода на экран (буфер кадров), а также для хранения промежуточных результатов обработки 3D-изображений. Проведя небольшие расчеты, мы можем выяснить, какая ее часть используется под буфер кадров, необходимый для вывода 2D-картинки на экран (которой мы пожертвовать не можем, не потеряв возможность работать с графикой), а какая применяется только для расчетов в режиме 3D и потому может быть использована нами. Изображение, хранимое в буфере кадров, представляет собой двумерный массив, размер которого соответствует используемому разрешению экрана, а размер каждого элемента равен глубине цвета. Поэтому при разрешении экрана 1024×768@32 для хранения изображения будет задействовано 1024 * 768 * 4 = 3145728 байт (32 бита = 4 байта) или 3 Мб. Как и любой другой процессор, видеочип адресует память от ее начала, поэтому, чтобы получить доступ к видеопамяти, не задев при этом буфер кадров, мы должны отобразить память не от ее начала, а с точки, расположенной за этими самыми тремя мегабайтами (а лучше сразу за восемью для надежности и поддержки более высоких разрешений). Берем из вывода приведенной выше команды lspci адрес prefetcheble-региона видеопамяти.

Он указан после словосочетания «Memory at» и в нашем примере составляет e0000000. Переводим 8 Мб в шестнадцатиричную систему счисления и получаем 800000. Прибавляем это число к адресу региона и получаем e0800000. Далее выходим из иксов и подгружаем модуль phram, передав ему в качестве аргументов этот адрес и размер региона (если адаптер оснащен 128 Мб памяти, то размер за вычетом 8 Мб будет равен 120 Мб):

$ sudo modprobe phram phram=VRAM,0xe0800000,120Mi

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

$ cat /proc/mtd

В выводе должен быть указан размер устройства, начало адресуемой им памяти и его имя. Если все в порядке, загружаем модуль mtdblock, который превратит псевдоустройство /dev/mtd0 в блочное устройство /dev/mtdblock0:

$ sudo modprobe mtdblock

Это все, теперь на устройстве можно создать своп:

$ sudo mkswap /dev/mtdblock0
$ sudo swapon /dev/mtdblock0

Или файловую систему:

$ sudo mkfs.ext2 /dev/mtdblock0

Чтобы не обрушить иксы, открой конфиг /etc/X11/xorg.conf и вставь в секцию Device строку Driver "vesa".

 

Тетрис, Арканоид и Сокобан из редактора

Потоковый редактор SED (Stream EDitor), существующий в UNIX с начала времен и предназначенный для потокового неинтерактивного редактирования текстов с помощью управляющих команд, оказался настолько мощным инструментом, что с его помощью можно не только выполнять сложнейшее редактирование текста, но даже написать полноценное приложение или целую игру. Наверное, все слышали облетевшую многие UNIX-сайты и блоги историю о том, как девушка по имени Юля написала самый настоящий тетрис, используя только редактор SED и небольшой скрипт-обертку (http://uuner.livejournal.com/55238.html). Трудно сказать, что побудило ее на эту странность, однако содержащийся в представленных файлах код взрывает голову, начиная уже с первых строк, и говорит о незаурядном мышлении и превосходном знании редактора.

Однако, как бы это не било по гордости за родную отчизну, на официальном сайте редактора (http://sed.sourceforge.net) подобных игр насчитывается аж 11 штук, среди которых можно найти такую классику как сокобан и арканоид, работающий в пошаговом режиме. А если промотать ниже, то найдешь даже модуль для Apache, позволяющий исполнять SED-сценарии внутри web-сервера.

 

Jabber вместо SSH

Возможность воспользоваться полноценным SSH-доступом есть далеко не всегда. Машина может находиться за файерволом, который режет 22-й порт, или входить в частную сеть с доступом в интернет только через NAT. Приходится включать творческое мышление, и первое, что приходит в голову — написать простой jabber-бот, который будет подключаться к jabber-серверу, слушать вводимые другим пользователем команды и выполнять в окружении операционной системы. Немного поискав в Сети, мы обнаружим, что идея не нова, и некоторые люди уже пробовали создать нечто подобное. Мне понравилась реализация, написанная командой сайта www.ylsoftware.com. Наибольшая ее ценность в простоте исходника бота, который легко понять и модифицировать для своих нужд.
Скачав архив, распаковываем его и создаем конфигурационный файл:

$ wget ylsoftware.com/jabber-shell-20090303.tar.bz2
$ tar -xjf jabber-shell-20090303.tar.bz2
$ vi ~/.jabber-shell
(
# Сервер и порт
'server' => 'jabber.ru',
'port' => '5222',
# Учетная запись пользователя, используемая ботом
'username' => 'jabber-shell',
'password' => 'password',
# Ресурс бота
'resource' => 'jabber-shell',
# JID админов
'admins' => 'admin1@host.com admin2@host.ru',
)

Бот регистрируется на сервере под отдельным JID’ом (который придется завести заранее) и принимает команды только от пользователей, перечисленных в опции admins. Теперь можно установить зависимости в виде пакетов perl, libnet-xmppperl и libnet-jabber-perl и запустить бота:

$ ./jabber-shell.pl &

Сообщения от запускаемых тобой команд будут приходить в ответных сообщениях.

 

Web-камера в качестве мыши

Введя в адресной строке браузера строку www.youtube.com/watch?v=LG HItQK2fA8&feature=player_embedded, ты сможешь увидеть видеоролик, демонстрирующий работу небольшого python-скрипта, позволяющего управлять курсором мыши с помощью любых объектов, находящихся в зоне видимости web-камеры. На нашем диске ты найдешь скрипт, который
позволяет это делать.

Для его запуска потребуется установить пакеты cmake, python, python-xlib, а также самый важный компонент — библиотеку компьютерного зрения OpenCV (http://opencv.sf.net). Ее нет в большинстве дистрибутивов, поэтому придется собрать самостоятельно:

$ tar -xjf OpenCV-2.0.0.tar.bz2
$ cd OpenCV-2.0.0
$ mkdir release; cd release
$ cmake -D CMAKE_BUILD_TYPE=RELEASE \
-D CMAKE_INSTALL_PREFIX=/usr/local \
-D BUILD_PYTHON_SUPPORT=ON ..
$ sudo make install

После установки всех компонентов просто запусти cam-mouse-ctrl.py, и ты сможешь проделать трюк, показанный в ролике.

 

А что сделал ты?

Все описанные в статье приемы были придуманы такими же юниксоидами, как ты. Если в твоей голове есть другие интересные идеи нестандартного использования программ или даже их полноценные реализации — смело шли их мне, и если они окажутся достойны внимания, мы опишем их в одной из ближайших статей (не забыв о копирайтах :).

 

Links

 

Info

PostScript — язык описания страниц. Предназначен для формирования изображений произвольной сложности и вывода их на печать.

Оставить мнение

Check Also

Скрытая сила пробела. Эксплуатируем критическую уязвимость в Apache Tomcat

В этой статье мы поговорим о баге в Apache Tomcat, популярнейшем веб-сервере для сайтов на…