понедельник, мая 14, 2007

Как сделать маленький LiveCD "вручную"

Я сделал уже второй livecd, правда этот - уже совсем специального назначения - для развертывания системы из образа. Так что у меня выработалась некая технология изготовления таких микро-дистрибутивов.
Пакеты я беру из своего debian etch (а шо? много уже скомпилированного софта). Но я считаю, что на liveCD система управления пакетами вроде apt совершенно ни к чему. Поэтому перед установкой в создаваемую систему я конвертирую deb-пакеты в обычные тарболлы (.tar.gz), благо это совсем просто (вот скрипт).
Далее, из идеи о минимальном дистрибутиве сразу следует, что на диске должно быть только то, что необходимо в данном случае. Поэтому начинаем создание livecd с установки самых нужных пакетов. Например, в последнем случае у меня был скрипт-инсталятор, написанный на bash+dialog. Значит, на диске нужны: bash, dialog и их (жесткие) зависимости. Скрипт использует cp с компанией - значит, нужен пакет coreutils.
Зависимости надо как-то отслеживать, не вручную же? В качестве внешней (по отношению к создаваемой системе) базы данных зависимостей я использую базу apt-cache моей рабочей системы.
Все это делается, естественно, скриптами. Вот скрипт, устанавливающий tar.gz в директорию с создаваемой системой. Этот скрипт находит deb-пакет, конвертирует его в tar.gz (используя вышеприведенный deb2targz), и устанавливает его. Наконец, этот скрипт устанавливает сначала зависимости пакета, а потом и сам пакет. Таким образом, пакеты ставятся в систему командой install-depends <имя-пакета>.
Замечание 1: скрипт install-depends устанавливает только непосредственные зависимости пакета. Т.е. если пакет A зависит от B, а B зависит от C, то команда install-depends A поставит пакеты A и B, но не поставит пакет C. Это пока приходится отслеживать вручную. Благо, в маленьких системах таких случаев мало. А для большой системы можно и скрипт поправить (а можно и нормальный пакетный менеджер поставить).
Замечание 2: всем скриптам нужна директория, выделенная под новую систему, и в ней директория с именем packages. Там будут складываться установленные пакеты (deb и tar.gz), и там же будет храниться файл installed.list со списком установленных пакетов - чтобы не устанавливать одно и то же два раза.
Замечание 3: во всех приводимых скриптах перед использованием нужно везде прописать правильные директории, по контексту вроде понятно, какие. Если непонятно - спросите в комментах.
Таким образом, по кусочкам, в выделенной директории оказывается более-менее рабочий вариант системы (по вопросам, какие пакеты надо ставить для того, чтобы работало то или другое, например login, загляните в LFS - полезная книжка). После того, как поставлен bash с зависимостями, в созданную систему можно chroot'нуться (chroot /path/to/live /bin/bash), и работать уже "изнутри".
После установки пакетов понадобится еще кое-какая доводка, чтобы система стала совсем рабочей - написание /etc/fstab, /etc/inittab и еще чего понадобится (в инсталяторе, например, мне ни inittab, ни fstab не понадобились). Сюда же относится написание startup сценариев - тут у вас полная свобода, пишите что вам надо. Для совсем простых систем можно вообще не ставить sysvinit, а в качестве init использовать самописный скрипт на bash.
Таким образом получается система, в которой можно работать как в chroot-среде. Теперь нужно обеспечить ее загрузку. Для этого, прежде всего, нужно ядро.
Можно взять дистрибутивное ядро. Оно сконфигурировано так, чтобы загружаться на чем угодно. Есть у него недостаток - оно модульное, и нужность тех или иных модулей определяется скриптами при каждой загрузке. Скрипты а) выполняются относительно долго и б) сложные, захочешь чего-то сделать по-своему - скорее всего сломаешь. Однако пару "дистрибутивное ядро + скрипты из рабочей системы" я посоветую для тех livecd, которые должны загружаться на совсем разных конфигурациях железа.
Если круг оборудования более определен, можно собрать для него свое ядро. Это окажется необходимо, если загружаться надо на самом распоследнем железе - дистрибутивное ядро его не поддерживает. Это также необходимо, если вы хотите применить к ядру патчи, которых нет в дистрибутивном ядре. Например, в LiveIDE я использую SquashFS, чтоб впихнуть всего побольше.
Для маленьких систем можно собрать монолитное ядро. Это хорошо тем, что ядро само определит все оборудование, какое оно знает, т.е. скрипты для определения оборудования не нужны. Конечно, эта идея не пройдет, если поддерживать нужно очень широкий круг оборудования. Но, например, из ядра для инсталятора я выкинул поддержку звуковых карт, сети и еще много чего - оно в момент установки не нужно.
Для загрузки нужен загрузчик. Я использую isolinux. Настроить его совсем несложно, все описано в документации. В качестве примера настройки можете взять содержимое директории isolinux/ на установочном CD вашего дистрибутива.
Загрузчик загрузит ядро. А ядро, по идее, должно запустить /sbin/init. Но для этого оно должно примонтировать корневую ФС. А где у нас будет корень? CD-ROM не подходит из-за того, что на разных машинах он подключен по-разному - то он /dev/hdb, а то вовсе /dev/scd0. Поэтому на LiveCD в качестве корневой ФС (по крайней мере, на первом этапе загрузки) традиционно используют initrd.
initrd - это файл образа любой ФС, понимаемой ядром (поддержка этой ФС должна быть вкомпилирована в ядро намертво, т.е. не модулем). Можно этот образ пожать при помощи gzip, получив initrd.gz - ядро умеет такие образы распаковывать.
Что класть в initrd? В initrd может быть, как минимум, три варианта:
  • Совсем минимальная система, которая только и делает, что находит диск и монтирует его в качестве "настоящей" корневой ФС;
  • Вся система;
  • Часть системы, способная загрузиться и подмонтировать остальные части системы с cd.
