Поиск по этому блогу

понедельник, 28 декабря 2009 г.

Chrome и представление даты в u64

Информация для размышления по теме.

Заметка №1:
function DateTimeToChromeTime(Time: TDateTime): int64;
var
LocalFileTime: TFileTime;
SystemTime: TSystemTime;
begin
DateTimeToSystemTime(Time, SystemTime);
SystemTimeToFileTime(SystemTime, LocalFileTime);
Result := LocalFileTime.dwHighDateTime;
Result := Result * $100000000;
Result := Result + LocalFileTime.dwLowDateTime;
Result := Result div 10;
end;


Заметка №2:
static inline u64 get_rtc(void)
{
unsigned int hi, lo, hi2;

do {
asm volatile("mfrtcu %0; mfrtcl %1; mfrtcu %2"
: "=r" (hi), "=r" (lo), "=r" (hi2));
} while (hi2 != hi);
return (u64)hi * 1000000000 + lo;
}

суббота, 19 декабря 2009 г.

Потоковое видео средствами ffserver & ffmpeg

Статья взята с habrahabr.ru, ещё не пробовал делать то, что тут написано...


Для организации трансляции нам потребуется:

  • Linux
  • FFmpeg (включает в себя ffserver)
Теория
FFmpeg — это набор свободных библиотек с открытым исходным кодом, которые позволяют записывать, конвертировать и передавать цифровое аудио и видео в различных форматах. Он включает libavcodec, библиотеку кодирования и декодирования аудио и видео и libavformat, библиотеку мультиплексирования и демультиплексирования в медиаконтейнер. Название происходит от названия экспертной группы MPEG и «FF», означающего «fast forward».

© Wikipedia

ffserver идёт в комплекте с ffmpeg и выполняет роль медиа-сервера — получает видеопоток от ffmpeg, который может быть запущен на другой машине, и раздаёт его счастливым пользователям.
Каждый получаемый поток называется Feed’ом (далее будет просто фид). Таких потоков может быть несколько, так же как и отдаваемых (выходных).
FFmpeg у нас будет захватывать видео с веб-камеры или читать из файла.

Практика


Сначала настроим ffserver, чей конфиг лежит в /etc/ffserver.conf:
  1. Port 8090
  2. BindAddress 0.0.0.0
  3. MaxClients 100
  4. MaxBandwidth 20000
  5. NoDaemon
  6. # Фид, надо запомнить feed.ffm, он нам потребуется при запуске ffmpeg
  7. File /tmp/feed.ffm
  8. FileMaxSize 3M
  9. # Ранее объявленный фид
  10. Feed feed.ffm
  11. Format flv
  12. VideoCodec flv
  13. VideoFrameRate 30
  14. VideoBufferSize 80000
  15. VideoBitRate 200
  16. # Качество видео от 1 до 31, 1 == отлично 31 == фи!
  17. VideoQMin 1
  18. VideoQMax 5
  19. # Разрешение, везде должно быть одинаково!
  20. VideoSize 352x288
  21. PreRoll 1
  22. # Если у вас есть микрофон, или вы транслируете видео со звуком, закомментируйте эту строчку
  23. Noaudio
  24. # Флешка test.swf для просмотра трансляции
  25. Feed feed.ffm
  26. # Будет запускаться в Adobe Flash Player
  27. Format swf
  28. VideoCodec flv
  29. VideoFrameRate 30
  30. VideoBufferSize 50000
  31. VideoBitRate 100
  32. VideoQMin 1
  33. VideoQMax 5
  34. # Разрешение, везде должно быть одинаково!
  35. VideoSize 352x288
  36. PreRoll
  37. # Если у вас есть микрофон, или вы транслируете видео со звуком, закомментируйте эту строчку
  38. Noaudio
Пускаем ffserver:
$ ffserver

Пускаем ffmpeg:
$ ffmpeg -s 352x288 -r 30 -f video4linux2 -i /dev/video0 http://localhost:8090/feed.ffm
-s разрешение, указанное в конфиге ffserver, -r количество кадров/секунду, -f формат, -i путь к камере (или к видео-файлу), http://localhost:PORT/FEED это адрес, где ffserver будет ждать наш поток

PS: если выдаст ошибку, то можно попробовать формат v4l (-f video4linux)

Открываем в браузере http://localhost:8090/test.swf и широко улыбаемся:)

Для отправки видео поменяем параметр -i на путь к файлу, уберём -f (ffmpeg сам определит формат файла):
$ ffmpeg -s 352x288 -r 30 -i ~/big_buck_bunny.ogg http://localhost:8090/feed.ffm

Ну а что бы вставить нашу флешку в html-страницу используем следующий код:
src="http://localhost:8090/test.swf" width="550" height="400"></embed>


Q: А можно ли экран потоково отдавать, Х11 должен же иметь какой-то девайс в /dev?
A: Да, можно.
ffmpeg -f x11grab -r 30 -s 352x288 -i :0.0 localhost:8090/feed.ffm
Если будете менять разрешение, то и в конфиге ffserver не забудьте.

Chromium OS

Решил пройтись по инструкции сборки и установки Chromium OS, тут опишу пошагово то, что сейчас собираюсь делать. А вот заработает ли всё это добро и на каком этапе я решу остановиться - это уже второй вопрос ;)

Как обычно всё, что я буду делать - будет под Debian GNU/Linux.

Для начала скачаем исходники, где и как - внимательно читаем инструкцию. Надо сказать, что в debian'овской сборке git'а не нашёлся gclient, а потому пришлось скачать исходники wget'ом и распаковать:
olden@og:~$ mkdir chromiumos
olden@og:~$ cd chromiumos/
olden@og:~/chromiumos$ wget \
http://build.chromium.org/buildbot/archives/chromiumos-0.4.22.8.tar.gz
olden@og:~/chromiumos$ tar xzf chromiumos-0.4.22.8.tar.gz
olden@og:~/chromiumos$ ln -s chromiumos-0.4.22.8/src/ src
О полученной иерархии структуры каталогов можно почитать в документе "Структура директорий".

Переходим в созданной иерархии к исходникам:
olden@og:~/chromiumos$ cd ~/chromiumos/src/scripts
Не забываем установить пакет debootstrap:
olden@og:~/chromiumos/src/scripts$ aptitude -y install debootstrap
Создаём репозиторий Chromium OS:
olden@og:~/chromiumos/src/scripts$ ./make_local_repo.sh
Этот процесс займёт некоторое время...
Дождались? Отлично. Поехали дальше.
Создаём окружение сборки:
olden@og:~/chromiumos/src/scripts$ ./make_chroot.sh
Опять придётся подождать...
Раз, два, три, четыре, пять. Начинаем собирать. Так как в Debian'е в git'е нет gclient'а, а платформа у нас x86 то ничто не мешает воспользоваться вторым методом из указанной выше инструкции:
olden@og:~/chromiumos/src/scripts$ mkdir -p ~/chromiumos/src/build/x86/local_assets
olden@og:~/chromiumos/src/scripts$ cd ~/chromiumos/src/build/x86/local_assets
olden@og:~/chromiumos/src/build/x86/local_assets$ wget \
http://build.chromium.org/buildbot/archives/chromium-chromiumos-r32516.zip \
-O chrome-chromeos.zip
olden@og:~/chromiumos/src/build/x86/local_assets$ cd ~/chromiumos/src/scripts
Ну вот... Всё ближе и ближе подходим к финалу.
Собираем Chromium OS!
Входим в chroot окружение:
olden@og:~/chromiumos/src/scripts$ ./enter_chroot.sh
Mounting chroot environment.
(chroot)olden@og:~/trunk/src/scripts$
Включаем наш аккаунт в сборку, дабы не морочить себе голову с заведением пользователей:
(chroot)olden@og:~/trunk/src/scripts$ ( cd ../platform/pam_google && ./enable_localaccount.sh olden )
Enabling local account.  Remove chromeos_pam_localaccount.h to disable.
Имхо можно так завести нескольких пользователей, но так как у меня только один пользователь, то проверить это не представляется возможным, но всё в наших руках! :)
(chroot)olden@og:~/trunk/src/scripts$ ./set_shared_user_password.sh
Enter password for shared user account: shareduserpassword
Shared user password set in /home/olden/trunk/src/scripts/shared_user_passwd.txt
Собираем пакеты и ядро:
(chroot)olden@og:~/trunk/src/scripts$ ./build_platform_packages.sh
(chroot)olden@og:~/trunk/src/scripts$ ./build_kernel.sh
Это займёт время не на одну чашку кофе...
Ну и самый ответственный момент,- создаём образы:
(chroot)olden@og:~/trunk/src/scripts$ ./build_image.sh
После чего можно приступать к созданию носителей, откуда собираемся загружать нашу Chromium OS.
Но об этом я расскажу в следуюющей заметке...
If you created or changed a DOS partition, /dev/foo7, say, then use dd(1)
to zero the first 512 bytes:  dd if=/dev/zero of=/dev/foo7 bs=512 count=1
(See fdisk(8).)
Done.  Image created in /home/olden/trunk/src/build/images/999.999.35309.183057-a1
To copy to USB keyfob, outside the chroot, do something like:
./image_to_usb.sh --from=~/chromeos/src/build/images/999.999.35309.183057-a1 --to=/dev/sdb
To convert to VMWare image, outside the chroot, do something like:
./image_to_vmware.sh --from=~/chromeos/src/build/images/999.999.35309.183057-a1

вторник, 15 декабря 2009 г.

Upgrading Debian From i386 To amd64

Upgrading Debian From 32-bit To 64-bit

*****WARNING*****

This procedure is, in every possible respect, a bad idea. If it eats your firstborn, please don't come crying to me.
You probably don't need a complete backup of your data to do this safely, but you DO, without question, need boot media that has lots of things on it, like dpkg, for when you fry your system. The expected result of this procedure is a machine on which nothing works, where "nothing" includes "ls".
Seriously; the official documentation specifically declares this procedure to be impossible, which should give you some idea of how bad an idea this is.
*****WARNING*****

Target Audience

Sysadmins that have a 32-bit system that they'd really like to be 64-bit without re-doing all their configuration.
This really is for professional-level sysadmins; I don't suggest that anyone who hasn't seen a Debian box through a few manual broken-apt recoveries with dpkg, and libc upgrades, and kernel upgrades, even consider this.
Smart admins do all the config with cfengine, so this isn't an issue, but I didn't know that when I made this machine. :D

Preparation

Kernel

To make this work, you MUST have a 64-bit kernel installed. Seriously; you can't imagine how badly you'll fuck your system if you follow these steps without a 64-bit kernel.
If "uname -a" doesn't end with "x86_64 GNU/Linux", stop RIGHT NOW and fix it.
If you don't know how to upgrade your kernel, stop reading this. It's not for you.

Statically-Linked Shell And Stuff

To assist possible recovery issues, I strongly suggest apt-getting busybox and running it as a shell ("/bin/busybox ash") in a separate window. Make sure ls and cp and so on work even with PATH=''

List Your Packages

Run dpkg --get-selections and save it to a safe place. You'll want to know what you had installed when apt-get starts trying to make shit up.

Manual Package Downloads

Since both apt-get and dpkg think you're on an i386 machine, 64-bit kernel or no, you're going to have to get yourself some packages.

32-bit Compatibility Libraries

