среда, 21 июля 2010 г.

Вставка нулевых значений в auto_increment поля в MySQL



По умолчанию, если в поле с опцией auto_increment вставляется значение 0 или null, MySQL заменяет его следующим значением счетчика. Если критично важно вставить именно 0, то нам поможет директива:
sql-mode='NO_AUTO_VALUE_ON_ZERO'
в /etc/my.cnf
или строка:
SET sql_mode = 'NO_AUTO_VALUE_ON_ZERO';
в начале файла дампа.

среда, 14 апреля 2010 г.

Странное поведение mktime относительно летнего времени


На опыте столкнулся с тем, что результат, возвращаемый функцией mktime(3) не учитывает перехода на зимнее/летнее время (т.е. результаты для "лета" оказываются на час больше, чем нужно). Проверено на linux 2.6.18 и FreeBSD 8.0 с корректно установленной зоной MSK/MSD - так что, вероятно, именно такое странное поведение соответствует спецификации POSIX. Самое смешное в том, что (в полном соответствии с документацией) функция mktime не только возвращает типа значение time_t, но и "нормализует" содержимое переданной в нее по указателю struct timespec, заполняя совершенно корректными (учитывающеми перевод времени) значениями поля tm_isdst, tm_gmtoff и tm_zone. Очевидно, где-то в этом направлении и лежит путь борьбы с этой функцией. Т.е вместо очевидного:

struct timespec ts;

time_t tm = mktime(&ts);

Пишем теперь так:

struct timespec ts;

time_t tm = mktime(&ts) - ts.tm_isdst * 3600;

Эстетам же и забывчивым можно предложить определить вот такой макрос:

#define mktime(t) (mktime(t) - (t)->tm_isdst * 3600)

и использовать mktime, как обычно.

Еще идеи?

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

Проброс сессии ssh из внешнего мира в немаршрутизируемую сеть (ssh tunnel)



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

Исходные данные

В задаче участвуют три хоста: машина, за клавиатурой которой мы находимся (имя: my-cons, адрес: 11.0.0.11), машина, к которой хотим получить доступ (имя: in-serv, адрес: 10.0.0.10) и машина-шлюз, с которой доступны обе эти машины (имя: gat-serv, адрес: 12.0.0.12). В дальнейшем хост, на котором будет вводиться команда, обозначается приглашением командной строки.
Пусть на всех трех хостах имеется учетная запись bigadm, под которой мы и будем работать. Также предполагается, что на in-serv и gat-serv запущен sshd

О ключах

Т.к. наиболее рациональным способом авторизации в ssh является использование публичных ключей, что напишем, какие ключи, где надо прописать.
  1. ключ my-cons:~bigadm/.ssh/id_rsa.pub должен быть добавлен в in-serv:~bigadm/.ssh/authorized_keys
  2. ключ gat-serv:~bigadm/.ssh/id_rsa.pub должен быть добавлен в gat-serv:~bigadm/.ssh/authorized_keys
  3. т.к. скорее всего процесс настраивается с помощью того же ssh, то ключ my-cons:~bigadm/.ssh/id_rsa.pub не помешает в gat-serv:~bigadm/.ssh/authorized_keys (строго говоря, для решения самой задачи это НЕ необходимо - если у нас напр. при настройке был доступ к консоли этого сервера - или мы производили настройку с какого-то другого хоста).
Сам процесс

Все достаточно просто:
bigadm@gat-serv$ ssh -f -N -g -L 2222:10.0.0.10:22 bigadm@12.0.0.12
(следует обратить внимание на ключ -g - без него 2222 порт открывается на адресе 127.0.0.1 - т.е. туннелем можно воспользоваться только локально - а это вовсе не то, что нам сейчас требуется (хотя применимо напр. для проброса по шифрованному каналу нешифрованного трафика - POP3, etc).
bigadm@my-cons$ ssh -p2222 12.0.0.12
и мы должны оказаться в консоли in-serv.

вторник, 2 февраля 2010 г.

nsswitch.conf для FreeBSD, пересобранной без NIS



Дальнейшие опыты проверены на FreeBSD 8.0

NIS в наше время используется достаточно редко, так что при пересоборке мира существует соблазн добавить в /etc/src.conf строку WITHOUT_NIS=YES (для более ранних версий править надо файл /etc/make.conf). После пересборки с этой опцией все вроде работает, но порой замечаются легкие странности - например, демон cron не отправляет стандартный вывод выполенных комманд по почте, а в /var/log/cron пишет:
NSSWITCH(_nsdispatch): nis, passwd_compat, endpwent, not found, and no fallback provided
Очевидно, проблему надо искать в /etc/nsswitch.conf
Там по умолчанию стоит:
passwd: compat
man-страница nsswitch.conf(5) сообщает, что compat означает подержку в файлах /etc/passwd и /etc/group строк + и - , что на самом деле имеет какой-то смысл только при использовании NIS (кто с ней знаком, помнит, зачем это надо - прочим нормальным людям едва ли необходимо об этом знать). Очевидно, система, собранная без поддержки NIS, просто перестает понимать какой-такой это compat - и пасует. Решение представляется очевидным. Меняем строку на банальное:
passwd: files

...и ожидаем новых сюрпризов. Мораль - хочешь спать спокойно, нечего править /etc/src.conf ;)

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

Postfix + Procmail для виртуальных ящиков


В дальнейшем предполагается, что виртуальные почтовые ящики расположены в директориях вида: /var/virtmail/domainname/username и принадлежат пользователю virtmail

В файле master.cf описываем транспорт procmail (все - в одну строку):

procmail unix - n n - - pipe flags=RO user=virtmail argv=/usr/bin/procmail -t -o SENDER=${sender} -m USER=${user} DOMAIN=${domain} /etc/procmailrc