Первый вариант обычно используется в "настольных" системах. Его можно использовать и для livecd, в том случае, если основная (live) система занимает как раз что-то около 500..700Мб. Если система занимает больше - нужно использовать сжатие отдельных частей системы, для того, чтобы с ними работать, нужна уже не совсем тривиальная система.
В LiveIDE у меня используется третий вариант. Директория /usr сжата в образ squashfs, а все остальное находится в initrd.
Для маленьких систем имеет смысл использовать второй вариант - помещение системы в initrd целиком.
Файловая система, находящаяся в памяти имеет следующие преимущества: 1) она доступна на чтение/запись (а cd и squashfs - только на чтение); 2) если, кроме ядра и initrd, с диска ничего не грузится, диск можно достать из привода сразу после загрузки. Ну а недостаток большого initrd очевиден - он занимает много места в памяти.
Для загрузки ядра с initrd в качестве корневой ФС нужна следующая строка в isolinux.cfg:
append initrd=initrd.gz load_ramdisk=1 ramdisk_size=50000 rw root=/dev/ram0
В параметре ramdisk_size нужно указать число, несколько превосходящее размер распакованного initrd.
Если в системе не используется sysvinit, а используется свой init-скрипт, нужно дописать к этой строке что-то вроде "init=/sbin/install-image" .
Теперь создаем образ initrd (например, так: dd if=/dev/zero of=initrd bs=1024 count=40x1024), форматируем его (mkfs.ext2 initrd), монтируем как loop-устройство (mount -o loop initrd /mnt/initrd), кладем туда все, что решили положить, отмонтируем и сжимаем (gzip initrd). Создаем директорию (mkdir output/), из которой будем собирать образ диска, в нее кладем директорию isolinux, создаем директорию isolinux/kernel, туда кладем ядро и initrd. По мере надобности кладем файлы/директории в корневую директорию диска.
Для создания загрузочного iso-образа используем команду вроде следующей
mkisofs -o /path/to/live-image.iso -r -V "My Live CD" -v -no-emul-boot -boot-load-size 4 -boot-info-table -b isolinux/isolinux.bin -c isolinux/isolinux.boot /path/to/output

