вторник, 2 ноября 2010 г.

Настройка xdm

После перехода с Lenny на Squeeze начал пользоваться xdm. Сегодня дошли руки до настройки более приятного вида этого дисплейного менеджера.

В файл /etc/X11/xdm/Xresources я добавил следующие строчки:
xlogin.Login.x:                 320
xlogin.Login.y:                 352
xlogin.Login.width:             640
xlogin.Login.height:            320
xlogin.Login.foreground:        black
xlogin.Login.face:              Liberation Sans-18
xlogin.Login.greeting:          Welcome to CLIENTHOST
xlogin.Login.greetFace:         Liberation Sans-24
xlogin.Login.greetColor:        darkred
xlogin.Login.namePrompt:        Login:    
xlogin.Login.passwdPrompt:      Password: 
xlogin.Login.promptFace:        Liberation Sans-18:bold
xlogin.Login.promptColor:       black
xlogin.Login.fail:              Login incorrect
xlogin.Login.failFace:          Liberation Sans-18
xlogin.Login.failColor:         red
xlogin.Login.failTimeout:       5
xlogin.Login.hiColor:           black
xlogin.Login.shdColor:          black
xlogin.Login.frameWidth:        3
xlogin.Login.innerFrameWidth:   3
xlogin.Login.sepWidth:          1
xlogin.Login.logoFileName:      /usr/share/X11/xdm/pixmaps/debian.xpm
xlogin.Login.logoPadding:       10
xlogin.Login.useShape:          true
В файл /etc/X11/xdm/Xsetup поместил следующую строчку:
$ xsetroot -solid grey
Если кому интересно, как запустить два X-сервера, то на всякий случай описываю и это. В файл /etc/X11/xdm/Xservers нужно прописать желаемое количество локальных X-серверов (мне хватает двух - один на консоли 7, второй на консоли 8):
:0 local /usr/bin/X :0 vt7 -nolisten tcp
:1 local /usr/bin/X :1 vt8 -nolisten tcp
Соответственно, вид настроенного xdm показан на нижеследующей фотографии:


К сожалению, снимок экрана программно сделать не удалось, хотя я знаю о существовании Xnest и Xephyr, но мне лень было с ними разбираться ради такой ерунды.

среда, 27 октября 2010 г.

FreeRDP

Сегодня в новостях услышал о существовании преемника rdesktop - freerdp. Судя по описанию в новости и по отзывам в комментариях, в нём устранены проблемы с несинхронным переключением раскладки на локальном и удалённом компьютере и устранены проблемы с залипанием клавиши Alt. Попробовал - и в самом деле, отлично работает. Ещё поправили глюк, когда вместо символа / вводился \. Наконец-то удалённое администрирование Windows-машин из Linux-компьютера превратилось в удовольствие! Спасибо добрым людям за то, что довели глючную поделку до ума.

В Debian пакет называется freerdp-x11, а команда для подключения - xfreerdp.

Автомонтирование с помощью autofs

Давно мечтал настроить автомонтирование с помощью autofs. Вроде бы всё очень просто, но до сих пор до меня не доходила одна очень простая, но ключевая вещь. Но об этом попозже, сначала опишу настройку.

Сначала, как водится, нужно установить autofs:
# apt-get install autofs5
Затем задать ему настроечные файлы. Первый файл называется /etc/auto.master и содержит всего одну строчку:
/mnt/.autofs    /etc/auto.misc --timeout=60
Эта строчка говорит о том, что все обращения к каталогу /mnt/.autofs будут обрабатываться демоном automount, настройки которого указаны в файле /etc/auto.misc. Опция --timeout=60 сообщает, что если к какому-либо диску не обращались в течение 60 минут, его нужно автоматически размонтировать.

Второй файл, как вы уже наверное догадались, называется /etc/auto.misc, у меня на компьютере он содержит следующие строчки:
cdrom           -fstype=auto,ro         :/dev/sr0
floppy          -fstype=auto,umask=000  :/dev/fd0
usb1            -fstype=auto,umask=000  :/dev/sdc1
usb2            -fstype=auto,umask=000  :/dev/sdd1
usb3            -fstype=auto,umask=000  :/dev/sdc
usb4            -fstype=auto,umask=000  :/dev/sdd
В первом столбце сообщается название каталога, в который будет смонтирован диск, во второй колонке перечисляются опции монтирования, в третьей колонке - имя файла устройства. Двоеточие на самом деле является разделителем имени компьютера и диска на нём. Autofs может автоматически монтировать не только файловые системы на локальных устройствах, но и каталоги NFS или Samba.

Перед запуском autofs можно создать в каталоге /mnt/.autofs подкаталоги cdrom, floppy, usb1, usb2, usb3, usb4 и проставить на них права доступа. Например, я ограничился двумя группами - cdrom для устройства, с которого можно только читать, и floppy для устройств, на которые можно и читать и писать:
# cd /mnt/.autofs
# chgrp cdrom cdrom
# chmod 550 cdrom
# chgrp floppy floppy usb1 usb2 usb3 usb4
# chmod 770 floppy usb1 usb2 usb3 usb4
Теперь можно добавить в группы floppy и cdrom пользователей, которые должны иметь доступ к дискетам/USB-дискам и приводу компакт- и DVD-дисков. Например, вот так:
# adduser stupin cdrom
# adduser stupin floppy
Теперь можно запустить autofs:
# /etc/init.d/autofs start
Теперь о простой, но очень важной детали. Если теперь просто зайти в каталог /mnt/.autofs, то окажется, что он пуст. Не смотря на то, что мы создавали в каталоге /mnt/.autofs подкаталоги cdrom, floppy, usb1, usb2, usb3, usb4, эти каталоги после запуска демона autofs не отображаются. На самом деле мы создавали их только для того, чтобы определить права для смонтированных файловых систем.

Эти каталоги не появятся в /mnt/.autofs до тех пор, пока мы не попытаемся к ним обратиться!

Например, заходим в каталог /mnt/.autofs и видим, что там ничего сейчас нет:
# cd /mnt/.autofs
# ls
Не обращая на это внимания, пытаемся обратиться к каталогу /mnt/.autofs/usb1, как будто он есть:
# ls usb1
1  2
При обращении к этому каталогу autofs активировал скрытый каталог и смонтировал в него USB-диск. Теперь, пока каталог не успел ещё отмонтироваться, его можно увидеть:
# ls
usb1
Так вот, для того, чтобы вас не смущало отсутствие каталогов и вы не гадали, какие каталоги там могут появиться, если к ним обратиться по имени, можно создать в /mnt символические ссылки, которые сами всегда будут существовать и указывать на нужные каталоги:
# cd /mnt
# ln -s .autofs/cdrom cdrom
# ln -s .autofs/floppy floppy
# ln -s .autofs/usb1 usb1
# ln -s .autofs/usb2 usb2
# ln -s .autofs/usb3 usb3
# ln -s .autofs/usb4 usb4
Теперь можно зайти в каталог /mnt и увидеть все диски, которые смонтированы в настоящее время статически или монтируются автоматически при обращении к ним:
# cd /mnt
# ls # ls
cdrom  disk_c disk_d floppy iso  usb1  usb2  usb3  usb4
Можно зайти в любой из каталогов и увидеть его содержимое. При этом автоматически монтируемые диски смонтируются при обращении к каталогу.

Есть, правда, и несколько неприятные вещи. Например, умные файловые менеджеры не меняют текущий каталог для того, чтобы отобразить его содержимое. Как следствие, когда мы переходим по ссылке, происходит обращение к автоматически монтируемой файловой системе и она монтируется. Создаётся список файлов в точке монтирования, этот список выводится файловым менеджером на экран. Если теперь человек надолго задумается, диск автоматически отмонтируется, т.к. он никем не занят и к нему не было обращений. Подсистема inotify сразу же сообщит об исчезновении файлов из каталога файловому менеджеру и файловый менеджер обновит содержимое каталога - покажет пустоту.

Поэтому удобно пользоваться таким автомонтированием только из командной строки, из Midnight Commander и из других файловых менеджеров, которые меняют текущий каталог.

Перенос DHCP-сервера

Встала задача - перенести настройки с DHCP-сервера Windows на DHCP-сервер в Linux. Основные настройки можно перенести и вручную, а вот таблицу с привязками имени, MAC- и IP-адреса каждого компьютера переносить вручную мне было лень. Было лень настолько, что я принялся писать конвейер для командной строки, который преобразует мне всю таблицу из одного формата в другой.