Unless the idea of every binary on your system suddenly ceasing to function sounds like your idea of a good time, you're going to need the 32-bit compatibility libraries for amd64, and you're going to need them before you upgrade libc. Start with the ia32-libs package (i.e. http://packages.debian.org/testing/libs/ia32-libs, but replace "testing" with your actual version) and download the amd64 version of it and ALL its dependencies.
You should now have a directory that looks like this:
ia32-libs_1.19_amd64.deb lib32asound2_1.0.14a-1_amd64.deb lib32gcc1_4.2-20070609-1_amd64.deb lib32ncurses5_5.6-3_amd64.deb lib32stdc++6_4.2-20070609-1_amd64.deb lib32z1_1.2.3-15_amd64.deb libc6-i386_2.5-9_amd64.deb lsb-release_3.1-23.1_all.deb 

dpkg, apt-get, and friends

Grab amd64 versions of dpkg, apt-get, and all their dependencies. You may not end up installing them all manually, but having them around can't hurt. Also grap apt-listchanges and apt-utils.
apt_0.6.46.4-0.1_amd64.deb binutils_2.17cvs20070426-8_amd64.deb bzip2_1.0.3-6_amd64.deb coreutils_5.97-5.3_amd64.deb cpio_2.7-3_amd64.deb debianutils_2.21_amd64.deb dpkg_1.14.4_amd64.deb ed_0.2-20_amd64.deb gcc-4.2-base_4.2-20070609-1_amd64.deb libacl1_2.2.42-1_amd64.deb libasound2_1.0.14a-1_amd64.deb libattr1_2.4.32-1.1_amd64.deb libbz2-1.0_1.0.3-6_amd64.deb libc6_2.5-9_amd64.deb libdb4.4_4.4.20-8_amd64.deb libgcc1_4.2-20070609-1_amd64.deb libgdbm3_1.8.3-3_amd64.deb libgpmg1_1.19.6-25_amd64.deb libncurses5_5.6-3_amd64.deb libreadline5_5.2-3_amd64.deb libselinux1_2.0.15-2_amd64.deb libsepol1_2.0.3-1_amd64.deb libstdc++6_4.2-20070609-1_amd64.deb make_3.81-3_amd64.deb ncurses-bin_5.6-3_amd64.deb patch_2.5.9-4_amd64.deb perl-base_5.8.8-7_amd64.deb perl_5.8.8-7_amd64.deb sed_4.1.5-2_amd64.deb 

The Actual Installation

Please note that order is very important. Read everything before starting. If this order doesn't seem eminently sensible to you, you may want to stop here.

32-bit Compatibility Libraries Install

First is the install of the 32-bit compat libc. This is the fun step:
dpkg --force-depends --force-architecture --force-overwrite -i libc6-i386_2.5-9_amd64.deb 
Yes, you really do need all those. When you're done, /lib/ld-linux.so.2 should be a symlink into /emul/ia32-linux, like this:
lrwxrwxrwx 1 root root 34 Jun 26 08:57 /lib/ld-linux.so.2 -> /emul/ia32-linux/lib/ld-linux.so.2* 
If it's not (it wasn't for me) run:
ln -sf /emul/ia32-linux/lib/ld-linux.so.2 /lib/ld-linux.so.2 
Check that it worked; there should be lots of stuff in /emul/ia32-linux, and:
$ ls -l /usr/lib32 /lib32                         lrwxrwxrwx 1 root root 20 Jun 26 08:56 /lib32 -> /emul/ia32-linux/lib/ lrwxrwxrwx 1 root root 24 Jun 26 08:56 /usr/lib32 -> /emul/ia32-linux/usr/lib/ 
Run "dpkg --force-architecture -i" for all of the other 32-bit compat libs until they're all installed. Should be uneventful.

64-bit libc Install

While this should be uneventful, I mention it separately because if you're going to fuck your system, this is where it'll happen. Run:
dpkg --force-architecture -i libc6_2.5-9_amd64.deb 

dpkg, apt-get, And Friends Install

If you can still "ls" and such in a non-static shell, congratulations. Now "dpkg --force-architecture -i" the packages for apt-get, dpkg, apt-listchanges, and apt-utils. Then keep trying to run each of apt-get, dpkg, apt-listchanges and apt-extracttemplates until they actually run without erroring.
For apt-listchanges, I had to install (in this order):
python2.4-minimal python2.4 python-apt zlib1g libdb-4.4 
That last isn't necessary for getting it to just run, but it was necessary to stop "apt-get -f install" from barfing.
At this point, "dpkg --print-architecture" should say amd64, as should most of "dpkg-architecture" if you have that installed, and "apt-get update" (which you should run) should download a bunch of files to /var/lib/apt/lists that have "amd64" in the name. That's good.

Upsetting apt-get

Run "apt-get update" followed by "apt-get -f install". Keep adding packages until "apt-get -f install" doesn't give you any library or ELFCLASS errors.
Having done so, things will probably still be upset, and you may need to do manual dpkg things. Steps I had to take to make "apt-get -f install" run to completion:
dpkg -i /var/cache/apt/archives/libperl5.8_5.8.8-7_amd64.deb 
Note that apt-get will Make Shit Up during this process. For example, it tried to give me exim4-daemon-light, which I never had installed (I use exim4-daemon-heavy). This is what the dpkg selections list is for. Hence:
apt-get -f install exim4 exim4-daemon-heavy apache2-mpm-prefork console-tools libconsole 
Then there was funkiness because someone broke tex's dependencies. :P

Ugrading Everything Else

Here's the fun part: catching all the things that haven't been gotten yet. First, make a list of remaining i386 packages:
for package in $(grep '[^e]install' dpkg_get_selections.out | awk '{ print $1 }') do     dpkg -s $package | grep -q 'Architecture: i386' && echo $package done >update 
Then open up yourself a copy of the update file (so you can fix the many problems that will occur) and run:
apt-get --reinstall install $(cat update | tr '\012' ' ') 
Keep editing and running until it works.
If you thought the last step downloaded a lot of packages, you may be surprised by the results of this step.
After all of that's done, you might want to check your currently installed packages for further badness:
for package in $(dpkg -l |  grep '^i' | awk '{ print $2 }') do     dpkg -s $package | grep -q 'Architecture: i386' && echo $package done >update2 
With this list, though, you almost certainly want to remove most or all of them: if they weren't installed as a dependency of the other stuff, you almost certainly don't care. Trim local stuff out (like kernel packages) and run:
dpkg -r $(cat update2 | tr '\012' ' ') 
That should pretty much do it.

Сам я не пробовал так апгрейдится... пока не пробовал... за ненадобностью. Но взял "на заметку". Оригинал статьи находится тут http://teddyb.org/~rlpowell/hobbies/debian_arch_up/.

понедельник, 14 декабря 2009 г.

MySQL: Восстановление пароля root

Останавливаем сервер MySQL:
# /usr/local/etc/rc.d/mysql-server.sh stop
Stopping mysql.
Waiting for PIDS: 83119, 83119.

Запускаем mysqld с параметром –skip-grant-tables, указав стартовать от имени пользователя mysql (или от другого непривелигерованного пользователя, но не от root’а.
Теперь запускаем mysql и делаем:
\u mysql
Правим таблицу user, очищая поле с паролем для root@localhost. Всё, пароля для root'а больше нет. Не забываем сказать flush privileges и перезапустить сервер mysql. Далее заходим под пользователем root@localhost и устанавливаем ему такой пароль какой нам необходим.

Как собрать бинарный deb пакет: подробное HowTo

Сегодня я расскажу на абстрактном примере как правильно создать *.deb пакет для Ubuntu/Debian. Пакет мы будем делать бинарный. Пакеты, компилирующие бинарники из исходников здесь не рассматриваются: осилив изложенные ниже знания, в дальнейшем по готовым примерам можно понять суть и действовать по аналогии :)

В статье не будет никакой лишней возни «вручную»: формат пакета эволюционировал в достаточно простую, а главное — логичную структуру, и всё делается буквально на коленке, с применением пары специализированных утилит.

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

Для тех, кто не хочет вдаваться в мощную систему установки софта в Linux, рекомендую посетить сайт проги CheckInstall: она автоматически создаёт deb-пакет из команды «make install» ;) А мы вместе с любопытными —

Источники


Информация надёргана из многих мест, но вот два основных:

В статье подробно изложены основы создания пакетов, достаточные для получения достаточно мощного управления установкой приложений. Более продвинутые фичи опущены, но предложены прямые ссылки на документацию для интересующихся.
Статья не является копией или переводом какой-либо документации: это — коллекция знаний, валявшихся в виде заметок, а теперь оформленная в виде статьи. Для ясности везде есть примеры, разъяснения на пальцах, найденные мной удобные фичи и некоторые типичные ошибки, которые можно совершить по незнанию.

Подготовка



Зачем это всё?

Да, CheckInstall умеет создавать рабочий пакет, но он не поддерживает все вкусности, на которые способны deb пакеты :) А именно:
  • Скрипты, выполняющиеся до, после и вместо установки пакета :)
  • Автоматическое управление конфигурационными файлами: пакет не позволит затереть старые конфиги новыми без спроса
  • Работа с шаблонами: возможность задавать пользователю вопросы при установке (!!!)
  • Изменение файлов других пакетов


Что потребуется

Конечно, для создания полноценного пакета хватит архиваторов tar, gz, ar, но можно исключить лишнюю возню, и воспользоваться инструментами, созданными для облегчения жизни :)
Ставим:
$ sudo apt-get install dpkg debconf debhelper lintian

Что мы будем делать

Для примера будет рассмотрен некий скрипт /usr/bin/super.sh. Не важно что внутри, главное — как он появится на правильном месте :)

Подготовка папки

В домашнем каталоге (или где удобно) создаём папку, в которой будут лежать все файлы будущего пакета: mkdir ~/supersh. Далее будем называть её корень пакета.
В корне пакета создаём папку «debian». Эта папка содержит управляющую генерацией пакета информацию, и не копируется на диск при установке пакета.
Также корневая папка пакета содержит будущий «корень диска»: при установке пакета все файлы (кроме папки «debian») распаковываются в корень /. поэтому наш скрипт должен лежать по такому пути, относительно корня пакета: «usr/bin/super.sh»
Белым по чёрному:
mkdir -p ~/supersh/debian # управляющая папка
mkdir -p ~/supersh/usr/bin # путь к скрипту
cp super.sh ~/supersh/usr/bin/ # копируем наш скрипт в нужное место

В итоге имеем:
supersh/debian/
supersh/usr/
supersh/usr/bin/
supersh/usr/bin/super.sh