Конечно, вряд ли все получится с первого раза. Чтобы не пороть кучу cd-болванок, образы можно тестировать под эмулятором (qemu).

ЗЫ. Я в курсе, что это "не совсем дебиан-вей". Это, скорее, слако-вей. Но этот способ гораздо более гибкий.

воскресенье, апреля 15, 2007

Чего-то давно не писал...

Вроде и повода не было. Надо бы про asciidoc статью сделать, да руки не доходят...
Через недельку-другую, надеюсь, будет кое-что новенькое ;)
А пока - еду на чемпионат Урала по программированию с 18 по 22-е число.
PS. Кто-нибудь может что-нибудь осмысленное сказать по поводу вот этого: http://portnov84.narod.ru/what.pdf ? Найдено в местной сетке, авторство/источник неизвестны. Есть подозрение, что это плод воображения какого-то тронутого линуксоида.

вторник, февраля 27, 2007

Live IDE

Сочиняю в связи с надоевшим вопросом "а IDE под линукс есть?". Как известно, правильный ответ - "*nix это и есть IDE". В подтверждение - делаю Linux Live CD узкого назначения - Live IDE. Пакеты беру из своего Debian testing/unstable. Софт выбран соответственно назначению лайва:
gvim 7.0 +plugins (taglist, NERDTree, SourceCodeObserver, bufexplorer, marksbrowser, MRU);
gcc, g++ 4.1 с комплектом (всякие gdb, gprof итп);
glade-2;
free pascal 2.0;
ghc6.6 (glasgow haskell compiler);
perl 5.8.8 - само собой;
python2.4;
man-ы, естественно ;)
evince, xpdf и djview - для просмотра документации;
irssi и dillo - чтоб можно было и в инет вылезти;
ну и набор dev-пакетов для библиотек - gtk1/2, glade-2, и тп.
В настоящий момент лайв грузится и работает, но есть десяток мелких багов, думаю за недельку их исправлю. Размер iso - 250Mb (вероятно, будет увеличиваться, но не знаю, насколько). Если кому-то интересно посмотреть - скажите куда можно залить 250Мб ;) Впрочем, в основном я об этом сообщаю не для того, чтоб все бросились сливать мой лайв, а скорее для того, чтоб указать, что создание live-cd узкого назначения - дело несложное, особенно если есть какой-то подходящий лайв, который можно положить в основу. Если б у меня был slackware live cd и работающая слака под боком - наверное, я бы стал делать диск на основе слаки, и заняло бы это у меня день от силы. Но слаки у меня нет, так что я потратил 4 дня на сочинение системы по методу LFS, только не из исходников, а из пакетов debian. Зато узнал много нового ;)
В общем - кому, как мне, приходится заниматься разработкой на компах, на которых нет возможности установить юникс - сочините себе такой лайв из любимого дистрибутива.

UPD. Образ занимает уже 350Мб, зато LiveCD поддерживает аж 10 языков программирования: C, C++, C#(mono), Java(JDK5), FreePascal2.0, Haskell,Ocaml,Perl,Python,Ruby.

среда, января 31, 2007

Тоже присоединяюсь

... к http://ivlad.livejournal.com/184754.html. Цитата:

В связи с т.н. "делом Поносова" (http://ru.wikipedia.org/wiki/Дело_Поносова ) хочу сказать, что если вы - учитель информатики (или любой другой учитель, или представитель администрации школы), который хочет (или, скажем мягче, готов попробовать) использовать Linux в учебном процессе, но не знает, с чего начать, я готов встретиться, рассказать и показать. Более-менее в любые выходные. Безвозмездно, то есть даром. =)
Правда, в совсем любые выходные я не могу (в частности, пол-февраля меня не будет в городе - буду в Перми на студенческой научной школе по программированию с 5-го по 11-е), но уж через e-mail (см. в профиле) меня найти можно. Ну и напомню - живу я в Магнитогорске Челябинской области, выезжаю редко. Если надо - могу до Белорецка съездить.

Также запостил предложение присоединяться на наш LUG (http://lug.mgn.ru), авось, еще кто-нибудь откликнется.

Чтоб не забыть - работающее решение с suspend2, GDM, xlock и пр.

На моем компьютере работаю в основном я, но время от времени - далекие от компьютеров родственники. Я работаю большую часть времени в иксах, но нередко - в "голой консоли". Остальные - только в иксах.

Чего я хочу. Хочу, чтоб при моем логине на четвертой консоли автоматически запускались иксы (на одинадцатой - первые десять у меня рабочие). А остальные юзеры должны входить в систему через GDM, запущенный на двенадцатой консоли. При этом должен работать спящий режим, при выходе из спящего режима должен появляться экран входа GDM (т.е. активной быть двенадцатая консоль) чтобы другой пользователь мог сразу залогиниться, а мои иксы (на 11-ой) должны быть заблокированы (xlock).

Настраиваем suspend в ядре (надежнее применить патч - suspend2). Чтоб оно работало удобно - в /etc/acpi/events/powerbtn пишем:

# We need to react on "button power.*" and "button/power.*" because
# of kernel changes.

event=button[ /]power
action=/usr/local/bin/sswsusp

где /usr/local/bin/sswsusp:

#!/bin/sh

su -c 'xlock -display :0 -planfont "-xos4-terminus-medium-*-normal-*-*-140-*-*-*-*-koi8-r"' portnov &
chvt 12
sudo swapon /dev/hda5
sudo hibernate
sudo swapoff /dev/hda5

swapon/swapoff нужны из-за того, что у меня обычно своп отключен, а suspend2 настроен писать образ памяти в своп. Если своп включен постоянно или suspend2 пишет образ в файл - swapon/swapoff не понадобится. xlock запускается от моего имени. chvt делает активной 12-ю консоль.

Теперь suspend работает по нажатию кнопки Power на системнике.

В конце ~/.zshrc пишем:

case "$(basename `tty`)@$HOST" in
tty4@portnov) runx
logout ;;
esac

где /usr/local/bin/runx:

#!/bin/bash

OPTIONS=$*

for I in $(seq 0 6)
do if [ ! -e /tmp/.X$I-lock ]
then break
fi
done

echo Running X on localhost:$I..
xinit ~/.xinitrc $OPTIONS -- -dpi 100 :$I

Этот скрипт запускает иксы на первом свободном дисплее.

Чтобы GDM нормально работал на 12-ой консоли, надо в /usr/share/gdm/defaults.conf (наверное, можно в более идеологически правильном месте… но не суть) поправить секцию [server-Standard]:

[server-Standard]
name=Standard server
command=/usr/bin/X -dpi 100 vt12 -audit 0
flexible=true

Без этой поправки GDM будет запускаться на седьмой консоли. А так как 7-я консоль у меня рабочая, то клавиатура уже перехвачена getty, и GDM клавиатуры не видит, в результате единственное, что можно сделать - ребутнуть комп из меню gdm.

Теперь выглядит работа так. Выключается компьютер (точнее, переводится в спящий режим) просто по кнопке Power на системнике. При включении показывается экран GDM. Если компьютер включил кто-то из родственников - он тыкает в свою иконку в списке, вводит пароль и работает. Если включил я - нажимаю Ctrl-Alt-F11, созерцаю заставку xlock, ввожу свой пароль - и продолжаю прерванный сеанс.

вторник, января 30, 2007

Еще одна примочка для ion3

Пишем где-нибудь в конфигах:

 function toggle_tabbar(fr)
if WFrame.mode(fr)=="tiled-alt"
then WFrame.set_mode(fr,"tiled")
else WFrame.set_mode(fr,"tiled-alt")
end
end

defbindings("WFrame", {
...
mpress(MOD4.."Control+Button2", "toggle_tabbar(_)"),
...});

Теперь по Ctrl-среднему клику можно включать/выключать отображение строки заголовков окон для фрейма.

понедельник, января 15, 2007

Humm

Посмотрел по "культуре" обсуждение явления блогов. Много думал :)
Резко не понравилось, что постоянно вместо "блог" говорили "жеже".