Для начала я снял дамп настроек DHCP-сервера в Windows:
netsh dhcp server \\11.11.11.1 dump > dump.txt
Потом я перенёс этот файл в Linux, сменил его кодировку и после получаса мучений, наваял такой конвейер (для того, чтобы увидеть целиком, придётся, видимо, скопировать его и вставить в текстовый редактор):
grep "Dhcp Server" dump.txt | \
  cut - -f8,9,10 -d" " | \
  grep domain | \
  cut -d. -f1-4 | \
  sed -e 's/\"//g' - | \
  sed -e 's/\(.*\) \(.*\) \(.*\)/\2 \1 \3/g' - | \
  sed - -e 's/^\([0-9a-f]\)\([0-9a-f]\)\([0-9a-f]\)\([0-9a-f]\)\([0-9a-f]\)\([0-9a-f]\)\([0-9a-f]\)\([0-9a-f]\)\([0-9a-f]\)/\1\2:\3\4:\5\6:\7\8:\9/g' | \
  sed - -e 's/:\([0-9a-f]\)\([0-9a-f]\)\([0-9a-f]\)\([0-9a-f]\)/:\1\2:\3\4/g' | \
  sed -e 's/\(.*\) \(.*\) \(.*\)/\thost \3 {\n\t\thardware ethernet \1;\n\t\tfixed-address \2;\n\t}/g' - \
  > hosts.txt
Эта строчка находит в файле dump.txt строки вида:
Dhcp Server 11.11.11.1 Scope 11.0.0.0 Add reservedip 11.11.11.11 00AABBCCDDEE "computer.domain" "" "DHCP"
И переделывает их в строки вида:
host computer {
  hardware ethernet 00:AA:BB:CC:DD:EE;
  fixed-address 11.11.11.11;
}
Которые записывает в текстовый файл hosts.txt.

понедельник, 18 октября 2010 г.

Аудиоплееры в Debian

С аудиоплеерами в Linux, на мой взгляд, сложилась парадоксальная ситуация. Плееров много, но выбрать из них нечего. Даже с видеоплеерами и то лучше - можно выбрать практически любой и он не будет написан на Python, mono или завязан на KDE4. А вот в случае с аудиоплеерами всё не так.

Недавно я не вытерпел и перешёл с Lenny на Squeeze - в Lenny оказалось неожиданно много глюков. Судя по графику глюков, Squeeze уже сейчас содержит глюков меньше, чем Lenny. По случаю этого обновления мной на пробу были протестированы несколько плееров:

1. Exaile - написан на Python, практически точная копия Amarok. По непонятной причине не захотел играть mp3. Разбираться было лень, т.к. есть много других плееров - как грязи.



2. Banshee - написан на mono. Даже смотреть не стал.

3. Audacious - вполне себе неплохой плеер с WinAMP-подобным интерфейсом. Всё бы ничего, но мне во-первых не очень нравятся программы со шкурками. Во-вторых, он не позволяет выбрать дорожку из многодорожечных FLAC-файлов. А в третьих, натерпелся я от него в Lenny глюков: неработающая поддержка MIDI, мёртвое зависание при попытке посмотреть свойства MIDI-файла, работающее через раз групповое добавление файлов.



4. Audacious GTK - вроде бы то, что надо, но невозможно двигать треки в списке, невозможно удалить несколько треков из списка за раз. Многодорожечные FLAC-файлы также не работают. Одним словом, покоцаный Audacious.



5. Listen Music Player - написан на Python. При обновлении библиотеки добавлял вновь обнаруженных артистов, альбомы и жанры в случайное место списка. В результате во время сканирования попытка запустить хоть какую-нибудь песню превращалась в увлекательную игру - попытка попасть мышью в только что увиденного артиста, который мгновенно убегал совершенно неожиданно то ли вверх по списку, то ли вниз. Уже выделенный однажды элемент так же неожиданно подменялся на другой случайный.



6. Amarok 2. Тяжёл и неповоротлив, как и всё современное KDE 4. Раньше пользовался Amarok, Amarok 2 пробовать не стал.

7. Quod Libet, написан на Python. Просто не запустился!

8. mpd - маргинальный плеер с клиент-серверной архитектурой.

9. mocp - см. пункт 8.

10. XMMS2 - после установки сообщил, что он будет работать только в режиме командной строки и вообще, что он deprecated и заменён на nyxmms2. Поиск такого пакета завершился молчаливым завершением пакетного менеджера - нет такого пакета.

11. BMP (Beep Media Player) - нет такого в пакетах.

12. QMMP - WinAMP-подобный плеер на основе Qt. Для Debian есть только в виде пакета для нестабильной (Sid) ветки. Ставить не стал.

13. Decibel Audio Player - без сканирования фонотеки добавить в список воспроизведения хотя бы файлик не дал (нужно лезть в настройки, чтобы можно было выбрать файлы из определённой папки). Во время сканирования коллекции с плеером ничего невозможно сделать - он не отображает уже отсканированные песни и не позволяет их запустить прямо сейчас, пока будет сканироваться остальное.



14. DeaDBeeF - плеер, стремящийся стать аналогом Foobar2000. Установил из репозитория проекта пакет для Squeeze. Поддерживает многодорожечные FLAC. Но, не позволяет воспроизводить MIDI через ALSA, можно воспроизводить MIDI только через собственный хиленький программный синтезатор с примитивным звучанием типа OPL3. Остановился пока на нём.

пятница, 8 октября 2010 г.

Добавление альтернативных имён портала SharePoint Services

Пишу себе на память. Вот по этой ссылке можно найти всю интересующую информацию по сабжу: Update to using External URLs with WSS v3

Можно воспользоваться "Центром администрирования", меню "Операции", пунктом "Сопоставления для альтернативного доступа" и прописать там альтернативное имя портала.

Я воспользовался командой следующего вида:
STSADM.EXE -o addalternatedomain -url http://portal -incomingurl http://anothername -urlzone intranet
Затем добавил новое имя на DNS-сервере и портал стал доступен под двумя именами одновременно.

Делается это с целью последующего переименования сервера в имя, соответствующее корпоративному стандарту. Затем сервер будет переведён из домена филиала в общекорпоративный домен по уже обкатанной мной технологии: Миграция портала SharePoint Services в домен Active Directory.

понедельник, 23 августа 2010 г.

flac & cue в mp3

Иногда попадаются рипы компакт-дисков, сделанные аудиофилами. Аудиофилам обычно очень важно, чтобы рип представлял собой точную копию компакт-диска, поэтому они часто делают рипы всего диска в виде одного файла формате flac, который они сопровождают ещё и файлом со списком дорожек в формате cue.

Чтобы закачать такую музыку на аудио-плеер, умеющий воспроизводить только mp3 или ogg, приходится разбивать flac на отдельные mp3-треки.

Кроме разбивки flac-файла на отдельные файлы и преобразования каждого из файлов в формат mp3 полезно также перенести всю полезную информацию из cue-файла в теги mp3-файла. Для этого нам понадобятся следующие пакеты: shntool, cuetools, lame, enca. Установим их:
# apt-get install shntool cuetools lame enca
shntool потребуется для того, чтобы разбить flac-файл на отдельные wav-файлы, cuetools понадобится для извлечения полезной информации из cue-файла, lame - для кодирования wav-файлов в формат mp3 и простановки тегов, enca используется для автоматического определения кодировки текста в cue-файле (поскольку cue-файл мог быть создан как в Windows, так и в Linux и может иметь символы самых разных алфавитов).

Теперь можно попытаться соединить всё это в единый скрипт:
#!/bin/sh

FROMCP=`enca -e *.cue`
iconv -f $FROMCP -t UTF-8 *.cue > /tmp/list.cue

DATE=`grep "REM DATE" /tmp/list.cue | sed -e 's/REM DATE \(.*\)/\1/g'`
GENRE=`grep "REM GENRE" /tmp/list.cue | sed -e 's/REM GENRE \(.*\)/\1/g'`
COMMENT=`grep "REM COMMENT" /tmp/list.cue | sed -e 's/REM COMMENT \(.*\)/\1/g'`
NUMBER=`cueprint -d "%N" /tmp/list.cue`

shntool split -f /tmp/list.cue *.flac -t %n

for((I=1;I<=NUMBER;I++));
do
  cueprint -n $I -t "ARTIST=\"%p\"\nALBUM=\"%T\"\nTRACKNUMBER=\"%n\"\nTITLE=\"%t\"\n" /tmp/list.cue > /tmp/tags
  . /tmp/tags
  J=`printf "%02d" $I`
  lame -b 192 --cbr \
    --ty "$DATE" \
    --tg "$GENRE" \
    --tc "$COMMENT" \
    --ta "$ARTIST" \
    --tl "$ALBUM" \
    --tn "$TRACKNUMBER" \
    --tt "$TITLE" \
    --add-id3v2 \
    --id3v2-only \
    $J.wav $J.mp3
  rm $J.wav