Создание пакета: debian/*


Как я уже сказал, папка debian содержит файлы, используемые при установке. Здесь я опишу (с примерами) каждый файл.
Для создания полноценного пакета достаточно контрольного файла «control», все остальные используются либо для прикрепления текстовой информации (changelog, лицензия), либо для управления расширенными возможностями установки приложений.
Из описанных ниже файлов в папке debian/* выбираем необходимые, и заполняем согласно инструкции :)
В наше примере реально используется только обязательный debian/control.

debian/control: Основная информация

control — центральный файл пакета, описывающего все основные свойства. Файл — текстовый, состоящий из пар «Атрибут: значение». Можно использовать комментарии: символ "#" в начале строки (возможность была добавлена в версии dpkg >= 1.10.11, надеяться на комментарии не стоит :).
В таблице приведены все поля, определённые для контрольного файла. Обязательные поля выделены жирным: без них пакет не будет считаться составленным верно.
Атрибут Описание Примеры
— основные —
Package: Имя пакета: [a-zA-Z0-9-] — только латиница, цифры, и дефис. Имя используется при установке: apt-get install Package: supersh
Version: Версия пакета (и проги внутри). Используется для определения «обновлять ли».
Формат принят такой: <версия_программы>-<версия_пакета>.
Рекомендую всегда указывать версию пакета: при изменении структуры пакета цифра увеличивается на единичку.
Допустимые символы достаточно вольные: можно использовать дату и буквы. Примеры смотрите сегодня в своём репозитории :)
Version: 1.0-1
Version: 2009.12.12-1
Provides Имя приложения (возможно, виртуальное), регистрируемое в системе в результате установки этого пакета.
Используется редко: в основном, если нужно изменить имя пакета, или если более одного пакета предлагают одинаковый функционал. Например, пакеты Apache и nginx предоставляют возможность демона httpd: Provides: httpd
Вы наверняка сталкивались с ошибкой при попытке установки: «is a virtual package». Это оно и есть :)
Provides: supersh
Maintainer Имя и почта мэйнтейнера пакета: человека, который «дебианизировал» приложение.
Формат произвольный, но принято имя
Maintainer: o_O Tync
Architecture Архитектура процессора, для которой предназначен пакет.
Допустимые значения: i386, amd64, all, source
all используется для скриптов: они же портативные, верно? :)
source используется для компилируемых пакетов с исходниками
Architecture: all
Section Определяет задачу, для которой приложение обычно используется (группа приложений).
Возможные значения: admin, base, comm, contrib, devel, doc, editors, electronics, embedded, games, gnome, graphics, hamradio, interpreters, kde, libs, libdevel, mail, math, misc, net, news, non-free, oldlibs, otherosfs, perl, python, science, shells, sound, tex, text, utils, web, x11
Section: misc
Description Описание пакета.
Описание состоит из двух частей: короткое описание (70 символов) на той же строке, и длинное описание на последующих строках, начинающихся с пробела.
В расширенном описании все переводы строки игнорируются. Для вставки \n используется одиночная точка.
Description: Short.
␣Long
␣goes here.
␣.
␣New line.
— связи и зависимости —
Depends Список пакетов через запятую, которые требуются для установки этого пакета.
После имени пакета можно в круглых скобках указать ограничение на версию, используя операторы: <<, =, >>, <=, >=. Если оператор не указан — используется >=
Depends: dpkg, libz (>= 1.2.3), jpeg (= 6b), png (<>
Pre-Depends Список пакетов, которые требуются в процессе установки этого пакета.
Эти зависимости могут потребоваться для скриптов установки пакета: например, пакет flash-installer требует wget
Можно использовать ограничения на версию (см. Depends).
Pre-Depends: wget (>= 1.0)
Conflicts Список пакетов, которые не могут быть установлены одновременно с этим.
Установка не удастся, если хоть один из перечисленных пакетов уже будет установлен.
Conflicts: crapscript
Replaces Список пакетов, файлы которых модифицируются этим пакетом.
Требуется в случае создания «пакета-патча», изменяющего что-либо: в противном случае при замене файлов чужого пакета возникнет ошибка при установке. У меня, например, такой пакет патчит UT2004 и убирает звук наводящейся ракетницы :)
Replaces: ut2004
Recommends Список пакетов, рекомендуемых к установке
Эти пакеты не обязательны, но обычно используются вместе с текущим
Recommends: superplatform
Suggests Список пакетов, предлагаемых к установке.
Эти пакеты не обязательны, но с ними прога работает ещё лучше :) По идее, менеджер пакетов должен предлагать установить их.
Suggests: supersh-modules
Build-Depends (Только для Architecture: source)
Список пакетов, требуемых для компиляции исходников.
То же, что и Depends, но логически отделено.
Build-Depends: cmake
— экстра —
Installed-Size Размер файлов пакета в килобайтах.
Просто цифра, округлённая до ближайшего целого. Используется менеджером пакетов для определения суммарного требуемого объёма на диске.
Installed-Size: 3
Priority Приоритет пакета: насколько он важен в системе
Возможные значения: extra, optional, standard, important, required (такие пакеты не удаляются вообще!).
Priority: optional
Esssential Если установить этот атрибут в значение «yes», пакет нельзя будет удалить. Esssential: yes
Origin Строка: откуда получены программы в пакете. Обычно используется URL сайта автора, почта или имя. Origin: brain
X-Source Полная ссылка на *.tar.gz архив с исходниками X-Source: .../*.tgz

Да, вот такие солидные возможности у контрольного файла :)
А в нашем примере он выглядит так:
Package: supersh
Version: 1.0-1
Section: misc
Architecture: all
Depends: bash, sed (>= 3.02-8)
Maintainer: o_O Tync
Description: Super Shell script
␣A super example script.
␣.
␣It does nothing :)


debian/copyright: © / лицензия

Текст лицензии. Файл не обязателен, но лучше подчеркнуть своё авторство ;)

debian/changelog: история изменений

Changelog в специальном формате: используется dpkg для получения номера версии, ревизии, дистрибутива и важности пакета. Лучше посмотреть в официальной документации ;) а я лишь приведу пример:
supersh (1.0-1) stable; urgency=medium

* Testing.

-- o_O Tync Sun, 13 Dec 2009 00:11:46 +0300


debian/rules: правила компиляции

Используется для управления компиляцией пакета: это когда Architeture: source :)
См. официальную документацию

debian/conffiles: список файлов конфигурации

Обычно пакеты содержат болванки конфигурационных файлов, например, размещаемых в /etc. Очевидно, что если конфиг в пакете обновляется, пользователь потеряет свой отредактированный конфиг. Эта проблема легко решается использованием папок типа «config.d», содержимое которых включается в основной конфиг, заменяя собой повторяющиеся опции.
Файл «debian/conffiles» позволяет решить проблему иначе: он содержит список файлов конфигурации (по одному на строке). Если в текущей версии пакета один из этих файлов обновляется, то пользователь получает предупреждение о конфликте версий конфигов, и может выбрать: удалить, заменить, или сделать merge.
С этой ситуацией наверняка сталкивался каждый линуксоид, копавшийся в конфигах :) А ноги растут отсюда.
На каждой строке должен быть полный абсолютный путь до каждого конфига. Например:
/etc/supersh/init.conf
/etc/supersh/actions.conf


debian/dirs: список папок для создания

Список абсолютных путей к папкам, которые требуются программе, но по каким-либо причинам не создаются. По одной на строке. Например:
/var/log/supersh
/var/lib/supersh

Удобно использовать для создания нескольких пустых папок.

debian/menu: создание пунктов меню

Хитрый файл для создания пунктов меню. У меня он так и не заработал :) Складывается ощущение, что его содержимое используется либо в необычных оконных менеджерах, либо в каком-то консольном меню… или же использовалось ранее и было забыто :)
Пример:
?package(supersh):needs="text" section="Applications/Programming" title="Super Shell script" command="/usr/bin/super.sh"
TODO: узнать зачем нужно. Об этом написано в man5 menufile, честно говоря я не вникал :)

debian/md5sums: контрольные суммы файлов

Используется для проверки целостности пакета. Важный файл.
Заполняется так (cwd=корень пакета):
$ md5deep -r usr > debian/md5sums

debian/watch: мониторинг сайта, откуда была скачана прога

Функция полезна, если Вы мэйнтейните от нескольких десятков пакетов, и уследить за всеми обновлениями сложно.
Файл содержит инструкции для программ uscan и uupdate. Используя эту возможность, можно следить за сайтом, откуда были получены исходники пакета, и обеспечивать контроль качества дистрибутива в целом.
Пример:
# Site Directory Pattern Version script
ftp.obsession.se /gentoo gentoo-(.*)\.tar\.gz debian uupdate

Лучше почитайте официальную документацию, такие мощные вещи нечастно требуются простым смертным :)

Скриптинг


Мы подошли к самому интересному: встраиванию скриптов в deb пакеты. Скрипты позволяют управлять установкой, переустановкой и удалением пакета, выполняя действия, которые нельзя сделать простым копированием файлов в правильные места. Это может быть скачивание дополнительных файлов (как это делает flash-installer), изменение существующих, а также — вывод интерактивных (GUI или ncurses) диалогов, позволяющих пользователю сконфигурировать пакет под себя: например, mysql спрашивает какой установить пароль для root.
Все скрипты выполняются от пользователя root (а как же ещё :). Также они получают аргументы (которые обрабатывать не обязательно), конкретизирующие на каком именно этапе находится установка. Подробнее об этом здесь.

debian/(preinst|postinst|config|prerm|postrm): скрипты установки

Всего можно создать до пяти скриптов в одном пакете:
Скрипт Назначение
debian/preinst Выполняется перед установкой пакета: он может подготовить что-либо для успешной установки
debian/postinst Выполняется сразу после установки пакета: он настраивает установленный пакет так, чтоб он был готов к работе
debian/prerm Выполняется непосредственно перед удалением пакета: обычно этот скрипт подчищает установочные пути пакета так, чтоб ничего лишнего не завалялось :)
debian/postrm Выполняется сразу после удаления пакета: вычищает остатки
debian/config Выполняется после установки пакета на стадии конфигурирования: это — единственный скрипт, в котором разрешено вести диалог с пользователем. Это делается при помощи dh_input и файла debian/templates

Обратите внимание, что ошибки, возникающие в этих скриптах никак не логируются: ничего интереснее кода возврата скрипта нигде не сохраняется, и логирование необходимо делать вручную! Пользователи одного моего пакета терпели неудачу при установке на Linux Mint, и не было даже возможности попросить у них лог ошибок (которого нету) чтобы выдебагать причину :)
Рекомендую использовать в начале каждого скрипта следующую болванку: она будет сохранять в syslog все возникающие ошибки.
#!/bin/bash
set -e # fail on any error
set -u # treat unset variables as errors

# ======[ Trap Errors ]======#
set -E # let shell functions inherit ERR trap

# Trap non-normal exit signals:
# 1/HUP, 2/INT, 3/QUIT, 15/TERM, ERR
trap err_handler 1 2 3 15 ERR
function err_handler {
local exit_status=${1:-$?}
logger -s -p "syslog.err" -t "ootync.deb" "[${package}] *.deb script '$0' error code $exit_status (line $BASH_LINENO: '$BASH_COMMAND')"
exit $exit_status
}

... Ваш код установочного скрипта ...

exit 0

WARNING: болванка пока не тестировалась широко, проверьте лишний раз! На невозможность отладки наткнулся совсем недавно :)

debian/templates: шаблоны для диалогов

Как уже было сказано, в скрипте debian/config можно задавать пользователю вопросы: ввести строку, выбрать один из вариантов, поставить галочку,… Этим занимается «библиотека» bash функций debhelper пакета debconf, умеющая кроме этого ещё массу полезных вещей. Здесь их не рассматриваю :)
Файл debian/templates содержит данные, используемые при выводе диалоговых окон (GUI или ncurses). Файл содержит блоки, разделённые пустой строкой. Каждый блок определяет ресурсы, используемые в одном конкретном диалоговом окне.
Шапка для всех типов диалогов стандартная:
Template: supersh/template-name
Type: string
Default: Default-value
Description: Dialog-title
␣Dialog-text

Template — уникальный (в пределах одного пакета) идентификатор шаблона. Если в скрипте нужно вызвать определённый диалог — используется именно это имя.
Type — тип шаблона. Определены такие типы: string, password, boolean, select, multiselect, text, note, error.
Default-value — значение по умолчанию: пользователь может просто согласиться с ним.
Description — как и в контрольном файле, состоит из двух полей: короткое описание, и длинный текст. Первое — это заголовок «окна», второе — более развёрнутое описание того, что требуется от пользователя. Рекомендуется не использовать слов вроде «введите», а сразу суть: «Приветствие скрипта», «Точка монтирования»,…

Тип Описание шаблона
string Приглашение на ввод текстовой строки
password Приглашение на ввод пароля.
Для этого типа шаблона нет значения Default по понятным причинам :)
boolean Галочка :) Имеет строковое значение «true» или «false»
select Возможность выбора одного из нескольких вариантов.
Варианты предлагаются в дополнительном атрибуте шаблона:
Choices: yes, no, maybe
multiselect Возможность выбора нескольких вариантов галочками.
Варианты предлагаются в дополнительном атрибуте шаблона:
Choices: sex, drugs, rock-n-roll
text Выводит на экран текст: некоторая не очень важная информация
note Выводит на экран текст: важная информация
error Выводит на экран текст: очень важная информация, критическая.

Для шаблонов text, note, error также нет значения Default, так как они лишь отображают информацию :)
Поиграемся с следующим шаблоном:
Template: supersh/greeting
Type: string
Description: Welcome message
␣The message you wish the script to welcome you with.
Default: Greetings, my master!


Основы использования debconf и debhelper

Это лишь работоспособные наброски. В оригинале почитать о шаблонах и работе с ними можно здесь: man 7 debconf-devel :)
Чтобы использовать шаблоны в своём скрипте настройки debian/config, необходимо сначала подключить функции debhelper:
. /usr/share/debconf/confmodule
Эти функции доступны в пакете debconf, не забудьте включить его в зависимости!
Примитивный пример использования:
#!/bin/bash -e

. /usr/share/debconf/confmodule

# Запрос
db_input medium "supersh/greeting" || true # инициализация
db_go || true # вывод запроса на экран

# Обработка ответа
db_get "supersh/greeting" # Получение значения в переменную $RET
greeting="$RET"
echo "$greeting" > /etc/supersh/greeting.txt

Здесь уже кроется неприятная засада: обратите внимание, что функции db_input передаётся приоритет диалога medium. Для debconf можно установить минимальный приоритет: диалоги с приоритетом ниже которого не отображаются, а берётся значение по умолчанию (Default шаблона)! Чтобы этого ТОЧНО не случилось — используем приоритет critical :) Кроме того, при установке из GUI порог вывода вопросов выше, и многие из них не отображаются вообще.
Возможные приоритеты: low — всегда используется default, medium — дефаулт обычно вполне подходит, high — дефаулт нежелателен, critical — внимание пользователя жизненно важно.
|| true используется чтобы скрипт не помер из-за ключика "-e" переданного bash.
В этом скрипте тоже рекомендуется использовать ту болванку для отлова ошибок, иначе с распространяемым пакетом могут возникнуть проблемы при отладке :)
Все тонкости использования debconf (функции, способы, параметры, коды ошибок) описаны в достаточно многословном мане: man debconf-devel.

Собираем пакет! :)


Ура! Все нужные файлы созданы, лежат по нужным папочкам. Теперь пора собирать пакет :)
Первое, что нужно сделать — это рекурсивно выставить всем файлам в корне пакета пользователя и группу root:root (или другие, если потребуется):
$ sudo chown -R root:root .
Проверьте права доступа на все файлы! При установке пакета права будет сохранены. В нашем примере, скрипт должен иметь бит выполнимости.
Потом выходим на папку назад, чтоб было видно корневую папку пакета, и пакет создаётся лёгким пинком сам:
$ dpkg-deb --build supersh
Созданный пакет необходимо переименовать, чтобы он соответствовал порядку именования *.deb пакетов: <имя пакета>_<версия>_<архитектура>.deb
$ mv supersh.deb supersh_1.0-1_all.deb
Всё, пакет готов!

Автоматическая проверка пакета

Существует утилита lintian, позволяющая проверить пакет и выявить типичные ошибки в его структуре. Делается это так:
$ lintian supersh_1.0-1_all.deb

Установка пакета

$ sudo dpkg -i supersh_1.0-1_all.deb

Создаём собственный репозиторий пакетов


Теперь у нас есть собственный пакет. Когда их будет несколько, и тем более — с зависимостями, окажется, что намного удобнее быстренько поднять собственный локальный микро-репозиторий, и включить его в список источников менеджера пакетов :) Здесь я опишу быстрый HowTo «как создать свой репозиторий». Идею будет легко развить, почитывая соответствующую документацию :)
Сперва установим помощника:
$ sudo apt-get install reprepro

Описание будущего репозитория

Центр репозитория — его описание. Главное в нём — список компонент репозитория. Мы создадим компоненты «soft» и «games».
Выберите папку для будущего репозитория. Все действия производятся из её корня.
Создаём файл conf/distributions следующего содержания:
Description: my local repository
Origin: Ubuntu
Suite: testing
AlsoAcceptFor: unstable experimental
Codename: karmic
Version: 5.0
Architectures: i386 amd64 source
Components: soft games
UDebComponents: soft games

В нашем деле создания простого репозитория все поля не играют принципиальной роли, и используются лишь для визуального определения «что есть что» :)

Создание репозитория

Репозиторий описан! Теперь сгенерируем болванку на основе описания. Команды выполняются в корне репозитория:
$ reprepro export
$ reprepro createsymlinks

И добавим готовый репозиторий в /etc/apt/sources.list:
deb file:///path/to/repo/ karmic soft games
Этот репозиторий можно также расшарить при помощи веб-сервера.

Управление пакетами в репозитории

В корень репозитория кладём *.deb файлы для добавления, и добавляем их в компоненту soft дистрибутива karmic:
reprepro -C soft includedeb karmic *.deb
теперь пакеты доступны из менеджера пакетов :)
Удаление пакетов:
reprepro -C soft remove karmic supersh

Финиш


В статье рассмотрены материалы по созданию deb пакетов. Акцент сделан на моментах, для которых в сети нет достаточно наглядного описания. Надеюсь, что моя попытка изложить просто и понятно не провалилась :)
Домашнее задание :)) — вполне неплохо документированные вещи, которые легко найти в man'ах и статьях:
  • Создание source пакетов, компилирующих исходники: на примере Zabbix об этом отлично рассказал хабраюзер mahoro в своей статье
  • Debconf, debhelper в конфигурационных скриптах: читаем маны по debconf-devel и debhelper. Они также позволяют создать скелет пакета командой dh_make.
  • Продвинутые способы создания документации в пакетах: файлы debian/docs, debian/manpage.*
  • Создание init скриптов
  • Управление заданиями cron
  • Подписывание репозитория ключём gpg


UPD: ICD2 подсказывает, что есть GUIшная прога для создания пакетов: GiftWrap.

Cheers! :)

P.S. В статье наверняка встречаются неточности и ошибки. Давайте причешем её вместе! :)


Оригинал статьи читать тут habrahabr.ru

1. в ... болванках скриптов не хватает проверки на то, какое действие собственно происходит. В случае с postinst-скриптом это вроде ничего, но в prerm это уже совсем не лишнее. Правильные шаблоны есть в dh_make.
2. В майском номере Linux Format была подобная статья:
Кому интересно:
pic.ipicture.ru/uploads/091213/1gN9WxSV1F.jpg
pic.ipicture.ru/uploads/091213/6ccT4iL9Zu.jpg

пятница, 11 декабря 2009 г.

Запуск виртуальной машины в VirtualBox без GUI

VirtualBoxИногда возникает необходимость запустить виртуальную машину на хосте без иксов. Я расскажу о том как это сделать, имея доступ к хостовой системе только по ssh + rdp (Remote Desktop Protocol). процесс я буду описывать для OC Ubuntu 9.10 в качестве хоста.

Начнем с установки VirtualBox.

Предварительно нужно установить пакет dkms (Dynamic Kernel Module Support Framework):

sudo apt-get install dkms

На сайте VirtualBox-а предлагается 2 варианта: прописать источник пакетов (deb download.virtualbox.org/virtualbox/debian karmic non-free) в /etc/apt/sources.list либо скачать и установить deb-пакет. Когда я прописал источник и сделал sudo apt-get install virtualbox-3.1 у меня потянулась куча пакетов из зависимостей (в том числе и каких-то для GUI интерфейса). Поэтому лучше скачать deb-пакет. Качаем, устанавливаем:

sudo dpkg -i virtualbox-3.1_3.1.0-55467_Ubuntu_karmic_i386.deb

возможно тут также потребуются зависимости (какие-то библиотеки для парсинга xml, в котором хранятся конфиги, но их значительно меньше чем в первом случае). Если установка не завершилась из-за зависимостей, можно просто сделать

sudo apt-get -f install

при этом установятся зависимости и VirtualBox

ок. VirtualBox поставили. Начнем создавать guest-машины.

создаем саму машину:

VBoxManage createvm --name ubuntu --ostype Ubuntu --register
(name — имя машины, ostype — тип системы. полный список всех типов можно узнать командой VBoxManage list ostypes)

настраиваем

VBoxManage modifyvm ubuntu --memory 512 --floppy disabled --audio none --nic1 bridged --bridgeadapter1 eth0 --vram 4 --accelerate3d off --boot1 disk --acpi on --cableconnected1 on --usb off --vrdp on --vrdpport 3390

тут с большего все понятно. в качестве типа сети можно указать также NAT (--nic1 nat). также включаем rdp

создаем hdd диск для виртуальной машины:

VBoxManage createhd --filename /home/user/vbox/ubuntu.vdi --size 20000 --register

добавляем контроллер IDE в нашу машину

VBoxManage storagectl ubuntu --name "IDE Controller" --add ide

цепляем на IDE0 созданный ранее hdd

VBoxManage storageattach ubuntu --storagectl "IDE Controller" --port 0 --device 0 --type hdd --medium /home/user/vbox/ubuntu.vdi

на IDE1 цепляем установочный образ

VBoxManage storageattach ubuntu --storagectl "IDE Controller" --port 1 --device 0 --type dvddrive --medium /home/user/vbox/iso/ubuntu-9.10-alternate-i386.iso

говорим машине грузиться с диска

VBoxManage modifyvm ubuntu --boot1 dvd

запускаем машину

nohup VBoxHeadless --startvm ubuntu &

для того чтобы поставить базовую систему воспользуемся rdp-клиентом (у меня KDE, в стандартную поставку входит KRDC). коннектимся на хостовую машину на порт, который указали в настройках (--vrdpport 3390), ставим систему, делаем sudo apt-get install openssh-server. теперь на виртуальную машину можно попасть по ssh

останавливаем виртуальную машину

VBoxManage controlvm ubuntu acpipowerbutton
через acpi

или более жестко

VBoxManage controlvm ubuntu poweroff

говорим грузится с hdd

VBoxManage modifyvm ubuntu --boot1 disk

можно также отцепить установочный диск

VBoxManage storageattach ubuntu --storagectl "IDE Controller" --port 1 --device 0 --medium none

и снова запускаем

nohup VBoxHeadless --startvm ubuntu &

еще полезные команды:

VBoxManage list runningvms
просмотр всех запущенных машин

VBoxManage showvminfo ubuntu
просмотр информации о виртуальной машине

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


Источник данной статьи habrahabr.ru

пятница, 4 декабря 2009 г.

Быстрый Flash в Ubuntu

Это просто калька поста с хабрахабра. Сам не проверял, но взял на заметку.


Пришлось недавно решать проблему с низкой скоростью проигрывания Flash в любом браузере на последней версии плагина от Adobe.
Было перепробовано множество вариантов решения, в конечном итоге были выявлены основные составлящие успеха.



Итак:
1) Лучше всего, по наблюдениям, Flash работает в Ubuntu 9.04.
2) Естественно, нужно убедиться, что установлена последняя версия драйвера видеокарты. Ставим Flash плагин:
sudo apt-get install flashplugin-nonfree
3) Создаём папку /etc/adobe, а в ней — файл /etc/adobe/mms.cfg. В файл вписываем следующую строку:
OverrideGPUValidation=true
Это заставит Flash использовать аппаратное ускорение графики.
4) Правим /etc/init.d/ondemand — вписываем
for CPU_THRESHOLD in /sys/devices/system/cpu/cpu*/cpufreq/ondemand/up_threshold
do
[ -f $CPU_THRESHOLD ] || continue
echo -n 40 > $CPU_THRESHOLD
done