включаем этот транспорт для виртуальных пользователей в main.cf:

virtual_transport = procmail

procmail_destination_recipient_limit = 1

Последняя опция означает, что письмо, адресованное нескольким получателям, будет "превращаться" во много писем - каждое с одним получателем. Иначе procmail не вполне правильно разбирается с такими множественными письмами.

Теперь самое интересное - что писать в /etc/procmailrc:

SHELL=/bin/sh

PATH=/bin:/usr/bin

MAILDR=/var/virtmail/${DOMAIN}/${USER}/

# на всякий случай создадим эту папку

DUMMY=`test -d $MAILDR | mkdir -m 700 $MAILDR`

# тут какие-то правила, ради которых и прикручивается procmail

# ...


# и последнее правило - куда класть почту по умолчанию:

:0:

${MAILDR}


По ходу экспериментов было замечено, что хранение имени почтовой директории в "стандартной" переменной MAILDIR приводило к необъяснимому поведению при вызове внешней команды - потому было выбрано "усеченное" имя.

вторник, 23 июня 2009 г.

Странная работа резольвера в Xubuntu 9.04


В Xubuntu 9.04 (не из коробки, а после рядя миграций из одной сети в другую) был обнаружена странная работа резольвера: команда
$ host some.host.somedomain.net
находит ip-адрес, а ping (или напр. firefox) при попытке обратиться к этому хосту, говорят, что хост не найден.
Методом тыка было предположено, что проблема - в файле /etc/nsswitch.conf (т.к. утилиты работы с DNS, такие как host, должны его игнорировать, а "нормальные" сетевые команды - наоборот - использовать).
Строка hosts в этом файле из коробки выглядит нечеловечески страшно:
hosts: files mdns4_minimal [NOTFOUND=return] dns mdns4
Что-то не нравился мне этот mdns4_minimal - да еще и return после него - потому меняем на более понятное:
hosts: files dns
после перезагрузки проблема больше не наблюдалась.

понедельник, 4 мая 2009 г.

ПППингвины over Ethernet


Настраиваем PPPoE на Linux

Сервер

Для опытов использовалась OpenSUSE 11.1
Необходимо поставить следующие RPM: ppp, rp-ppoe и freeradius-client. Про то, как настраивать авторизацию на сервере RADIUS уже написано тут.
Проверить, как работает авторизация можно командой
# radexample
(да, именно с правами root - иначе она не сможет прочесть файл конфигурации, но в этом не признается - и выдаст Authentication FAILURE)
Проверив, что все работает, нужно в файле /etc/radiusclient/radiusclient.conf нужно убрать следующие строки (pppd на них сильно ругается):
radius_deadtime 0
bindaddr *
Если мы уберем эти строки заранее, ничего страшного не случится, но от radexample толку не ждите - она выпадет в кору.
Файл параметров сервера /etc/ppp/pppoe-server-options предельно прост:
+chap
-pap
auth
proxyarp
plugin radius.so
Запускается сервер командной строкой:
# pppoe-server -I eth1 -L 10.11.12.13
(стартовый скрипт для него придется сочинять самим)
  1. Первый параметр - интерфейс, на котором ждем подключения клиентов. Он должен быть поднят - иначе pppoe-server не поднимется IP адрес этому интерфейсу может быть как присвоен, так и не присвоен.
  2. Второй параметр - адрес, который будет отдаваться клиентам как адрес конца тоннеля (насколько мне удалось выяснить, он может быть как равен адресу нашего интерфейса - если таковой присвоен - так и не равен ему - на работу это не влияет).
Адреса клиента берем с RADUIS, потому в командной строке ничего не указываем.
Для того, чтобы сервер был реально полоезен, нужно разрешить на нем роутинг. В файле /etc/sysctl.conf пишем:
net.ipv4.ip_forward=1
Аналогичная конфигурация работоспособна на CentOS 5.3 и Ubuntu 9.04 (там пакет, содержащий pppoe-server, называется pppoe). Нужно заметить, что эти системы не нуждаются в прятание строк в файле /etc/radiusclient/radiusclient.conf (для CentOS ищется на http://rpmfind.net пакет radiusclient для fc или el, а в убунте есть аналогичный пакет radiusclient1).

Клиент

Опыты проводились на Ubuntu 9.04
Ничего доставлять не надо - все нужное в дистрибутиве уже есть.
Файл /etc/ppp/peers/pppoe:
user "myname"
defaultroute
replacedefaultroute
noauth
noipdefault
plugin rp-pppoe.so eth0
Последний параметр в последней строке - интерфейс, через который будем выходить на сервер. Он должен быть поднят, ip-адрес на нем может как быть, так и не быть.
Файл /etc/ppp/chap-secrets:
"myname" * "mysecret" *
myname и mysecret - это (как вы догадались) наши имя и пароль на RADIUS-сервере.
Соединение запускам командой:
# pppd call pppoe
Если возникли проблемы, добавляем в конфиг сервера и клиента строчку debug - и получаем довольно неплохой уровень отладочных сообщений.
Аналогичная конфигурация работает на Mandriva 2009.1

P.S. в Mandriva 2009.1 pppoe-server не вполне работоспособен - по крайней мере, мне вообще не удалось заставить его отвечать на LCP Request. Судя по всему, проблема заключается в pppd. Лечится сборкой из исходников ppp-2.4.4.XXXX.rpm для FedoraCore (pppoe плагин в него входит), а файлы в /etc/radiusclient копируются из ${RPMROOT}/BUILD/ppp-X.X.X/pppd/plugins/radius/etc (нюансы этой операции описаны в предыдущем посте).