done

rm /tmp/list.cue /tmp/tags
Скрипт рассчитан на то, что в текущем каталоге имеется только один cue-файл и один flac-файл.

Иногда вместо flac используется ape, который с лицензионной стороны намного хуже flac'а. В частности, существовавший когда-то на просторах опенсорса проект mac (Monkey's Audio Codec), исчез именно из-за лицензионных проблем. Не смотря на это, кое-где ещё можно найти как исходники, так и deb-пакет. После установки пакета shntool можно использовать прежним образом, единственное отличие будет заключаться лишь в том, что вместо flac-файла нужно будет указать ape-файл.

Обновлено 3 сентября 2010 года. При обновлении этой заметки и скрипта был использован комментарий к моей старой заметке Конвертируем FLAC в MP3 под Debian.

суббота, 21 августа 2010 г.

Duke Nukem 3D в Debian GNU/Linux

Продолжаю серию заметок о запуске старых игр - стрелялок от первого лица:
  1. Quake в Linux
  2. Запуск Quake на движке Nexuiz
  3. Quake2 на Debian GNU/Linux
На этот раз я откопал современный порт Duke Nukem 3D, который называется Eduke32. Официальный сайт проекта находится по следующему адресу: http://www.eduke32.com/ Для установки движка игры воспользуемся репозиторием Debian на сайте проекта. На странице Apt Repository находим интересующий нас раздел Lenny. В соответствии с инструкциями добавляем репозиторий в систему, прописав следующие две строчки в файл /etc/apt/sources.list:
deb http://apt.duke4.net lenny main
deb-src http://apt.duke4.net lenny main
Теперь добавим PGP-ключ репозитория с помощью следующей команды:
# wget http://apt.duke4.net/key/eduke32.gpg -O- | apt-key add -
Обновим список пакетов:
# apt-get update
И установим интересующие нас пакеты с движком игры и с условно-бесплатной версией самой игры:
# apt-get install eduke32 duke3d-shareware
Кроме этих двух пакетов в репозитории имеются ещё два пакета: build-engine-utils - коллекция инструментов, предназначенных для манипуляции данными игр, основанных на движке Build (из таковых я припоминаю ещё игры Blood, Redneck Rampage и Outlaws) и mapster32 - редактор карт, работающий в режиме OpenGL. В общем, в этом репозитории, похоже, есть всё необходимое, чтобы делать новые карты и модификации игры.

Но это ещё не всё. Ещё я нашёл проект High Resolution Pack, в рамках которого люди занимаются повышением разрешения текстур и заменой всех спрайтов на модели: polymer_hrp132.zip, архивчик уже достиг объёма 466 мегабайт!

Скачаем последний релиз HRP и распакуем его в каталог с настройками личными игры текущего пользователя:
$ wget http://www.duke4.org/files/nightfright/beta/polymer_hrp132.zip
$ unzip polymer_hrp132.zip -d ~/.eduke32
Теперь при запуске игры, в окошке выбора разрешения нужно указать использование движка Polymer, который как раз и умеет рисовать трёхмерные модели.

Вот так игра выглядит на разрешении 1280x1024 без использования HRP:

А вот так выглядит на разрешении 800x600 с использованием HRP:

Ещё пара снимков с использованием HRP. Этот с разрешением 1280x1024:

Этот с разрешением 800x600:

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

пятница, 13 августа 2010 г.

Lighttpd и gamin

Ранее я уже писал, что начал пользоваться Mathopd: Биография одного домашнего сервера и настройка Mathopd. Тогда я решил попробовать его, потому что привычный Lighttpd отказывался устанавливаться в отсутствии famd, а famd конфликтовал с gamin, который я установил, чтобы избежать внезапных зависаний программ: famd vs gamin. Нужно было пересобрать Lighttpd с gamin вместо famd, но мне тогда было лень этим заниматься, т.к. это было прекрасным поводом попробовать Mathopd :)

На днях Mathopd мне наконец надоел и я решил всё-таки собрать Lighttpd с gamin. Рецептом сборки этой связки я и хочу поделиться.

Для начала, скачаем исходники:
$ apt-get source lighttpd
И перейдём в каталог с распакованными исходниками и информацией для сборки:
$ cd lighttpd-1.4.19
Затем, заглянем в файл debian/control и просмотрим список зависимостей для сборки пакета (Build-Depends): debhelper (>= 5.0.0), cdbs, mime-support, libssl-dev, zlib1g-dev, libbz2-dev, libattr1-dev, libpcre3-dev, libmysqlclient15-dev, libfam-dev, libldap2-dev, libfcgi-dev, libgdbm-dev, libmemcache-dev, liblua5.1-0-dev, quilt, patchutils, pkg-config, uuid-dev, libsqlite3-dev, libxml2-dev, libkrb5-dev, perl

Установим всё это хозяйство, за исключением libfam-dev, который мы заменим на libgamin-dev:
# apt-get install debhelper cdbs mime-support libssl-dev zlib1g-dev libbz2-dev \
  libattr1-dev libpcre3-dev libmysqlclient15-dev libgamin-dev libldap2-dev libfcgi-dev \
  libgdbm-dev libmemcache-dev liblua5.1-0-dev quilt patchutils pkg-config uuid-dev \
  libsqlite3-dev libxml2-dev libkrb5-dev perl
Теперь отредактируем файл debian/control, заменив в нём libfam-dev на libgamin-dev.

Далее, опишем изменения, сделанные в пакете с помощью dch:
$ dch -i
Я внёс следующее описание сделанных изменений:
lighttpd (1.4.19-5+lenny1gamin) stable-security; urgency=low

* Changed dependency from libfam-dev to libgamin-dev.

-- Vladimir Stupin <wheelof@gmail.com>  Fri, 13 Aug 2010 10:17:22 +0600

Осталось лишь собрать изменённый пакет:
$ dpkg-buildpackage -b -us -uc -rfakeroot
Всё. Переходим в каталог выше, где и находятся собранные пакеты:
lighttpd_1.4.19-5+lenny1gamin_i386.deb
lighttpd-doc_1.4.19-5+lenny1gamin_all.deb
lighttpd-mod-cml_1.4.19-5+lenny1gamin_i386.deb
lighttpd-mod-magnet_1.4.19-5+lenny1gamin_i386.deb
lighttpd-mod-mysql-vhost_1.4.19-5+lenny1gamin_i386.deb
lighttpd-mod-trigger-b4-dl_1.4.19-5+lenny1gamin_i386.deb
lighttpd-mod-webdav_1.4.19-5+lenny1gamin_i386.deb
Устанавливаем нужные пакеты с помощью dpkg и пользуемся:
# dpkg -i lighttpd_1.4.19-5+lenny1gamin_i386.deb

среда, 4 августа 2010 г.

Доступ к буферу обмена X Window System из командной строки с помощью xclip

Перевод статьи: Access the X Window System Clipboard from the Command Line with xclip

17 марта 2009, Эрик Фэлор (Erik Falor)

Вы когда-нибудь выделяли текст в окне терминала, чтобы скопировать его в X-приложение? Отбросьте мышь и воспользуйтесь вместо неё xclip. С помощью xclip вы просто перенаправляете через конвейер в xclip тот текст, который вы хотите скопировать:
$ lspci | xclip
Теперь перейдите в X-приложение и вставьте захваченный вывод в программу. xclip также позволит вам “вставить” выбранный текст в терминал. Просто воспользуйтесь опцией -o для вывода выделенного текста:
$ xclip -o
xclip можно найти на sourceforge.net/projects/xclip.

Изменение громкости из сценария Bash

Перевод статьи: Change Volume From a Bash Script

24 сентября 2008, Митч Фрэзер (Mitch Frazier)

Если вы пользуетесь звуковой системой ALSA, вы можете воспользоваться функциями, содержащимися в представленном сценарии, для получения и установки громкости звука вашей системы. Вы можете использовать его, если у вас запущен сторожевой сценарий и вы хотите увеличить громкость сигнала во время тревоги, а затем вернуть громкость обратно к предыдущему уровню.

Функция get просто использует amixer для вывода информации о канале управления миксером "Master" и затем использует grep для вырезания нужного значения из выведенной информации.

Функция set также использует amixer для задания громкости. Она использует опцию "cset" программы amixer.

Сценарий следующий:
#!/bin/bash
#

#####################################################################
# Получить текущую громкость.
function get_volume()
{
  mixer=$(amixer get Master | grep 'Front Left:')
  echo $mixer | cut -d ' ' -f 4
}