После аналогичного блока
for CPUFREQ in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
do
[ -f $CPUFREQ ] || continue
echo -n ondemand > $CPUFREQ
done

Это заставит ОС не понижать частоту процессора при загрузке большей, чем 40%.

понедельник, 16 ноября 2009 г.

I/O Scheduler. Выбираем оптимальный.

Что нам понадобится для достижения цели?
Во-первых, установленный hdparm:
# aptitude install hdparm

Во-вторых, маленький скрипт:
# DISC="sda"; \
cat /sys/block/$DISC/queue/scheduler; \
for T in noop anticipatory deadline cfq; do \
echo $T > /sys/block/$DISC/queue/scheduler; \
cat /sys/block/$DISC/queue/scheduler; \
sync && /sbin/hdparm -tT /dev/$DISC && echo "----"; \
sleep 15; \
done
Если диск не sda, то соответствующим образом правим кусок кода с объявлением:
DISC="sda";
Запускаем и получаем подобный результат:
noop anticipatory deadline [cfq]
[noop] anticipatory deadline cfq

/dev/sda:
Timing cached reads:   1690 MB in  2.00 seconds = 844.83 MB/sec
Timing buffered disk reads:  216 MB in  3.00 seconds =  71.91 MB/sec
----
noop [anticipatory] deadline cfq