#####################################################################
# Задать громкость.
function set_volume()
{
  amixer cset iface=MIXER,name="Master Playback Volume" $1 >/dev/null
}

if [[ $(basename $0 .sh) == 'sound' ]]; then
  sound_file=~/Documents/sounds/notify.wav
  if [[ "$1" ]]; then
    sound_file="$1";
  fi

  ovol=$(get_volume)
  echo "Текущая громкость: $ovol"
  aplay $sound_file
  sleep 2

  vol=40
  echo "Воспроизведение на громкости: $vol"
  set_volume $vol
  aplay $sound_file
  sleep 2

  echo "Возвращение к громкости: $ovol"
  set_volume $ovol
  aplay $sound_file
fi

# vim: tabstop=4: shiftwidth=4: noexpandtab:
# kate: tab-width 4; indent-width 4; replace-tabs false;
Если вы сохраните этот сценарий под именем sound.sh и запустите его самого, передав имя звукового файла, сценарий воспроизведёт файл на текущей громкости, затем поднимет громкость и воспроизведёт его снова, и наконец, восстановит громкость и воспроизведёт его последний раз. Если вы откроете средство управления миксером перед запуском сценария, вы должны увидеть как громкость главного канала изменяется под действием сценария. Вы можете изменить значение громкости в строке vol=40 на значение, которое вам нужно.


Митч Фрэзер (Mitch Frazier) является помощником редактора в Linux Journal и веб-редактором в linuxjournal.com.

Скачать весь веб-сайт с помощью wget

Перевод статьи: Downloading an Entire Web Site with wget

05 сентября 2008, Дашамир Хоксха (Dashamir Hoxha)

Если вам когда-нибудь потребуется скачать целый веб-сайт, например для просмотра без доступа в интернет, wget может это сделать -- например:
$ wget \
  --recursive \
  --no-clobber \
  --page-requisites \
  --html-extension \
  --convert-links \
  --restrict-file-names=windows \
  --domains website.org \
  --no-parent \
  www.website.org/tutorials/html/
Эта команда скачает веб-сайт www.website.org/tutorials/html/.

Используются следующие опции:
  • --recursive: скачивать весь веб-сайт.
  • --domains website.org: не переходить по ссылкам вне сайта website.org.
  • --no-parent: не переходить по ссылкам вне каталога tutorials/html/.
  • --page-requisites: собрать все элементы, относящиеся к странице (изображения, CSS и так далее).
  • --html-extension: сохранять файлы с расширением .html.
  • --convert-links: преобразовывать ссылки так, чтобы они работали локально, без доступа в интернет.
  • --restrict-file-names=windows: изменять имена файлов таким образом, чтобы они работали в Windows.
  • --no-clobber: не заменять какие-либо существующие файлы (используется в случае, если скачивание было прервано и возобновлено).

Наслаждайтесь Gawk

Перевод статьи: Fun With Gawk

15 февраля 2010, Джеймс Хайннэнт (James Hinnant)

Когда grep и sed бывает недостаточно, gawk может предоставить дополнительную лошадиную силу, которая вам необходима. Следующий совет содержит образец того, что можно делать с помощью gawk.

Выделить последний столбец из текстового файла, столбцы которого разделены пробелами:
$ cat myfile | gawk '{print $NF}'
или:
$ gawk '{print $NF}' myfile
Вывести количества файлов, которыми владеет каждый из пользователей в текущем каталоге:
$ /bin/ls -l | \
  gawk 'NR > 1 {counts[$3]++;}
END {for (s in counts) {
printf(" %-15s : % 5d\n",
s, counts[s]);}}' | \
  sort
Завершить ваши процессы (одно из применений - завершить зависший сеанс, если вы можете удалённо войти на рабочую станцию с другого компьютера):
$ ps -elf | \
  gawk -v me="$USER" '$3 == me {print $4}' | \
  egrep -v $$ | \
  xargs -i@@ kill -9 @@; kill -9 $$

Преобразовать имена файлов к нижнему регистру

Перевод статьи: Convert Filenames to Lowercase

25 июля 2008, Фил Хьюз (Phil Hughes)

Я собирался сказать, что я написал это вчера, но отметка времени файла указывает на то, что это было 22 ноября 1998. Ничего нового, ничего особенного, это просто работает.

Вернёмся в старое-доброе время операционных систем, не понимавших разницы между NAME и name. В результате, если иногда приходится копировать файлы с гибких дисков (помните такие?), созданных на Давно Онемевшей Системе, можно получить свалку каталогов с именами файлов в верхнем регистре. Поскольку мы, опытные старожилы UNIX, пользуемся хитрой уловкой для вывода имён каталогов до имён файлов файлов по команде ls (а именно - начинаем имена каталогов с букв в верхнем регистре), наличие имён файлов с символами в верхнем регистре нас раздражает.

Поскольку я слишком часто пользовался командой mv и ввод команд типа mv FILE.TXT file.txt меня окончательно изнурил, я написал этот сценарий. Я думал, что я просто сделал косметический ремонт, но на самом деле сценарий делает работу и в нём легко разобраться. (Номера строк приведены просто для того, чтобы на них ссылаться.)
1   #!/bin/sh
 2   # lowerit
 3   # преобразовывает имена всех файлов в текущем каталоге к нижнему регистру
 4   # работает только над обычными файлами -- не меняет имена каталогов
 5   # запрашивает подтверждение перед заменой существующего файла
 6   for x in `ls`
 7   do
 8     if [ ! -f $x ]; then
 9       continue
10     fi
11     lc=`echo $x | tr '[A-Z]' '[a-z]'`
12     if [ $lc != $x ]; then
13       mv -i $x $lc
14     fi
15   done
Строка 6 начинает цикл (который заканчивается в строке 15). Команда ls возвращает список имён файлов, которые последовательно назначаются переменной оболочки x. if test (строки с 8 по 10) проверяет, является ли имя текущего файла именем простого файла. Если нет, остаток выражения в текущего прохода цикла пропускается.

Если выполняется строка 11, то известно, что обрабатывается обычный файл. С помощью tr мы приводим имя файла в нижний регистр и присваиваем новое имя переменной оболочки lc. Затем в строке 12 происходит проверка, что имя файла в нижнем регистре отличается от исходного. Если это так, то выполняется 13 строка, которая меняет исходное имя файла на новое имя в нижнем регистре. Опция -i заставляет mv спрашивать подтверждение, если команда собирается перезаписать существующий файл.

Фил Хьюз (Phil Hughes)

Дополнение переводчика от 13-05-2012. Нашёл ещё один вариант скрипта для этой задачи:
$ find ./ -type f | awk '{ print $1 " " tolower($1) }' | xargs -L 1 mv

Проверка правильности IP-адресов из сценария Bash

Перевод статьи: Validating an IP Address in a Bash Script

26 июня 2008, Митч Фрэзер (Mitch Frazier)

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

Задача очевидна: IP-адреса являются 32-битными значениями, записанными как четыре числа (отдельные байты IP-адреса), разделённых точками. Каждое из четырёх чисел может принимать значение в диапазоне от 0 до 255.

Следующий сценарий bash содержит функцию, которая возвращает истину, если её передан правильный IP-адрес и ложь в противном случае. В bash под истиной понимают завершение с нулевым кодом, всё остальное означает ложь. Код команды/функции bash помещается в переменную "$?".
#!/bin/bash

# Проверка правильности IP-адреса:
# Способ применения:
#      valid_ip IP_АДРЕС
#      if [[ $? -eq 0 ]]; then echo good; else echo bad; fi
#   ИЛИ
#      if valid_ip IP_ADDRESS; then echo good; else echo bad; fi
#
function valid_ip()
{
  local ip=$1
  local stat=1

  if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
    OIFS=$IFS
    IFS='.'
    ip=($ip)
    IFS=$OIFS
    [[ ${ip[0]} -le 255 && ${ip[1]} -le 255 \
      && ${ip[2]} -le 255 && ${ip[3]} -le 255 ]]
    stat=$?
  fi
  return $stat
}

# При непосредственном запуске выполним несколько проверок.
if [[ "$(basename $0 .sh)" == 'valid_ip' ]]; then
  ips='
4.2.2.2
a.b.c.d
192.168.1.1
0.0.0.0
255.255.255.255
255.255.255.256
192.168.0.1
192.168.0
1234.123.123.123
'
  for ip in $ips
  do
    if valid_ip $ip; then
      stat='good';
    else
      stat='bad';
    fi
    printf "%-20s: %s\n" "$ip" "$stat"
  done
fi
Если сохранить этот сценарий под именем "valid_ip.sh" и запустить его напрямую, он проведёт несколько проверок и выведет результаты:
# sh valid_ip.sh
4.2.2.2             : good
a.b.c.d             : bad
192.168.1.1         : good
0.0.0.0             : good
255.255.255.255     : good
255.255.255.256     : bad
192.168.0.1         : good
192.168.0           : bad
1234.123.123.123    : bad
В функции valid_ip, чтобы удостовериться в том, что рассматриваемый IP-адрес состоит из четырёх разделённых точками чисел, используется регулярное выражение в операторе if:
if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
Если проверка пройдена, код внутри оператора if разделяет рассматриваемый IP-адрес на четыре части по точкам и помещает части в массив:
OIFS=$IFS
IFS='.'
ip=($ip)
IFS=$OIFS
Эти действия меняют переменную bash, которая называется "внутренний разделитель полей" (Internal Field Separator). Обычно она используется для обработки слов, разделённых пробелами, по после этого bash будет использовать для разделения полей точки. Поместим значение рассматриваемого IP-адреса внутрь скобок и присвоим их значение массиву, поместив каждое из полей, разделённых точками, в отдельную ячейку массива. Теперь проверим отдельные поля, чтобы удостовериться в том, что они меньше или равны 255. Результат проверки сохраним, так чтобы его можно было вернуть в качестве значения функции:
[[ ${ip[0]} -le 255 && ${ip[1]} -le 255 \
  && ${ip[2]} -le 255 && ${ip[3]} -le 255 ]]
stat=$?
Отметим, что не обязательно проводить проверку равно ли число нулю или оно больше нуля, так как проверка регулярным выражением уже отфильтровала всё, что не состоит из точек и цифр.


Митч Фрэзер (Mitch Frazier) является помощником редактора в Linux Journal и веб-редактором в linuxjournal.com.

воскресенье, 25 июля 2010 г.

Quake2 на Debian GNU/Linux

Ранее я уже писал про то, как можно запустить Quake в Linux:
  1. Quake в Linux
  2. Запуск Quake на движке Nexuiz
Запуск Quake 3 тоже не представляет проблем, если воспользоваться для этого игрой OpenArena.

Вот чего мне до сих пор не удавалось, так это приличным образом запустить в Debian любимый мной Quake 2, который во времена студенчества мы с тремя моими друзьями перевели на русский язык. Но теперь я нашёл готовые deb-пекеты для установки Quake 2 в Debian: Yamagi Quake II Client

Для установки Quake 2 скачиваем три пакета вот отсюда Debian packages of Yamagi Quake II:
$ wget http://deponie.yamagi.org/quake2/debs/i386/yamagi-quake2_2.11-1_i386.deb
$ wget http://deponie.yamagi.org/quake2/debs/all/quake2-data_16_all.deb
$ wget http://deponie.yamagi.org/quake2/debs/i386/yamagi-quake2-addons_1.1_i386.deb
И незамедлительно устанавливаем их:
# dpkg -i yamagi-quake2_2.11-1_i386.deb
# dpkg -i quake2-data_16_all.deb
# dpkg -i yamagi-quake2-addons_1.1_i386.deb
Теперь достаём с полки диск с Quake 2 и копируем содержимое каталога baseq2 в каталог /usr/share/games/quake2/baseq2. Достаточно скопировать только файл pak0.pak:
# cp /cdrom/BASEQ2/PAK0.PAK /usr/share/games/quake2/baseq2/pak0.pak
И запускаем:
$ yamagiq2
Как всегда, без ложки дёгтя в бочке мёда не обходится.

Во-первых, для работы quake2 необходимо наличие в системе пакетов libogg0 (>= 1.1.3), libsdl1.2debian (>= 1.2.10-1), libvorbis0a (>= 1.1.2), libvorbisfile3 (>= 1.1.2), zlib1g (>= 1:1.2.1). Проверяем наличие нужных пакетов и устанавливаем недостающие.

Во-вторых, звук в игре по непонятной мне причине немного заикается и хрипит. Как я ни пытался улучшить звук, ничего особого не получилось. С помощью следующей команды:
$ yamagiq2 +s_khz 44 +s_loadas8bit 0 +snd_restart
Удалось лишь немного улучшить качество звука в те моменты, когда он не заикается и не хрипит. Но заикаться и хрипеть от этого он всё равно не перестал.

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

Из приятного можно отметить следующее:
  • Можно играть не только в классический Quake 2, но и в его моды Reckoning от Xatrix и Ground Zero от Rogue.
  • Можно слушать музыку с компакт-диска без компакт-диска, благо в состав пакета входит скрипт, который может снять треки с диска, закодировать их в OGG/Vorbis и положить на жёсткий диск, откуда и можно в дальнейшем воспроизводить треки.
Для добавления модов скопируем каталоги с модами в соответствующее место, откуда их может взять движок игры.
# cp -R /home/stupin/quake2/Quake2Mods/RecKoning/xatrix /usr/share/games/quake2/
# cp -R /home/stupin/quake2/Quake2Mods/GroundZero/rogue /usr/share/games/quake2/
Теперь для запуска одного из модов можно воспользоваться следующими командами:
$ yamagiq2 +s_khz 44 +s_loadas8bit 0 +snd_restart +set game xatrix
$ yamagiq2 +s_khz 44 +s_loadas8bit 0 +snd_restart +set game rogue
Для съёма треков с компакт-диска можно воспользоваться примером скрипта, находящимся в одном из пакетов с игрой: /usr/share/doc/yamagi-quake2/examples/cdripper.sh

Ну и напоследок, снимок на память:

суббота, 19 июня 2010 г.

Миграция портала SharePoint Services в домен Active Directory

Предупреждение.

Всё нижеследующее вы можете использовать на свой страх и риск! Автор не несёт никакой ответственности за возможные риски: утерю информации, некорректное функционирование программного обеспечения и т.п.

Постановка задачи.

Имеется веб-портал SharePoint Services 3.0, аутентификация пользователей в котором происходит по локальным учётным записям на самом сервере. Требуется ввести сервер в домен Active Directory и использовать для аутентификации на портале учётные записи из домена.

1. Получение информации об имеющихся на портале учётных записях

Запускаем MS SQL Enterprise Manager, открываем базу данных WSS_Content. Информация о пользователях находится в таблице UserInfo. Запускаем из Enterprise Manager'а инструмент SQL Query Analyzer, в которм выполняем следующий запрос:
select tp_SystemID, tp_Login, tp_Title
from UserInfo;
Полученную информацию копируем в таблицу Excel. В выбранных колонках находятся: SID пользователя, логин пользователя вместе с доменом в виде "ДОМЕН\Логин", строка описания пользователя. SID пользователя в базе данных хранится в двоичном виде, а Query Analyzer выводит его в шестнадцатеричном виде.

После этого в таблице должны иметься следующие столбцы:
A - шестнадцатеричный SID локальной учётной записи,
B - логин локальной учётной записи,
C - описание локальной учётной записи.

2. Добавляем в полученный список столбец с учётными записями пользователей из домена

Каждой учётной записи, используемой для входа на портал, нужно сопоставить учётную запись из домена. Возможно, на этом этапе понадобится завести в домене учётные записи недостающих пользователей.

После этого в таблице должны иметься следующие столбцы:
A - шестнадцатеричный SID локальной учётной записи,
B - логин локальной учётной записи,
C - описание локальной учётной записи,
D - логин доменной учётной записи.

3. Получение SID пользователей из домена

Берём программу user2sid Евгения Рудного по ссылке http://evgenii.rudnyi.ru/programming.html#sid2user. Копируем столбец D в текстовый файл, а в начале каждой строки добавляем команду user2sid. Копируем получившийся bat-файл в каталог с программой. Запускаем bat-файл, перенаправив вывод из него в другой текстовый файл. В полученном текстовом файле убираем всё, кроме SID'ов, так чтобы в каждой строчке файла было по одному SID'у. Информацию из текстового файла добавляем в столбец E файла Excel.

После этого в таблице должны иметься следующие столбцы:
A - шестнадцатеричный SID локальной учётной записи,
B - логин локальной учётной записи,
C - описание локальной учётной записи,
D - логин доменной учётной записи,
E - SID доменной учётной записи.

Будьте внимательны! В списке должны присутствовать ровно столько SID'ов пользователей, сколько их имелось в первоначальном столбце. Также они должны следовать точно в таком же порядке, как в Excel-файле. Если что-то идёт не так, нужно поправить Excel-таблицу и bat-файл и повторить этот этап снова.

4. Конвертирование доменных SID в шестнадцатеричный вид

Для понимания того, каким образом SID хранится в двоичном виде в системе, можно воспользоваться следующей статьёй: Microsoft Security Descriptor(SID)Attributes.