/dev/sda:
Timing cached reads:   1612 MB in  2.00 seconds = 805.98 MB/sec
Timing buffered disk reads:  208 MB in  3.03 seconds =  68.67 MB/sec
----
noop anticipatory [deadline] cfq

/dev/sda:
Timing cached reads:   1644 MB in  2.00 seconds = 822.10 MB/sec
Timing buffered disk reads:  206 MB in  3.02 seconds =  68.20 MB/sec
----
noop anticipatory deadline [cfq]

/dev/sda:
Timing cached reads:   1728 MB in  2.00 seconds = 864.06 MB/sec
Timing buffered disk reads:  214 MB in  3.01 seconds =  71.05 MB/sec
----
Первая строка чисто информационная, в ней мы просто видем тот scheduler который используется на текущий момент времени и всегда можем вернуться к нему. Затем следуют секции тестирования. Наиболее оптимальные результат выбираем вручную, он соответствует наибольшей скорости чтения мегабайт в секунду. Короче занимаемся округлениями :)
Новое значение, можно установить прямо в grub'е, изменив значение elevator=...
Далее:
# update-grub
# reboot

ps: Спасибо Сергею (snkua[at]jabber.ru) за подсказанные идеи :)
Ссылки по теме:
http://www.redhat.com/magazine/008jun05/features/schedulers/
http://www.redhat.com/promo/summit/2008/downloads/pdf/Thursday/Sanjay_Rao.pdf
http://sfdoccentral.symantec.com/sf/5.0/linux/html/sf_rac_install/sfrac_prep_install27.html

понедельник, 9 ноября 2009 г.

Мои изыскания по конвертированию avi в mp4 для проигрывания фильма на HTC Android G1 (гуглофоне) - 3 серия (заключительная)

Ура! Ура! Ура! Я его таки сделал! Вот что значит - хорошенько отдохнуть и уже на свежую голову перечитать весь материал заново.
Собственно я не знаю, будет ли работать это решение если не проделать все предыдущие "махинации" (1, 2), но факт остаётся фактом - я конвертанул видео в нужные андроиду формат и теперь есть и видео, и звук.
Для этого потребовалось всего лишь внимательней прочитать статью "Converting Videos For The Android T-Mobile G1 Phone With Linux", а если быть более точным то комментарии к ней. Там есть ссылка на уже готовый и вполне работоспособный код. У себя я его обозвал android_ffmpeg_converter, сказал ему chmod +x и вуаля! Вот, собственно, содержимое скрипта:
#!/bin/bash
# AUTHOR: M@sprackle.org
# PURPOSE: To convert one file or many files to Android format and size.
# LIMITATIONS: Get the Cancel button working in Zenity pop-up
# INSTALL: Place this script in "~/.gnome2/nautilus-scripts/Android"
# and set to execute `chmod +x ~/.gnome2/nautilus-scripts/Android`
# USE: Just right click on a file or folder that contains files you
# would like to convert to an Android format.  This was converted from
# my already used iPhone script.
#
# Where do you want all of these files to be saved?
# You should NOT have to edit below this line
SAVESPOT="~username/tmp/movie"
#
# Same as above I just wanted a single place to find my files
if [ ! -d $SAVESPOT ]; then
mkdir $SAVESPOT
fi
# Lets see if this was a single file or a Directory
if [ -f "$1" ]; then
#
# Let's cut up the name so it's not example.avi.mp4
NEWNAME=`echo "$1" | awk -F. '{print $1}'`
#
# Run the command - I found all these flags on some website.
# So far they're good.
ffmpeg -i "$1" -s 480x256 -vcodec mpeg4 -acodec libfaac -ac 1 -ar 16000 -r 13 -ab 32000 -aspect 3:2 -padtop 32 -padbottom 32 $SAVESPOT/"$NEWNAME".mp4 </dev/null
#
# Ta-Da
else
#
# I placed the files in a new Directory to make them easy to find
cd "$1"
#
# Lets find the files we want to work with.
find . -type f -print0 | while read -d $'\0' file; do
#
# Lets check to see that this is a video file first
file "$file" | egrep "video:"
#
# If the egrep returns a "0" it found the phrase "video:" then continue
if [ $? != "0" ]; then
exit 1
fi
# Let's cut up the name so it's not example.avi.mp4
NEWNAME=`echo "$file" | cut -c 3- | awk -F. '{print $1}'`
#
zenity --text "Processing $NEWNAME" --info &
# Run the command - I found all these flags on some website.
#  So far they're good.
ffmpeg -i "$file" -s 480x256 -vcodec mpeg4 -acodec libfaac -ac 1 -ar 16000 -r 13 -ab 32000 -aspect 3:2 -padtop 32 -padbottom 32 $SAVESPOT/"$NEWNAME".mp4 </dev/null
#
zenity --text "$NEWNAME Complete" --info &
#
# Ta Da
done
#
fi
и всё! Как говориться, приятного просмотра :)
Возможно, и даже наверняка, потребуется внести изменения в переменную SAVESPOT и указать в ней директорию куда надо сохранять итоговое сконвертированное видео. Параметры-же у этого скрипта более чем простые. Параметр один - имя конвертируемого файла.
Счастливого просмотра :)

четверг, 5 ноября 2009 г.

Мои изыскания по конвертированию avi в mp4 для проигрывания фильма на HTC Android G1 (гуглофоне) - 2 серия

Как я уже написал в предыдущем посте, конвертирование через mencoder потерпело фиаско. Я услышал звук, но совершенно не увидел видео.
Слегка подумав я всё-таки решил вершуться к идее сборки ffmpeg. В прошлом посте я упомянул о заморачивании сборки ffmpeg, но не упомянул, что я ею таки занимался. Другой вопрос, что я собирал сборку из Debian'овский исходников, полученных через apt-get:
apt-get source ffmpeg
Так как собирал я его ещё до менкодера и до сборки h264 то, наверное, вполне естественно, что полученная утилита ни в какую не хотела конвертировать видео в нужный мне формат. Так как мысль эта меня посетила только что, а я уже успел собрать ffmpeg из исходников svn, то чем бы закончился такой эксперимент сказать, к сожалению, сейчас не могу. Однако опишу мою недолгую борьбу со сборкой ffmpeg из svn. Хотя по большому-то счёту и описывать нечего, так как весь процесс описан в статье "How-To Build FFmpeg on Debian Squeeze". Пошагово:
$ svn checkout svn://svn.ffmpeg.org/ffmpeg/trunk ffmpeg
$ cd ffmpeg
$ ./configure \
--enable-gpl \
--enable-postproc \
--enable-pthreads \
--enable-libfaac \
--enable-libfaad \
--enable-libmp3lame \
--enable-libtheora \
--enable-libx264 \
--enable-shared \
--enable-nonfree \
--enable-libvorbis \
--enable-libgsm \
--enable-libspeex \
--enable-libschroedinger \
--enable-libdirac \
--enable-avfilter \
--enable-avfilter-lavf \
--enable-libdc1394 \
--enable-libopenjpeg \
--enable-libopencore-amrnb \
--enable-libopencore-amrwb \
--enable-version3 | \
tee ../ffmpeg-configure.txt && \
make && \
sudo make install && \
make tools/qt-faststart && \
sudo ldconfig
Как видим, ничего сложного. Единственное, что надо отметить, так это то, что в /etc/ld.so.conf или его include должен быть описан каталог /usr/local/lib.

На текущий момент времени запущена переконвертация их xvid в mpeg4 следующей строкой:
$ /usr/local/bin/ffmpeg -y -i исходный_файл.avi -pass 1 -vcodec libx264 -acodec aac -vpre fastfirstpass -r 23.976 -aspect 3:2 -s 480x320 -b 480k -bt 480k -ab 96k -sameq файл_назначения.mp4

ps: Как и в предыдущем посте: ничего определённого о положительном или отрицательном результате пока сказать не могу, но о результатах обязательно сообщу дополнительно :)

ps2: Печально... Очень печально... Теперь было 10 секунд видео, но без звука... А затем ошибка - невозможно воспроизвести... Brain on! Думаем дальше! ;)

Мои изыскания по конвертированию avi в mp4 для проигрывания фильма на HTC Android G1 (гуглофоне)

Сразуже скажу, что в своей "борьбе" я руководствовался прочтением следующих материалов. Правда не все сразу они были найдены, а следовательно, будь по другому, я возможно намного раньше получил бы необходимые мне результаты.
Сначала я хотел конвертировать через ffmpeg и заморачиваться с его сборкой, но менкодер показался как-то ближе и привычней, как, собственно, и м-плеер в состав которого он входит. Но!...

И вот тут начинается самое интересное.
Можно добавить:
deb http://www.debian-multimedia.org squeeze main
и установить пакеты mplayer и mencoder, а можно собрать всё самому и попробовать установить. Чем я руководствовался когда начал сборку пакета mplayer с поддержкой кодеков h264 и xvid? Ну... Во-первых я как-то не сразу сообразил, что mencoder, в дебиановском "стандартном" и мультимедийном репозитории, не входит в состав mplayer'а. Во-вторых, ffmpeg, даже будучи установленным из мультимедийного репозитория, поддержку h264 не осуществлял. Конечно-же можно попробовать установить mencoder и попытаться осуществить конвертацию им, но... как-то лениво, ибо уже был собрат собственный mplayer_1.0svn_i386.deb, с поддержкой h264 и xvid, процессом создания которого я и собираюсь тут поделиться.
Тут я буду рассказывать всё "гладко" и, по мере возможности, последовательно хотя, поверьте, все эти ступени и шаги по ним, разбирательства с ними, заняло куда больше времени чем я тут об этом собираюсь рассказать.
Чтобы упростить себе жизнь, всё-таки внесём, для начала, вышеуказанный источник в репозиторий. Обновим свою систему as is и двинемся дальше.
Для нормальной сборки поддерджки в менкодере кодека h264 необходимо наличие в системе пакетов libfaac0 и libfaad0, плюс dev'ы libfaac-dev и libfaad-dev. Ставим их.
Затем собираем библиотеки и пакеты для поддержки h264 и xvid.
$ wget http://downloads.xvid.org/downloads/xvidcore-1.2.1.tar.gz
$ tar xzpf xvidcore-1.2.1.tar.gz
$ cd xvidcore
$ dpkg-buildpackage
$ cd ..
$ sudo dpkg -i ./libxvidcore4_1.2.1-1_i386.deb  ./libxvidcore4-dev_1.2.1-1_i386.deb
Собственно пакет поддержки xvid у нас уже есть и установлен. В дальнейшем можно будет просто устанавливать собранный deb.
Поехали дальше.
$ git clone git://git.videolan.org/x264.git
$ cd x264
$ ./configure && make && sudo make install sudo make install
$ cd ..
Ну вот, у нас есть поддержка h264. Для тех кто в бронепоезде и всё ещё не знает что такое git - просто установите пакет git-core.
Теперь перейдём к сборке. Сайт проекта www.mplayerhq.hu. На мой взгляд он нисколько не изменился с 90-х. А вот сам новый mplayer удивил. Последний раз, когда я его собирал руками, в нём не было поддержки сборки через dpkg-buildpackage - теперь есть. И это приятно. Далее всё очень просто:
$ svn checkout svn://svn.mplayerhq.hu/mplayer/trunk mplayer
$ cd mplayer
$ DEB_BUILD_OPTIONS="--enable-gui --win32codecsdir=/usr/local/lib/codecs --enable-menu --enable-linux-devfs --enable-dynamic-plugins --codecsdir=/usr/local/lib/codecs" dpkg-buildpackage
Опции для configure передаются через переменную DEB_BUILD_OPTIONS. "Форточные" кодеки у меня лежат в /usr/local/lib/codecs, качаются так-же с сайта проекта. Внимательно следим чтобы была поддержка faac ибо... После успешной сборки у нас появляется mplayer_1.0svn_i386.deb который мы и устанавливаем через dpkg.
Естественно если нам нужно чтобы mplayer поддерживал что-то ещё, то ставим соответствующие lib'ы и dev'ы к ним, чтобы на этапе конфигурации они смогли быть найдены.
На этом этап сборки можно считать законченным.

Теперь о конвертировании. Как и было указано в ссылках выше, вызываем менкодер следующим образом:
$ mencoder исходное_имя_файл.avi -o имя_файла_назначения.mp4 \
-vf dsize=480:352:2,scale=-8:-8,harddup \
-oac faac \
-faacopts mpeg=4:object=2:raw:br=128 \
-of lavf \
-lavfopts format=mp4 \
-ovc x264 \
-sws 9 \
-x264encopts nocabac:level_idc=30:bframes=0:bitrate=512:threads=auto:turbo=1:global_header:threads=auto:subq=5:frameref=6:partitions=all:trellis=1:chroma_me:me=umh

Запускаем и ждём результата. Закачиваем на наш любимый гуглофон. Пытаемся смотреть видео :)

ps: Собственно на данном этапе видео у меня как раз таки конвертируется, так что о 100% положительном результате сказать не могу. Могу лишь сказать, что оно таки начало конвертироваться, в отличии от вчерашнего дня ;) Об окончательных результатах "борьбы" сообщу дополнительно, убрав этот ps. ;)

ps2: Печально... Очень печально... Хоть и конвертанулось видео... Хоть я его нормально посмотрел на компе плеером... А вот гуглофон выдал только тихий-тихий звук, но совершенно без видео. Что-ж, буду копать дальше. Ожидайте продолжение серии статей по изысканиям ;)

пятница, 23 октября 2009 г.

Настройка проприетарных драйверов ATI под Debian, Linux 2.6.27.4, ATI driver installer 8.10, Debian/Lenny

Это просто копия моей-же статьи с linuxforum.ru.


Хочу поделиться с сообществом своим опытом в настройке проприетарных драйверов от ATI. Все дело в том, что на момент начала моей "борьбы" с этими драйверами более-менее современного описания найдено не было, а те рецепты которые были найдены, в частности, на этом форуме не дали полного и вразумительного ответа. Поэтому и родилась мысль поделиться опытом. Как оказалось - все более чем просто! Надо лишь знать в какую сторону копать.
Итак, поехали...

Карточка у меня оказалась достаточно древняя (это рабочий десктоп, как ни как):
$ lspci | grep ATI
01:00.0 VGA compatible controller: ATI Technologies Inc RV370 [Sapphire X550 Silent]
01:00.1 Display controller: ATI Technologies Inc RV370 secondary [Sapphire X550 Silent]
А сайта AMD ATI были взяты последние драйвера для моей карточки ati-driver-installer-8-10-x86.x86_64.run.

Предчувствие меня не обмануло и, как и ожидалось, простой запуск на исполнение послал меня, выдав ошибку при компиляции. С этого момента начались мытарства в поисках нужного ответа, часть которого была найдена тут mczim-debian.blogspot.com и, да простит меня русскоязычная часть форумчан, тут www.debian-administration.org.ua. Скажу сразу, что хоть и в первом, и во втором случае эти рецепты ранее были признаны рабочими, но в моём случае они к успеху не привели. Но тем не менее - это очень правильные рецепты.

Теперь по-порядку, к чему свелись мои действия из этих двух рецептов:
$ chmod +x ati-driver-installer-8-10-x86.x86_64.run

Получим список поддерживаемых платформ для сборки драйверов:
$ ./ati-driver-installer-8-10-x86.x86_64.run --listpkg

Мне повезло, так как Debian/lenny в этом списке присутствовал. Ура. Следующий шаг тоже особых усилий не требует:
$ sudo ./ati-driver-installer-8-10-x86.x86_64.run --buildpkg Debian/lenny

Ждем. После завершения у нас появляются пакеты:
fglrx-amdcccle_8.542-1_i386.deb
fglrx-driver_8.542-1_i386.deb
fglrx-driver-dev_8.542-1_i386.deb
fglrx-kernel-src_8.542-1_i386.deb

Отлично! Устанавливаем их при помощи dpkg -i один за другим, начиная с fglrx-driver_8.542-1_i386.deb. Внимание! Если в процессе установки fglrx-driver произошла ошибка - ничего страшного, все фиксится очень просто:
$ sudo aptitude reinstall libgl1-mesa-glx

и повторяем попытку установки.

А вот теперь самое интересное. При попытке собрать пакет с драйвером fglrx под свою платформу мы получаем "отбой", так как во время компиляции возникает ошибка. Усиленные поиски в Сети привели к находке патча для файла firegl_public.c, правда для его наложения на текущую версию драйверов пришлось поработать напильником, так как по смещениям нужные строки не совпадали... ну как обычно... По-порядку. Diff'ничек с правильными смещениями для вышеуказанных дров:
--- firegl_public.c.orig 2008-10-31 14:36:11.000000000 +0200
+++ firegl_public.c 2008-10-31 15:18:02.000000000 +0200
@@ -200,6 +200,12 @@
#define preempt_enable()
#endif

+/* Since 2.6.27 smp_call_function doesn't have a nonatomic/retry argument */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
+#define SMP_CALL_FUNCTION(func, info, retry, wait) smp_call_function(func, info, wait)
+#else
+#define SMP_CALL_FUNCTION(func, info, retry, wait) smp_call_function(func, info, retry, wait)
+#endif
// ============================================================
/* globals */

@@ -251,7 +257,7 @@
const char BUILD_KERNEL_HAS_MODVERSIONS_CLEARED;
#endif

-#ifdef __SMP__
+#ifdef CONFIG_SMP
const unsigned long __ke_SMP_State = 1;
const char BUILD_KERNEL_HAS_SMP_SET;
#else
@@ -2348,8 +2354,8 @@
{
/*Some kernel developer removed the export of symbol "flush_tlb_page" on 2.6.25 x86_64 SMP kernel.
Define a simple version here.*/
-#if defined(__x86_64__) && defined(__SMP__) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25))
- on_each_cpu(KCL_flush_tlb_one, &va, 1, 1);
+#if defined(__x86_64__) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25))
+ on_each_cpu(KCL_flush_tlb_one, &va, 1);
#else
flush_tlb_page(vma, va);
#endif
@@ -2766,7 +2772,7 @@

/*****************************************************************************/

-#ifdef __SMP__
+#ifdef CONFIG_SMP
static atomic_t cpus_waiting;

static void deferred_flush(void* contextp)
@@ -2782,13 +2788,13 @@
while (atomic_read(&cpus_waiting) > 0)
barrier();
}
-#endif /* __SMP__ */
+#endif /* CONFIG_SMP */