Пишем на PHP сценарий для конвертирования SID:
<?

  function swap($hexdword)
  {
    $res = "";
    for($i = 6; $i >= 0 ; $i -= 2)
      $res .= $hexdword[$i] . $hexdword[$i+1];
    return $res;
  }

  function sid2hex($sid)
  {
    $sidl = explode("-", $sid);

    $hex_sid = "0x" .
      sprintf("%02X", $sidl[1]+0) .
      sprintf("%02X", $sidl[2]+0) .
      "000000000005";

    for($i = 0; $i < $sidl[2]; $i++)
      $hex_sid .= swap(sprintf("%08X", $sidl[3+$i]+0));

    return $hex_sid;
  }

  function hex2sid($hex_sid)
  {
    $hex_sid = trim($hex_sid);
    $sidl[0] = "S";
    $sidl[1] = hexdec(substr($hex_sid, 2, 2));

    $sidl[2] = hexdec(substr($hex_sid, 4, 2));

    for($i = 0; $i < $sidl[2]; $i++)
      $sidl[3+$i] = hexdec(swap(substr($hex_sid, 18+$i*8, 8)));

    $sid = implode("-", $sidl);

    return $sid;
  }

  $sids = "S-1-5-21-583367659-4273102991-479599032-4176
S-1-5-21-583367659-4273102991-479599032-4450";

  $sidsl = explode("\n", $sids);

  foreach ($sidsl as $sid)
    echo sid2hex($sid) . "<br>";
?>
Для того, чтобы быть уверенным в правильности написанных функций, я написал их пару. Проверив, что преобразование SID в шестнадцатеричный вид и обратно, не искажает его, я удостоверился, что функции написаны правильно.

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

После этого в таблице должны иметься следующие столбцы:
A - шестнадцатеричный SID локальной учётной записи,
B - логин локальной учётной записи,
C - описание локальной учётной записи,
D - логин доменной учётной записи,
E - SID доменной учётной записи,
F - шестнадцатеричный SID доменной учётной записи.

5. Получение SQL-запросов для миграции портала на доменные учётные записи

Забегая вперёд, я хочу сказать, что обнаружил в базе данных ещё одну таблицу, в которой упоминаются логины пользователей. Эти логины не используются для проверки входа пользователей, они используются лишь для вывода информации о пользователе. Можно не менять их - в конце концов мы занимаемся не вполне чистым делом, а грязным хаком, а можно поменять, чтобы несоответствие реального логина и информации о логине не бросалось в глаза. итак, эта информация находилась в таблице AllUserData в поле nvarchar3.

Теперь мы можем написать в Excel'е формулы, которые сгенерируют нам SQL-запросы, необходимые для внесения необходимых изменений в БД SharePoint Services.
G ="update UserInfo set tp_Login = '" & D2 &"', tp_SystemID = " & F2 & " where tp_Login = '" & B2 &"' "

H ="update AllUserData set nvarchar3 = '" & D2 &"' where nvarchar3 = '" & B2 &"' "
Чтобы не бросаться голой задницей на амбразуру, подготовим SQL-запросы для отката навороченного:
I ="update UserInfo set tp_Login = '" & B2 &"', tp_SystemID = " & A2 & " where tp_Login = '" & D2 &"' "

J ="update AllUserData set nvarchar3 = '" & B2 &"' where nvarchar3 = '" & D2 &"' "
После этого в таблице должны иметься следующие столбцы:
A - шестнадцатеричный SID локальной учётной записи,
B - логин локальной учётной записи,
C - описание локальной учётной записи,
D - логин доменной учётной записи,
E - SID доменной учётной записи,
F - шестнадцатеричный SID доменной учётной записи,
G - SQL-запрос для обновления информации в таблице UserInfo,
H - SQL-запрос для обновления информации в таблице AllUserData,
I - SQL-запрос для отката обновления таблицы UserInfo,
J - SQL-запрос для отката обновления таблицы AllUserData.

Создаём два текстовых файла - update.txt и rollback.txt. В первый копируем столбцы G и H, а во второй - I и J.

6. Миграция

Для миграции нужно выделить перерыв обслуживания примерно в 15 минут. За это время можно будет выполнить SQL-запросы из файла update.txt и ввести компьютер в домен. На случай если что-то пойдёт не так, лучше увеличить паузу до 30 минут, чтобы вывести компьютер из домена и выполнить SQL-запросы из файла rollback.txt.

На случай же если же что-то пойдёт совсем не так, следует заготовить резервную копию базы данных. Перед снятием резервной копии нужно перевести базу данных портала в режим "Только чтение" через "Центр администрирования" SharePoint Services, вкладку "Управление приложениями", пункт "Квоты и блокировки семейства узлов", а затем снять резервную копию средствами MS SQL Enterprise Manager. После восстановления следует не забыть восстановить режим "Нет блокировки".

Я выполнял обновление из дома, глубоким вечером, разумеется проработав в рабочее время сценарий миграции и текстовые файлы с SQL-запросами.

7. Кое-что ещё

Дополнительно, я поменял учётную запись администратора SharePoint Services в "Центре администрирования" на доменную. Поменял я её в базе данных SharePoint_Admincontent_многобукв в таблицах AllUserData и UserInfo. Это уже не столь критично и не столь сложно. Администраторов мало и они, в отличие от пользователей, могут выдержать и больший перерыв в обслуживании.

пятница, 18 июня 2010 г.

Применение групповых политик

На днях боролся с групповыми политиками Active Directory.

У нас на работе действует стандарт по обеспечению безопасности, предписывающий использовать сложные длинные пароли и периодически менять их (конкретные требования в этом изложении роли не играют). В то же время, есть несколько служебных учётных записей, которые используются большим количеством людей. Например, для доступа к порталу Share Point из агентств, используются учётные записи agent и readonly. Эти учётные записи имеют простые пароли, совпадающие с именем пользователя.

Сейчас эти учётные записи заведены на том же компьютере, где установлен Share Point. Этот компьютер не введён в домен. Чтобы упростить жизнь людям, хочется использовать учётные записи из домена Active Directory. Люди, работающие под той же учётной записью, под которой они входят на портал, смогли бы больше не задумываться о пароле и автоматически попадать на портал под своей учётной записью. Пароль личной учётной записи постоянно менялся бы синхронно со сменой пароля "на вход в компьютер", чем достигалась бы повышенная безопасность.

Перед вводом сервера в домен и переводом портала на использование учётных записей из Active Directory нужно завести недостающих пользователей портала в домене. Как минимум, это учётные записи agent и readonly, обладающие простыми паролями. Соответственно, для того, чтобы их можно было завести с теми же паролями, необходимо смягчить политику безопасности паролей. Для этого я создал в Active Directory новое подразделение, для которого создал новую групповую политику "Простые пароли". Я применил её к подразделению, и попробовал завести пользователей. Но пользователей завести не удалось, т.к. их пароли не удовлетворяли требованиям безопасности.

Я посмотрел результирующую групповую политику и увидел следующее:


При просмотре любого из параметров в окошке свойств параметра выводится следующий текст:



Цитирую, чтобы мой пост легче находился поиском: "GPO, расположенные выше, имеют более высокий приоритет. Процессор обработки политики не пытался настроить параметр. Дополнительная информация приведена в %windir%\security\logs\winlogon.log на целевом компьютере."

Я долго искал в интернете ответ на вопрос почему это не работает. В конце концов вышел на обсуждение Применение групповых политик, где нашёл следующий ответ:

Дело в том, что политика паролей (как и все политики учетных записей) применяется к доменным учетным записям, которые находятся на контроллерах домена, а не на рабочих станциях. Поэтому всякие запреты наследования бесполезны, т.к. применяются не там.

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

Вы можете назначить иную политику паролей на уровне OU, но она будет применяться только к локальным учетным записям пользователей, которые могут быть определены на компьютерах, входящих в данную OU. К доменным пользователям применяется единая политика паролей, определенная на уровне домена.

Так что ваша задача не имеет решения в рамках одного домена.

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

Причём отвечающие говорят об этом, как о достаточно известном fuck'те. Как я понимаю, обойти это можно только поменяв быстренько, пока никто не заметил, политику безопасности, завести нужных пользователей или поменять пароли, а затем так же быстро и незаметно вернуть прежнюю политику =D Вам смешно? Мне тоже. Хотя для кое-кого, это всё было бы смешно, если бы не было столь грустно. Например, для тех, кто не имеет возможности поменять политику домена - для администраторов подразделений.

четверг, 10 июня 2010 г.

Настройка IPSEC туннеля между Cisco и FreeBSD

Не очень люблю дублировать лишний раз информацию, поэтому просто сошлюсь на статью, по которой я настроил IPSec-туннель между Cisco и FreeBSD: Настройка IPSEC туннеля между Cisco и FreeBSD

От себя лишь хочу добавить вот что.

1. Если все соединения настроены по данной статье, тогда sainfo в конфигурации racoon будет везде совпадать. А это значит, что вместо повторения одной и той же секции, можно написать секцию sainfo один раз, заменив секции вида:
sainfo subnet 10.5.3.0/24 any address 10.11.16.0/23 any {
  pfs_group 2;
  lifetime time 24 hour;
  encryption_algorithm aes;
  authentication_algorithm hmac_sha1;
  compression_algorithm deflate;
}
на одну секцию вида
sainfo anonymous{
  pfs_group 2;
  lifetime time 24 hour;
  encryption_algorithm aes;
  authentication_algorithm hmac_sha1;
  compression_algorithm deflate;
}
2. Реальные таблицы маршрутизации бывают много сложнее выдуманных книжных.

Во всех найденных мной статьях между собой связываются два не пересекающихся диапазона IP-адресов. Например, сети 192.168.0.0/24 и 172.16.1.0/25 или 10.0.1.0/24 и 10.0.2.0/24 и т.п.

Но реальные ситуации могут оказаться гораздо сложнее. Например, на одном из маршрутизаторов под управлением FreeBSD могут оказаться три интерфейса:
  1. Интернет-интерфейс, через который идёт трафик по-умолчанию, и трафик на сеть 192.168.1.0/24,
  2. Локальный интерфейс, к которому подключена сеть 10.0.0.0/25,
  3. Некий дополнительный интерфейс, через который нужно направлять шифрованный трафик из локальной сети в сеть 192.168.0.0/16.
LAN 10.0.0.0/25
      |
      |
  ____|______
 |           |
 |  FreeBSD  |------> Internet, LAN 192.168.1.0/24
 |___________|
      ||
      || IPSec
 _____||_____
|            |
|   Cisco    |
|____________|
      |
      |
      |  
LAN 192.168.0.0/16
Что мы видим в этом случае? Два пересекающихся диапазона IP-адресов: 192.168.1.0/24 и 192.168.0.0/16. В файле ipsec.conf FreeBSD можно указать лишь сети, для которых будет осуществляться шифрование, но нельзя указать интерфейс, для которого действует это правило. В итоге может получиться, что будет шифроваться весь трафик из сети 10.0.0.0/25 в сеть 192.168.0.0/16, включая трафик на сеть 192.168.1.0/24, уходящий через Интернет-интерфейс, где никто не ожидает, что он будет зашифрован.

Или другой подобный случай. Есть большая IPSec-сеть, в которой филиальные маршрутизаторы FreeBSD соединяются только с центральным офисом компании. Маршрутизаторов много, скажем три-четыре десятка, за каждым из них закреплён свой диапазон 10.0.x.0/24. Что делать, если к центральному офису будет подключен ещё один филиальный маршрутизатор? Нужно будет прописывать эту сеть в политики шифрования каждого из остальных филиальных маршрутизаторов? А не устанешь?
LAN 10.0.x.0/24
      |
      |
  ____|______
 |           |
 |  FreeBSD  |
 |  10.1.0.x |
 |___________|
      ||
      || IPSec
 _____||_____           ___________
|            |         |           |
|   Cisco    |  IPSec  |  FreeBSD  |
|  10.1.0.1  |=========| 10.1.0.y  |--------LAN 10.0.y.0/24
|____________|         |___________|
      ||
      || IPSec
  ____||_____
 |           |
 |  FreeBSD  |
 | 10.1.0.z  |
 |___________|
      |
      |
      |
LAN 10.0.z.0/24
В таком случае было бы хорошо настроить на маршрутизаторах филиалов некое подобие маршрута по умолчанию. Например, прописать, что филиальный маршрутизатор должен шифровать трафик между сетями 10.0.0.0/8 в центральном офисе и 10.0.x.0/24 в филиале. Но если написать так в ipsec.conf, то маршрутизатор будет шифровать трафик между своей локальной сетью 10.0.x.0/24 и собой 10.0.x.1, поскольку его собственный адрес 10.0.x.1 формально тоже находится в "большой сети" 10.0.0.0/8. А ведь FreeBSD может быть не только маршрутизатором, а и, например, почтовым сервером. В таком случае почтой в локальной сети филиала пользоваться не смогут.

Именно на такую ловушку я и попался. Хорошо, что я перед настройкой на реальном оборудовании собрал тестовый стенд, на котором и выявил такую проблему.

В подобных случаях можно исключить некую подсеть из большой сети следующим образом:
spdadd 10.0.8.0/24 10.0.8.0/24 any -P out none;
spdadd 10.0.8.0/24 10.0.8.0/24 any -P in none;
spdadd 10.0.8.0/24 10.0.0.0/8 any -P out ipsec esp/tunnel/10.1.0.8-10.1.0.1/unique;
spdadd 10.0.0.0/8 10.0.8.0/24 any -P in ipsec esp/tunnel/10.1.0.1-10.1.0.8/unique;
В этом примере мы исключаем из шифрования сети 10.0.0.0/8 подсеть 10.0.8.0/24.

воскресенье, 30 мая 2010 г.

Недостатки инициализации сети в CentOS

На днях пытался настроить сеть в CentOS по образу и подобию того, как я делал это ранее в статьях Два VPN-подключения к Уфанет и VPN-подключение к Уфанет и локальные ресурсы через Ethernet. Попробовал и понял: приличных средств для реализации такой настройки нет.

Для начала - у меня на компьютере имеются два интерфейса Ethernet, определились они под именами eth0 и eth1, как и положено. Только вот мне вдруг невтерпёж захотелось их поменять именами. Сказано - сделано, в RedHat и им подобным (включая CentOS) для привязки интерфейса к MAC-адресу кошерно использовать не udevd, а опцию HWADDR. Прописал необходимое значение этой опции в файлах /etc/sysconfig/network-scripts/ifcfg-eth0 и /etc/sysconfig/network-scripts/ifcfg-eth1. Попытки применить настройки скриптами инициализации сети и udev ни к чем не привели, поэтому пришлось перезагрузиться. После перезагрузки интерфейсы получили необходимые имена.

К слову, смена MAC-адреса на сетевой карте осуществляется с помощью опции MACADDR, но совместное использование HWADDR и MACADDR не допускается, т.к. может привести к непредсказуемым последствиям. То ли дело в Debian, где привязки имён интерфейсов к MAC-адресам осуществляются автоматически с помощью udev, а для смены привязок достаточно отредактировать уже имеющиеся правила. Для смены MAC-адреса в файле /etc/network/interfaces можно прописать опцию hwaddress ether XX:XX:XX:XX:XX:XX, а для надёжности, чтобы udevd не присвоил интерфейсу с этим MAC-адресом другое имя интерфейса, скопипастить одно правило udevd, прописав в него новый MAC-адрес, так что интерфейс с этими MAC-адресами будет иметь одно и то же имя.

Далее, хотел отключить прописывание маршрута по умолчанию, полученного по DHCP с помощью опции DHCLIENT_IGNORE_GATEWAY=yes. Игнорировать маршрут от DHCP? Отвечаем "да". Как бы не так. Я не сразу понял, почему оно не работает, а не работает оно из-за бага: /sbin/dhclient-script gets DHCLIENT_IGNORE_GATEWAY test backwards, который зарепорчен аж 16 февраля 2010 года, да ещё и актуальной в тот момент версией CentOS была 5.4, а я обнаружил этот баг в 5.5. Может не хотят исправлять ради сохранения совместимости с Enterprise-системой от Red Hat? Это, дескать, не баг, а фича.

Далее. Для настройки собственных маршрутов и правил маршрутизации можно создавать файлы /etc/sysconfig/network-scripts/route-* и /etc/sysconfig/network-scripts/rule-*. При чём для файла маршрутов есть два формата: устаревший и актуальный. Устаревшим считается формат, в котором можно было прописывать команды ip route, а новым - жалкие пронумерованные по порядку переменные ADDRESSn, NETMASKn, GATEWAYn. Захотел в новом формате удалить или закомментировать какой-нибудь маршрут из середины, как перед тобой встаёт выбор: либо все следующие маршруты перестанут работать, либо тебе нужно перенумеровать все оставшиеся маршруты так, чтобы их нумерация не прерывалась и шла строго по порядку.

Казалось бы - наплюй на этот новый формат, да воспользуйся вменяемым старым. Но нет! Я хотел написать нечто такое:
81.30.176.0/20 via $GATEWAY dev $DEVICE src $IPADDR table main

а в правила - нечто такое:
from $IPADDR table lunlim