int ATI_API_CALL __ke_flush_cache(void)
{
-#ifdef __SMP__
+#ifdef CONFIG_SMP
/* write back invalidate all other CPUs (exported by kernel) */
- if (smp_call_function(deferred_flush, NULL, 1, 0) != 0)
+ if (SMP_CALL_FUNCTION(deferred_flush, NULL, 1, 0) != 0)
panic("timed out waiting for the other CPUs!\n");

/* invalidate this CPU */
@@ -2802,7 +2808,7 @@

while (atomic_read(&cpus_waiting) > 0)
barrier();
-#else /* !__SMP__ */
+#else /* !CONFIG_SMP */
#if defined(__i386__) || defined(__x86_64__)
asm volatile ("wbinvd":::"memory");
#elif defined(__alpha__) || defined(__sparc__)
@@ -2810,7 +2816,7 @@
#else
#error "Please define flush_cache for your architecture."
#endif
-#endif /* !__SMP__ */
+#endif /* !CONFIG_SMP */

//for kernel 2.6.25, tlb_flush has been included when calling set_pages_*.
#if LINUX_VERSION_CODE 

После установки пакета fglrx-kernel-src_8.542-1_i386.deb в /usr/src появляется файл fglrx.tar.bz2, вот его куда-нибудь в /tmp распаковываем, накладываем выше приведённый патч, пакуем назад с таким же именем и кладем назад в /usr/src.

Конечно-же подразумевается, что ранее ядро мы собирали вручную.
Очень кратко о сборке ядра:
# make menuconfig
# make-kpkg clean
# fakeroot make-kpkg --initrd --revision=custom.1.0 kernel_image
# fakeroot make-kpkg --initrd --revision=custom.1.0 kernel_headers
# fakeroot make-kpkg --initrd --revision=custom.1.0 kernel_source
# dpkg -i ../linux-image_версия-ядра_ревизия-ядра_i386.deb


Вот. Тут бы и сказочке конец, тут бы и собрать дровишки и установить их. Но... Конечно же драйвера соберутся и установка пройдёт гладко, вплоть до перезагрузки, так как на момент загрузки fglrx будет выдана ошибка, которую можно будет лицезреть по dmesg. Поэтому ещё немного терпения.

Это хорошо, что ядро у нас собрано установлено и работает. Придётся его... собирать опять, перед этим слегка пропатчив init_task.c в пути исходников ядра arch/x86/kernel.
--- arch/x86/kernel/init_task.c.orig 2008-11-02 09:11:46.000000000 +0200
+++ arch/x86/kernel/init_task.c 2008-11-01 11:16:34.000000000 +0200
@@ -14,7 +14,8 @@
static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
struct mm_struct init_mm = INIT_MM(init_mm);
-EXPORT_UNUSED_SYMBOL(init_mm); /* will be removed in 2.6.26 */
+//EXPORT_UNUSED_SYMBOL(init_mm); /* will be removed in 2.6.26 */
+EXPORT_SYMBOL(init_mm); /* will be removed in 2.6.26 */

/*
* Initial thread structure.

Вот, отлично, теперь пересобираем и устанавливаем ядро. Перезагружаемся.
Используя
$ sudo m-a
или
module-assistant prepare,update
module-assistant build,install fglrx
depmod -a
собираем пакет fglrx-kernel-версия-ядра_8.542-1+ревизия-ядра_i386.deb и устанавливаем его.

Ну и напоследок:
$ sudo aticonfig --initial
$ sudo aticonfig --overlay-type=Xv
$ sudo reboot

Собственно всё! Перезагружаемся и наслаждаемся!

Проверка:
$ fglrxinfo
display: :0.0 screen: 0
OpenGL vendor string: ATI Technologies Inc.
OpenGL renderer string: Radeon X300/X550/X1050 Series
OpenGL version string: 2.1.8087 Release
$ glxinfo | grep render
direct rendering: Yes
OpenGL renderer string: Radeon X300/X550/X1050 Series
$ glxgears -info
GL_RENDERER = Radeon X300/X550/X1050 Series
GL_VERSION = 2.1.8087 Release
GL_VENDOR = ATI Technologies Inc.
GL_EXTENSIONS = GL_AMD_performance_monitor GL_ARB_depth_texture
GL_ARB_draw_buffers GL_ARB_fragment_program
GL_ARB_fragment_shader GL_ARB_half_float_pixel
GL_ARB_half_float_vertex GL_ARB_multisample GL_ARB_multitexture
GL_ARB_occlusion_query GL_ARB_pixel_buffer_object
GL_ARB_point_parameters GL_ARB_point_sprite GL_ARB_shader_objects
GL_ARB_shading_language_100 GL_ARB_shadow GL_ARB_shadow_ambient
GL_ARB_texture_border_clamp GL_ARB_texture_compression
GL_ARB_texture_cube_map GL_ARB_texture_env_add
GL_ARB_texture_env_combine GL_ARB_texture_env_crossbar
GL_ARB_texture_env_dot3 GL_ARB_texture_float
GL_ARB_texture_mirrored_repeat GL_ARB_texture_non_power_of_two
GL_ARB_texture_rectangle GL_ARB_transpose_matrix GL_ARB_vertex_buffer_object
GL_ARB_vertex_program GL_ARB_vertex_shader
GL_ARB_window_pos GL_ATI_draw_buffers
GL_ATI_envmap_bumpmap GL_ATI_fragment_shader GL_ATI_meminfo
GL_ATI_separate_stencil GL_ATI_texture_env_combine3
GL_ATI_texture_float GL_EXT_abgr GL_EXT_bgra GL_EXT_blend_color
GL_EXT_blend_equation_separate GL_EXT_blend_func_separate
GL_EXT_blend_minmax GL_EXT_blend_subtract
GL_EXT_compiled_vertex_array GL_EXT_copy_texture
GL_EXT_draw_range_elements GL_EXT_fog_coord GL_EXT_framebuffer_blit
GL_EXT_framebuffer_multisample GL_EXT_framebuffer_object
GL_EXT_gpu_program_parameters GL_EXT_multi_draw_arrays
GL_EXT_packed_depth_stencil GL_EXT_packed_pixels
GL_EXT_point_parameters GL_EXT_rescale_normal GL_EXT_secondary_color
GL_EXT_separate_specular_color GL_EXT_shadow_funcs
GL_EXT_stencil_wrap GL_EXT_subtexture GL_EXT_texgen_reflection
GL_EXT_texture3D GL_EXT_texture_compression_s3tc
GL_EXT_texture_cube_map GL_EXT_texture_edge_clamp
GL_EXT_texture_env_add GL_EXT_texture_env_combine
GL_EXT_texture_env_dot3 GL_EXT_texture_filter_anisotropic
GL_EXT_texture_lod_bias GL_EXT_texture_mirror_clamp
GL_EXT_texture_object GL_EXT_texture_rectangle GL_EXT_texture_sRGB
GL_EXT_vertex_array GL_KTX_buffer_region GL_NV_blend_square
GL_NV_texgen_reflection GL_SGIS_generate_mipmap
GL_SGIS_texture_edge_clamp GL_SGIS_texture_lod GL_WIN_swap_hint WGL_EXT_swap_control
7295 frames in 5.0 seconds = 1458.984 FPS
7239 frames in 5.0 seconds = 1447.743 FPS
7328 frames in 5.0 seconds = 1465.518 FPS
7364 frames in 5.0 seconds = 1472.800 FPS
7346 frames in 5.0 seconds = 1469.199 FPS
$ fgl_glxgears
Using GLX_SGIX_pbuffer
1597 frames in 5.0 seconds = 319.400 FPS
2008 frames in 5.0 seconds = 401.600 FPS
1997 frames in 5.0 seconds = 399.400 FPS
2008 frames in 5.0 seconds = 401.600 FPS
2267 frames in 5.0 seconds = 453.400 FPS
2589 frames in 5.0 seconds = 517.800 FPS

Ps:
Отдельное спасибо хочется сказать Вадику Пилипенко aka Pil$on, который
"заставил" меня совершить подвиг по установке ATI'шных дров вместо
покупки nVidia и который поделился идеей патча ядра, на предмет замены
EXPORT_UNUSED_SYMBOL на EXPORT_SYMBOL (уж не знаю, где он нашёл это
решение и чем это чревато, но... - работает)

Как получить modeline

Немного о настройке X'ов. В секции Monitor каждый может заметить загадочные строки ModeLine, но не каждый может ответить на вопрос откуда берутся эти параметры.
Приоткроем завесу над этой тайной. Вот два метода позволяющий получить значения ModeLine.
$ aptitude install read-edid
$ aptitude install videogen
В первом пакете нас интересуют утилиты get-edid и parse-edid - первая из них получает, а вторая интерпретирует значение спецификации монитора используя VESA VBE DDC протокол.
videogen - это программа генерации Modelines для XFree86 сервера.
Теперь как пользоваться первой и второй из них.

Для начала рассмотрим пакет read-edid.
$ sudo get-edid | parse-edid
parse-edid: parse-edid version 2.0.0
get-edid: get-edid version 2.0.0

Performing real mode VBE call
Interrupt 0x10 ax=0x4f00 bx=0x0 cx=0x0
Function supported
Call successful

VBE version 200
VBE string at 0x2110 "ATI RV370"

VBE/DDC service about to be called
Report DDC capabilities

Performing real mode VBE call
Interrupt 0x10 ax=0x4f15 bx=0x0 cx=0x0
Function supported
Call successful

Monitor and video card combination does not support DDC1 transfers
Monitor and video card combination supports DDC2 transfers
0 seconds per 128 byte EDID block transfer
Screen is not blanked during DDC transfer

Reading next EDID block

VBE/DDC service about to be called
Read EDID

Performing real mode VBE call
Interrupt 0x10 ax=0x4f15 bx=0x1 cx=0x0
Function supported
Call successful

parse-edid: EDID checksum passed.

# EDID version 1 revision 3
Section "Monitor"
# Block type: 2:0 3:fd
# Block type: 2:0 3:fc
Identifier "SyncMaster"
VendorName "SAM"
ModelName "SyncMaster"
# Block type: 2:0 3:fd
HorizSync 30-81
VertRefresh 56-75
# Max dot clock (video bandwidth) 140 MHz
# Block type: 2:0 3:fc
# Block type: 2:0 3:ff
# DPMS capabilities: Active off:yes  Suspend:no  Standby:no

Mode  "1280x1024" # vfreq 60.020Hz, hfreq 63.981kHz
DotClock 108.000000
HTimings 1280 1328 1440 1688
VTimings 1024 1025 1028 1066
Flags "+HSync" "+VSync"
EndMode
# Block type: 2:0 3:fd
# Block type: 2:0 3:fc
# Block type: 2:0 3:ff
EndSection
Тут наиболее интересная для решения поставленной нами задачи информация содержится практически в самом конце. Для составления ModeLine нас интересуют строки начинающиеся с Mode, DotClock, HTimings, VTimings и Flags:
Mode  "1280x1024" # vfreq 60.020Hz, hfreq 63.981kHz
DotClock 108.000000
HTimings 1280 1328 1440 1688
VTimings 1024 1025 1028 1066
Flags "+HSync" "+VSync"
Итоговая ModeLine:
  • ModeLine "1280x1024" 108.00 1280 1328 1440 1688 1024 1025 1028 1066 +HSync +VSync

Перейдём ко второму методу, пакету videogen.
Тут всё значительно проще. Просто вызываем videogen с параметрами режима, максимального значения dot clock rate, максимальной частотой горизонтальной развёртки и максимальной частотой вертикальной развёртки:
$ videogen -m=1280x1024 -mdc=108 -mhf=81 -mvf=75
и получаем результирующую строку ModeLine:
  • Modeline "1280x1024" 108.00 1280 1320 1368 1640 1024 1026 1030 1078  # 108 MHz, 65.9 kHz, 61.1 Hz

Следует обратить внимание, что полученные двумя различными способами строки ModeLine слегка отличаются. Собственно это и не удивительно, если первый вариант считывает необходимые параметры с самого монитора то второй является простым калькулятором для ModeLine.

Собственно на этом всё ;)

вторник, 20 октября 2009 г.

Установка скорости последовательного порта

Понадобилось тут последовательный порт на 2400 залочить.
Помню, что раньше через setserial всё успешно лочил, но было это давно, в далёких 90-х. Тем не менее решил попробовать, на что и получил нелицеприятное сообщение:
# setserial /dev/ttyS0 uart 16550A port 0x03f8 irq 4 baud_base 2400 spd_normal skip_test
Cannot set serial info: Invalid argument

При этом значения выше (9600 и т.д.) воспринимались вполне корректно:
# setserial /dev/ttyS0 uart 16550A port 0x03f8 irq 4 baud_base 9600 spd_normal skip_test
#
Выход был найден. Оказывается всё можно сделать и без использования дополнительного setserial:
# stty 2400 < /dev/ttyS0
Проверяем:
# stty -F /dev/ttyS0 | grep speed
speed 2400 baud; line = 0;
Чудеса да и только ;)

Установка BFS (Brain Fuck Scheduler) в ядро Linux.

Недавно Вадик Пилипенко (Pilson) поделился ссылкой на статью "Установка BFS (Brain Fuck Scheduler) на примере Ubuntu Linux 9.04". Но так как у меня не Ubuntu, а Debian то возникли некоторые нюансы при компиляции и установке...
Собственно по-порядку. Патч к своему ядру я взял там-же где указано в вышеприведённой статье, на http://ck.kolivas.org/patches/bfs/. На мои исходники к ядру 2.6.30.4 патч лёг в общем-то без проблем, за исключением того, что не пропатчился Makefile, но выяснилось, что как-раз его-то можно было и не патчить, так как единственное, что менялось, так это EXTRAVERSION. Поэтому было решено оставить его as is, но поменял NAME на BFS Powered.
При конфигурировании ядра не забыть, и это обязательно, изменить следующие настройки:
  • Processor type and features -> Timer frequency устанавливаем в 1000Hz
  • Processor type and features -> Tickless System (Dynamic Ticks) отключаем
  • Processor type and features -> Preemption Model -> Preemptible kernel (Low latency desktop)
Дальше как по инструкции "Сборка и установка ядра под Debian":
fakeroot make-kpkg \
--revision=og.$( date +%Y%m%d.%H%M%S ) \
--initrd \
--append-to-version=-bfs304 \
kernel_image \
kernel_headers \
kernel_manual \
kernel_doc \
kernel_source
Сразу-же замечу, что мне лениво заморачиваться с порядковыми номерами ревизий, а оттого использовал подстановку текущей даты и времени, а так-же, в отличии от инструкции по сборке ядра, "искуственно" добавлена версия, которая затем добавиться в имя deb-пакетов. Ну и порядок инструкция для make-kpkg задан сразу пачкой, а не по отдельности.
После того как ядро собралось:
# dpkg -i linux-image-2.6.31.4-bfs304_og.20091020.102119_i386.deb
Выбор ранее не выбранного пакета linux-image-2.6.31.4-bfs304.
(Чтение базы данных ... на данный момент установлено 282999 файлов и каталогов.)
Распаковывается пакет linux-image-2.6.31.4-bfs304 (из файла linux-image-2.6.31.4-bfs304_og.20091020.102119_i386.deb)...
Done.
Настраивается пакет linux-image-2.6.31.4-bfs304 (og.20091020.102119) ...
Running depmod.
Examining /etc/kernel/postinst.d.
run-parts: executing /etc/kernel/postinst.d/initramfs-tools 2.6.31.4-bfs304 /boot/vmlinuz-2.6.31.4-bfs304
Тут ждала первая неожиданность - не собрался /boot/initrd.img-2.6.31.4-bfs304. Поэтому его сборку, по подсказке Pilson'а, выполнил отдельно:
# mkinitramfs -o /boot/initrd.img-2.6.31.4-bfs304 2.6.31.4-bfs304
параметрами переданы имя собираемого initrd-файла и версия ядра.
Собственно ядро установилось, initrd собрался.
Что-ж, пошёл на:
# reboot
Если возникнут проблемы - напишу отдельно ;)

четверг, 15 октября 2009 г.

Сборка и установка ядра под Debian

Зададимся целью: собрать "универсальное" ядро, чтобы потом им делиться с друзьями, знакомыми, да и самим спокойно портировать куда угодно ;)

Для начала ставим пакеты fakeroot, kernel-package, libncurses5-dev:
aptitude install fakeroot kernel-package libncurses5-dev
Все зависимости будут подтянуты автоматом...
Затем берём нужный архив с kernel.org и сливаем и распаковываем его в /usr/src (берём для примера ядро 2.6.31.4).
$ cd /usr/src
$ sudo -s
# wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.31.4.tar.bz2
# tar xjf linux-2.6.31.4.tar.bz2
# if [ -d linux ]; then rm linux; fi; ln -s linux-2.6.31.4 linux
# cd linux
Тут есть один момент. Так как у нас уже есть рабочее ядро в установленной системе то, если не хотим выставлять все галочки в конфигурации нового ядра с нуля, берём готовый config либо из /boot либо из /proc:
# cp /boot/config-$( uname -r ) .config
# zcat /proc/config.gz > .config
В итоге имеем предварительную заготовку к конфигурации нашего нового ядра.

Теперь конфигурируем ядро под специфические для нас цели, либо добавляем опции для новых модулей, либо... Одним словом - творчество:
# make menuconfig
Тут инетресно будет ответить, что если мы сразу-же выйдем из меню, то можем увидеть что-то подобное этому:
.config:903:warning: symbol value 'm' invalid for RFKILL_INPUT
.config:2920:warning: symbol value 'm' invalid for DRAGONRISE_FF
.config:2937:warning: symbol value 'm' invalid for GREENASIA_FF
.config:2939:warning: symbol value 'm' invalid for THRUSTMASTER_FF
.config:2940:warning: symbol value 'm' invalid for ZEROPLUS_FF
имеет смысл найти эти опции при конфигурировании нового ядра и посмотреть что да к чему... Кстати, если кому интересно под X-ами заниматься конфигурированием, то может сделать так:
# make xconfig
Важно! Не забываем сказать "Kernel module loader" в "Loadable module support", так как возможны варианты. Ну всё. Пимпочки поотмечали, кнопочки понажимали, из окошек вышли, новый конфиг сохранили, теперь приступим к сборке. Для начала сделаем:
# make-kpkg clean
Если до этого сборка не производилась, то увидим что-то наподобие этого:
exec make kpkg_version=12.021 -f /usr/share/kernel-package/ruleset/minimal.mk clean
====== making target minimal_clean [new prereqs: ]======
This is kernel package version 12.021.
test ! -f .config || cp -pf .config config.precious
test ! -e stamp-building || rm -f stamp-building
test ! -f Makefile || \
make    ARCH=i386 distclean
make[1]: Entering directory `/usr/src/linux-2.6.31.4'
CLEAN   scripts/basic
CLEAN   scripts/kconfig
CLEAN   include/config
CLEAN   .config .config.old include/linux/autoconf.h
make[1]: Leaving directory `/usr/src/linux-2.6.31.4'
test ! -f config.precious || mv -f config.precious .config
rm -f modules/modversions.h modules/ksyms.ver scripts/cramfs/cramfsck scripts/cramfs/mkcramfs
Ну, а теперь, собственно, собираем ядро:
# fakeroot make-kpkg --initrd --revision=og.091015.00 kernel_image
og.091015.00 - означает лишь ревизию нашей сборки. Может быть любой - у кого насколько фантазии хватит :) После того как предыдущая команда нормально выполнится, можно также дать такой "джентельменский набор":
# fakeroot make-kpkg --initrd --revision=og.091015.00 kernel_headers
# fakeroot make-kpkg --initrd --revision=og.091015.00 kernel_manual
# fakeroot make-kpkg --initrd --revision=og.091015.00 kernel_doc
# fakeroot make-kpkg --initrd --revision=og.091015.00 kernel_source
После этого получим набор из следующих deb-пакетов:
  • linux-image-2.6.31.4_og.091015.00_i386.deb
  • linux-headers-2.6.31.4_og.091015.00_i386.deb
  • linux-manual-2.6.31.4_og.091015.00_all.deb
  • linux-doc-2.6.31.4_og.091015.00_all.deb
  • linux-source-2.6.31.4_og.091015.00_all.deb

располагаться они будут в /usr/src.
Нам остаётся их только установить через dpkg:
# cd /usr/src
# dpkg -i ./linux-image-2.6.31.4_og.091015.00_i386.deb
и т.д.
Конфигурация к GRUB'у должна будет выполниться автоматически, равно как и собраться initrd.
Финальный шаг:
# reboot

понедельник, 28 сентября 2009 г.

Cisco - два провайдера и ip sla / rtr

Итак, рассмотрим простой пример. Есть клиент и имеется два провайдера (аплинка). Автономной системы для построения BGP-peer'ов у нас нет, а работать, при падении одного каналов как-то надо. При этом у нас есть внутренний клиент нашей сети который работает не как все, а с точностью до наоборот. В нормальной (оба канала работают) этот клиент всё-равно ходит через резервный канал (Dialer1), в то время как все работают по основному (Dialer0) и переключается он на основной канал только в том случае если резервный(!) падает (бывает и такое).
Одно из возможных решений может выглядеть так:
interface Vlan1
ip address 192.168.0.1 255.255.255.0
ip policy route-map tracking
!
route-map tracking permit 10
match ip address 1
set default interface Dialer1 Dialer0
!
route-map tracking permit 20
match ip address 2
set default interface Dialer0 Dialer1
!
access-list 1 permit 192.168.0.101
access-list 2 deny   192.168.0.101
access-list 2 permit 192.168.0.0 0.0.0.255

Да, такая конструкция работает, но есть один недостаток, причём достаточно не очевидный.
Может наблюдаться такая ситуация, что и статус и протокол могут находиться в состоянии Up, а канал может не работать. Тогда эта конструкция ничем не поможет.
Что-же делать? Всё очень просто: использовать возможности sla.
Что нам для этого надо? Просто надо переписать route-map tracking и написать правила для sla.
interface Vlan1
ip address 192.168.0.1 255.255.255.0
ip policy route-map tracking
!
track 123 rtr 1 reachability
!
track 124 rtr 2 reachability
!
ip sla 1
icmp-echo 195.5.5.208 source-interface Dialer1
timeout 2000
threshold 2
frequency 3
ip sla schedule 1 life forever start-time now
ip sla 2
icmp-echo 193.34.140.1 source-interface Dialer0
timeout 2000
threshold 2
frequency 3
ip sla schedule 2 life forever start-time now
!
route-map tracking permit 100
match ip address 1
set ip next-hop verify-availability 195.5.5.208 10 track 123
set ip next-hop verify-availability 193.34.140.1 20 track 124
!
route-map tracking permit 120
match ip address 2
set ip next-hop verify-availability 193.34.140.1 10 track 124
set ip next-hop verify-availability 195.5.5.208 20 track 123
!
route-map tracking permit 200
set ip next-hop verify-availability 195.5.5.208 10 track 123
set ip next-hop verify-availability 193.34.140.1 20 track 124
!
access-list 1 permit 192.168.0.101
access-list 2 deny   192.168.0.101
access-list 2 permit 192.168.0.0 0.0.0.255

Собственно всё банально просто. ;)
route-map перестаёт отрабатывать для пакета свои правила после того как обнаружит первое-же совпадение. Поэтому, собственно, порядок определения сиквенсов важен!
Теперь если мы взглянем на состояние интерфейсов то увидим:
#sh ip int br | i ^Dialer
Dialer0                    193.34.141.151  YES IPCP   up                    up      
Dialer1                    unassigned      YES IPCP   up                    up
При этом видим, что и статус и протокол Dialer1 находятся в состоянии up, т.е. первый вариант route-map tracking не сработал бы и клиент 192.168.0.101 просто не работал бы. Но если мы взглянем на статистику по route-map tracking из второго варианта то увидим:
#sh route-map tracking
route-map tracking, permit, sequence 100
Match clauses:
ip address (access-lists): 1 
Set clauses:
ip next-hop verify-availability 195.5.5.208 10 track 123  [down]
ip next-hop verify-availability 193.34.140.1 20 track 124  [up]
Policy routing matches: 711 packets, 95929 bytes
route-map tracking, permit, sequence 120
Match clauses:
ip address (access-lists): 2 
Set clauses:
ip next-hop verify-availability 193.34.140.1 10 track 124  [up]
ip next-hop verify-availability 195.5.5.208 20 track 123  [down]
Policy routing matches: 216 packets, 14100 bytes
route-map tracking, permit, sequence 200
Match clauses:
Set clauses:
ip next-hop verify-availability 195.5.5.208 10 track 123  [down]
ip next-hop verify-availability 193.34.140.1 20 track 124  [up]
Policy routing matches: 0 packets, 0 bytes
Состояние в ip next-hop verify-availability 195.5.5.208 10 обозначено как down, а соответственно эти маршруты установлены не будут.

Всё. Вот и вся заметка. ¨Спасибы¨ принимаются в литрах ;)

понедельник, 21 сентября 2009 г.

Игры с xkbcomp

Господа, как же мне не нравится циклическое переключение раскладок клавиатуры. Циклически это как? Это когда за английским следует русский, за русским украинский, за украинским опять английский и т.д.
До чего-же упрощается жизнь когда привыкаешь к асимметричному переключению раскладок. Это когда переключению в каждую раскладку соответствует своя комбинация.
Например, хотите английский - нажмите CapsLock (очень часто-густо нужная клавиша, правда?), русский - Shift + CapsLock, украинский Ctrl + CapsLock. Кажется неудобным? Как бы не так! Когда привыкните - не сможете больше отвыкнуть.
Так как же это сделать в любимых X'ах? На самом деле не просто, а очень просто. Изначально, года четыре назад, я просто как обезьяна скопировал у sash-kan'а маленький keymap, которым сейчас с удовольствием готов поделиться дальше [gz, bz2, xz]:
xkb_keymap {
    xkb_keycodes { include "evdev+aliases(qwerty)" };
    xkb_geometry { include "pc(pc104)" };
    xkb_types    {
        include "complete"
        type "THREE_GROUPS" {
            modifiers = Shift+Control+Alt;
            map[None] = Level1;
            map[Shift] = Level2;
            map[Control] = Level3;
            map[Control+Shift] = Level4;
            map[Alt] = Level5;
            level_name[Level1] = "Base";
            level_name[Level2] = "Shift";
            level_name[Level3] = "Ctrl";
            level_name[Level4] = "Ctrl Shift";
            level_name[Level5] = "Alt";
        };
    };
    xkb_compatibility { include "complete" };
    xkb_symbols {
        include "pc+us+ru:2+ua:3+us(dvorak):4+level3(menu_switch)+inet(evdev)"
        replace key <CAPS>
        {
            type = "THREE_GROUPS",
            actions[Group1]=[LockGroup(group=1), LockGroup(group=2), LockGroup(group=3), LockMods(modifiers=Lock), LockGroup(group=4)]
        };
    };
};

Собственно "изюминка" тут даже невооружённым взглядом заметна. Ну и ещё. Безусловно этот конфиг в каждой секции можно дополнить другими определениями - это всего лишь обычный keymap который скармливается xkbcomp'у.
Чтобы этот конфиг отрабатывал каждый раз при входе в Ваш любимый DE, сохраните вышеприведённый конфиг, скажем, в /usr/share/X11/xkb/keymap/three_groups и нарисуйте примерно такой скрипт в /etc/X11/Xsession.d/60xkb-lang:
(
cd /usr/share/X11/xkb/ && xkbcomp keymap/three_groups $DISPLAY &>/dev/null
)

true
Маленькая заметка напоследок. Уже несколько раз при обновлении любимого Debian'а сталкивался с проблемой, что разработчики что-то переписывали-переопределяли в xkb в результате чего надо было заново и заново пытаться перелопатить конфиг в поиске нужной комбинации include в symbols. Огромное спасибо sash-kan'у который натолкнул сегодня меня на следующую мысль:
$ xkbcomp $DISPLAY - | less
Просто сегодня в очередной раз обновился и с расстройством обнаружил, что у меня не отрабатывают клавиши Up, Down, Left, Right, Home и т.д. когда компилится вышеуказанный keymap. Но при этом великолепно работают при, так сказать, установках "по-умолчанию" в Gnome. Простая командочка:
$ xkbcomp $DISPLAY - | egrep "^xkb_"
позволила увидеть искомую комбинацию для include. Моему счастью не было предела! ;)
Ну, собственно, на этой оптимистической нотке эту заметку можно и закончить :)