думая, что переменные $GATEWAY, $IPADDR, $DEVICE должны быть определены и взяты либо из файла /etc/sysconfig/network-scripts/ifcfg-eth0, либо получены по DHCP. Нет! Этих переменных там нет!

Ну что я могу сказать? Это Enterprise, детка. Для настройки маршрутов используются графические конфигурялки, баги признают фичами, а в скриптах не допускается самодеятельность, дабы не ввести в заблуждение железобетонную логику системы. Всё как у военных - строго по уставу, не важно что квадратное приходится катать, а круглое таскать.

Может среди прочитавших эту заметку попадутся знатоки Red Hat, CentOS и Fedora? Люди, будьте добры, подскажите, можно ли сделать то, что я хочу, какими-нибудь простыми средствами?

Видимо придётся воспользоваться для настройки маршрутов всё теми-же нестандартными скриптами dhcp-клиента и скриптами /etc/ppp/ip-up.local и /etc/ppp/ip-down.loclal.

Источники:
1. Interface Configuration Files
2. Files in /etc/sysconfig
3. Как избежать неправильной нумерации сетевых карт в системах Red Hat Enterprise Linux с несколькими сетевыми интерфейсами?
4. Как настроить дополнительные маршруты в Red Hat Enterprise Linux?
5. Настройка сети в Linux через конфиг-файлы, ч.1

Дополнение от 30 мая 2010.

При попытке настроить нестандартный скрипт dhclient наступил на selinux, ударивший меня в лоб: он запрещал dhclient'у обращаться к каким-то левым, по мнению selinux, файлам. Разбираться с политиками selinux я не стал и просто отключил его. dhclient после этого сработал нормально. Прописал все настройки pptp, скрипты для добавления и удаления маршрутов. Попытался поднять соединение и обломился: про pptp-клиент я-то забыл. Ну, думаю, сейчас из репов поставлю и всё нормально. Поискал в репах, а pptp-клиента нет! Вот чёрт, опять Enterprise...

пятница, 21 мая 2010 г.

Резервная копия настроек сервера

Всё написанное ниже ни в коем случае не стоит воспринимать как руководство к действию, это лишь информация к размышлению.

Для резервного копирования настроек сервера можно использовать простенький скрипт, ежедневно отправляющий на почтовый ящик резервную копию настроек сервера (для отправки используется пакет biabam). Главное достоинство таких резервных копий - их малый объём, а процесса резервного копирования - очень высокая скорость. Сам скрипт может быть, например, таким:
#!/bin/sh

DATE=`date "+%Y-%m-%d"`

dpkg --get-selections > /root/backups/dpkg.list
mysqldump -u root --password=password --all-databases > /root/backups/mysql.sql

tar -cjvf /root/backup-$DATE.tbz --files-from=- << END
/etc//root/bin/
/home/stupin/bin/
/usr/local/bin/
/var/cache/bind/
/var/spool/cron/crontabs/
/root/backups/dpkg.list
/root/backups/mysql.sql
END
rm /root/backups/dpkg.list /root/backups/mysql.sql

echo "This is a Backup of your Debian Server!!! Keep this!" |\
  biabam /root/backup-`date "+%Y-%m-%d"`.tbz \
    -s "Daily backup Debian Server Configs: $DATE" stupin@mydomain.ru
rm /root/backup-$DATE.tbz
Будьте осторожны, т.к. злоумышленник, получивший доступ к этому сообщению, фактически получает полный доступ к серверу.

Файлик dpkg.list позволяет быстро установить все необходимые пакеты (перед этим лучше сначала перенести учётные записи).
# dpkg --set-selections < dpkg.list
# apt-get dselect-upgrade
Файлик mysql.sql позволяет быстро восстановить состояние БД mysql:
$ mysql -u root --password=password < mysql.sql
Что делать с остальными файлами - я думаю вы догадаетесь сами. Можно, например, сделать rsync нужных каталогов:
$ rsync /root/backup/var/cache/bind/ /var/cache/bind/
Можно сделать rsync каталога /etc/, но тут стоит соблюдать осторожность. Если восстановление происходит на другом оборудовании, то как минимум не стоит бездумно копировать /etc/fstab и /etc/udev/. Если перенос осуществляется ещё и на другую систему, то стоит подумать также о том, можно ли безболезненно скопировать /etc/passwd и /etc/shadow.

суббота, 9 января 2010 г.

Переименование фотографий по EXIF-тегам

В августе-сентябре прошлого года я ездил в отпуск в компании из пяти человек. На всю компанию было два цифровых фотоаппарата. Отдыхали в другом часовом поясе и в середине отпуска мне приспичило выставить на своём фотоаппарате второе время. По приезду из отпуска мы обменялись фотографиями. Я слил все фотографии в один каталог, попутно переименовав их в соответствии со временем из EXIF-тегов.

Время на фотоаппаратах несколько различалось в начале поездки, поэтому итоговые фотографии были слегка перемешаны, к чему я был готов. Но вот что было неожиданным, так это то, что функция двойного времени на моём фотоаппарате не прописывала оба времени в снимок. Если задано одно время, то в EXIF-теги прописывалась информация о первом времени, а если заданы оба времени, то в EXIF-теги прописывалась информация из второго времени. Поэтому кроме небольшого перемешивания в начале, с некоторого момента фотографии с разных фотоаппаратов перемешались с разницей в 2 часа.

Для начала я решил всё вернуть на место и разделить фотографии по фотоаппаратам. Один из фотоаппаратов прописывал в EXIF-теги название модели "Canon PowerShot A560", поэтому я выделил с помощью grep и xargs все фотографии с этого фотоаппарата в отдельный каталог:
$ mkdir canon
$ grep -Ul "Canon PowerShot A560" | xargs -n1 -I'{}' mv '{}' canon/
Оставшиеся фотографии были с первого фотоаппарата и я поместил их в другой каталог под именем olympus.

Далее, просматривая фотографии, я сначала нашёл тот момент, когда я прописал второе время. А затем нашёл два практически одинаковых снимка, сделанных с разных фотоаппаратов, но в разных ракурсах. Так я узнал разницу в синхронизации часов - она составляла 36 секунд.

Теперь о главном. В результате поиска инструмента, который бы мог перевести время в EXIF-тегах, я нашёл утилиту exiftool. Оказалось, что эта утилита не только умеет менять время в EXIF-тегах, но и умеет переименовывать фотографии в соответствии с тегами. Она также поддерживает редактирование не только EXIF-информации из JPEG-файлов, но и редактирование тегов музыкальных файлов, например MP3. Подробнее об утилите можно прочитать здесь: http://www.sno.phy.queensu.ca/~phil/exiftool/. Я же остановлюсь на тех полезных функциях, которые мне пригодились именно для решения моих проблем: корректировка времени в EXIF-тегах и переименование.

Для начала поставим пакет с утилитой:
# aptitude install libimage-exiftool-perl
Теперь, для корректировки времени можно воспользоваться следующей командой (сначала я скорректировал разницу в часах между двумя фотоаппаратами):
$ exiftool "-AllDates-=0:0:0 0:0:36" olympus/moscow-time/
$ exiftool "-AllDates-=0:0:0 0:0:36" olympus/ufa-time/
Потом я ещё раз скорректировал время (ликвидировав разницу в часовых поясах между снимками):
$ exiftool "-AllDates+=0:0:0 2:0:0" olympus/moscow-time/
Знак плюс или минус говорит о том, нужно ли прибавить разницу к показаниям часов или отнять её. Следующие шесть цифр, разделённых двоеточиями и пробелами, указывают разницу в годах, месяцах, днях, часах, минутах и секундах.

И так, теперь время во всех EXIF-тегах фотоснимков синхронизировано и нужно их переименовать. Раньше я это делал с помощью пакета exifprobe, в соответствии с этой статьёй: Цифровые фотографии. Наводим порядок. Однако exiftool оказался способен заменить эту статью одной строчкой:
$ exiftool -r -d %Y%m%d-%H%M%S%%-c.jpg "-filename<DateTimeOriginal" .
Опция -r означает, что фотографии нужно искать и в подкаталогах указанного каталога - рекурсивно.

Строка %Y%m%d кодирует 4 цифры года, две цифры месяца, две цифры дня. Строка %H%M%S кодирует две цифры часов в 24-часовом формате, две цифры минут, две цифры секунд. Строка %%-c используется при наличии нескольких файлов с одинаковым именем, при повторах она добавляет знак минус и номер файла. Строка .jpg указывает расширение файла.

Теперь все фотографии синхронизированы по времени, переименованы в соответствии с датой и временем, одновременно сделанные фотографии снабжены номером.