среда, 13 марта 2013 г.

X11 Forwarding in Solaris 11

В Solaris 11 Express из коробки X11 forwarding разрешен в /etc/sshd/sshd_config - однако не работает (о чем и сообщает при каждой попытке захода на сервер с помощью ssh -X). Для того, чтобы увидеть, в чем проблема, достаточно добавить в командную строку ssh ключ -v В составе системы просто-напросто нет программы xauth.
Поправить беду - как ни странно - можно вполне стандарным способом:
# pkg install xauth
Если после этого перезайти на серевер, сообщение об ошибке больше не выводится, но первая же X-программа, которую я попытался запустить (это была groovyConsole) умерла, сообщив об отсутствии в системе libXrender.so
Но мы уже знаем, что делать:
# pkg install libxrender
После этого groovyConsole запустилась. В процессе поиска в сети решения проблемы достаточно часто мне встречался совет, который и приведу ниже (хотя в моем случае заработало и без этого). Утверждается, что X11 forwarding работает лучше, если явно потребовать от sshd использовать IPv4. Делается это добавлением строки:
ListenAddress 0.0.0.0
в файл /etc/sshd/sshd_config. Применяемая для этой же цели в Linux инструкция:
AddressFamily inet
sshd из поставки Solaris 11 неизвестна.

P.S.: в Solaris 10 аналогичная проблема решается установкой пакетов SUNWxwplt и SUNWxwice (также нужно убедиться, что  /usr/openwin/bin входит в PATH).

вторник, 5 февраля 2013 г.

Pseudo-targets in Groovy AntBuilder


К моему удивлению, ни в 700-страничном фолианте "Groovy in Action", ни в достаточно неплохой документации на сайте языка  не приводится пример создания с помощью AntBuilder полнофункционального проекта (т.е. не просто последовательности выполняемых задач (tasks), а совокупности взаимозависимых целей (target). Анализ имеющихся в сети исходников и сниппетов не дал ничего интереснее, чем псевдо-цели с использованием замыканий (closures). Например, такой код принимает имена задач из командной строки (почти как настоящий ant):

#!/usr/bin/env groovy
DEFAULT = 'jar'
DEST = 'target'
JAR = "$DEST/myapp.jar"
SRC = 'src'
ant = new groovy.util.AntBuilder()
ant.taskdef(name: 'groovyc', classname: 'org.codehaus.groovy.ant.Groovyc')
compile = {
    println '\ncompile:'
    ant.mkdir(dir: DEST)
    ant.groovyc(destdir: DEST, srcdir: SRC, includes: '*.groovy')
}
jar = {
    compile()
    println '\njar:'
    ant.jar(destfile: JAR, basedir: DEST, includes: '*.class')
}  
if (args) for (t in args) this[t]() else this[DEFAULT]()

Самое обидное в том, что в groovy вполне можно написать в таком стиле:

ant.target(name: 'clean') {delete(dir: DEST)}

но паче чаяния такая цель будет выполнена немедленно после объявления - а это совсем не то поведение, которое нам нужно. А из этого unresolved issue в джире кодехауза следует, что путей борьбы с данной странностью разработчики пока не придумали.

среда, 28 ноября 2012 г.

Многопользовательский VNC-сервер на RHEL5


Из коробки в RHEL5 (опыты проводились на Oracle Linux 5.8) для запуска Xvnc предназначена служба vncserver, предполагающая жескую привязку запущенных процессов к пользователям и портам (ея настройки находятся в /etc/sysconfig/vncservers). В данной статье описано более интересеное поведение: Xvnc принимает множественные соединения на одном порту и выводит окно авторизации gdm. При такой конфигурации служба vncserver должна быть остановлена. Далее: добавляем порт vnc в /etc/services:

vnc        5900/tcp

Создаем /etc/xinetd.d/vncserver:

service vnc
{
disable = no
protocol = tcp
socket_type = stream
server = /usr/bin/Xvnc
wait = no
user = nobody
server_args = -inetd –query localhost –once –geometry 1024x768 \
 –depth 16 -SecurityTypes=None
}
(строки, разделенные знаком \, на самом деле составляют одну строку)

И добаляем в /etc/gdm/custom.conf (если их там еще нет) следующие строки:

[security]
AllowRemoteRoot=true
DisallowTCP=false

[xdmcp]
Enable=true
MaxSessions=30

После перезапуска xinetd и gdm должна появиться возможность подсоединиться vnc-клиентом (например, remmina) на порт 5900.
В качестве неизбежных рюшечек избавимся от  гнома по умолчанию (ибо сервер у нас не совсем резиновый). В файл /etc/sysconfig/desktop пишем:

PREFERRED=/opt/bin/xsession.sh

Ну а сам /opt/bin/xsession.sh предоставляем фантазии читателя. Мой минималисткий вариант таков (mwm ставится из пакета openmotif):

#!/bin/sh
vncconfig -iconic &
xclock -bg black -fg green -digital -strftime '%H:%M:%S %d.%m.%y' \
 -geometry -0-0 -update 1 &
xterm -bg black -fg grey -geometry +0+0 &
exec mwm

В комментариях здесь нуждается только вторая строка - без нее не будет работать клипбоард.

вторник, 13 ноября 2012 г.

Pacemaker за 5 минут

Так уж получилось, что и старое, и новое издание Clusters from Scratch описывают слегка не ту конфигурацию, что используется на наших серверах. Поэтому пишу сам себе HOWTO. Задача: поднять двухнодовый кластер с httpd. Платформой служит Oracle Linux 6.3 из коробки.
Предварительные необходимые шаги (без детализации):
  1. отключаем selinux;
  2. разрешаем весь трафик через интерфейсы, по которым узлы будут общаться друг с другом;
  3. убеждаемся, что httpd не запускается при загрузке - и кластерный ip никем не используется;
  4. создаем одинаковый беспарольный RSA-ключ для рута на обеих узлах и взаимно авторизуем его;
  5. устанавливаем pacemaker и corosync через yum.
А теперь - за дело. /etc/corosync/corosync.conf.example содержит почти все нужное. Копируем его без суффикса example, заменяем  bindnetaddr на реальный (это адрес сети, а не хоста - он будет одинаковым на обеих узлах) и добавляем в конец секцию запуска pacemaker:
service {
        name: pacemaker
        ver: 0
}
После этого запускаем corosync:
# service corosync start
И команда
# crm status
должна показать работающий кластер из двух узлов и нуля ресурсов. Corosync будет единственным из кластерных сервисов, запускаемых при загрузке:
# chkconfig corosync on
Все остальное, что мы собираемся запускать в кластере, будет стартовать из-под него. Если первоначальные настройки должны быть сделаны симметрично на обеих узлах, то дальнейшие crm-команды выполняются только на одном из узлов.
Наша примитивная конфигурация требует слегка поменять стандартные настройки кластера. Отключаем STONITH:
# crm configure property stonith-enabled=false
И кворум (иначе в двухнодовом кластере вместе с одним из узлов умрут все сервисы):
# crm configure property no-quorum-policy=ignore
Теперь можно добавлять ресурсы. Переходящий IP-адрес:
# crm configure primitive ip0 ocf:heartbeat:IPaddr2 \
    params ip=10.1.1.251 nic=eth1 cidr_netmask=32 \
    op monitor interval=10s
И веб-сервер:
# crm configure primitive www0 lsb:/etc/init.d/httpd \
    op monitor interval=30s
т.к. наши два ресурса логически связаны (и по смыслу должны запускаться на одном и том же узле), то сгруппируем их: 
# crm configure group g0 ip0 www0
И установим порядок запуска (веб-сервер всегда после адреса):
# crm configure order ip-www inf: ip0 www0
Далее следует сводка простейших команд администрирования кластера.
Если понадобилось вывести узел из кластера (например для апргрейда):
# crm node standby
(Эта и следующая команды выполняются на том узле, которым мы манипулируем - либо третьим аргументом должно быть имя узла). Возвращение в кластер после окончания обслуживания:
# crm node online
Перемещение группы ресурсов на другой узел кластера:
# crm resource move g0
После того, как перемещение закончится, надо выполнить:
# crm resource unmove g0
иначе группа никогда не сможет вернуться на прошлый узел.
Посмотреть на работающий кластер в реальном времени можно командой
# crm_mon

Нуждающиеся в более серьезной документации, чем эта, найдут ее на ClusterLabs.

четверг, 4 октября 2012 г.

/etc как репозиторий Mercurial


Безумная идея видавшего виды админа - а почему бы не приделать к Linux хранение истории правок конфигурации? Для воплощения в жизнь используем CentOS 6.3 и Mercurial 1.4 (он показался мне капельку проще, чем Subversion - и к тому же он хранит репозиторий и рабочую копию рядом - т.е. нам не придется создавать никаких дополнительных директорий и усложнять и без того непростую иерархию). Все последующие команды выполняются от имени суперпользователя - ибо в /etc немало файлов, недоступных для чтения другим пользователям:
# cd /etc
# hg init
# hg add *
# hg commit -m 'add /etc' -u root
Теперь во-первых убеждаемся, что изуродованная таким образом система успешно перезагрузится (хотя кому может помешать директория /etc/.hg?), потом не забудем закрыть эту директорию от обычных пользователей - все-таки наш репозиторий содержит немало такого, что им знать не положено:
# chmod 700 /etc/.hg
И проверяем, как у нас все работает:
# groupadd dummies
# useradd -d /home/dummy -g dummies -p h5CVem3AekREA dummy
# hg diff
Любуемся на изменения:

diff -r 2d2839e14225 group
--- a/group Thu Oct 04 14:08:10 2012 +0400
+++ b/group Thu Oct 04 14:24:47 2012 +0400
@@ -33,3 +33,4 @@
 nfsnobody:x:65534:
 sshd:x:74:
 cgred:x:499:
+dummies:x:500:
diff -r 2d2839e14225 gshadow
--- a/gshadow Thu Oct 04 14:08:10 2012 +0400
+++ b/gshadow Thu Oct 04 14:24:47 2012 +0400
@@ -33,3 +33,4 @@
 nfsnobody:!::
 sshd:!::
 cgred:!::
+dummies:!::
diff -r 2d2839e14225 passwd
--- a/passwd Thu Oct 04 14:08:10 2012 +0400
+++ b/passwd Thu Oct 04 14:24:47 2012 +0400
@@ -18,3 +18,4 @@
 rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin
 nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
 sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
+dummy:x:500:500::/home/dummy:/bin/bash
diff -r 2d2839e14225 shadow
--- a/shadow Thu Oct 04 14:08:10 2012 +0400
+++ b/shadow Thu Oct 04 14:24:47 2012 +0400
@@ -18,3 +18,4 @@
 rpcuser:!!:15617::::::
 nfsnobody:!!:15617::::::
 sshd:!!:15617::::::
+dummy:h5CVem3AekREA:15617:0:99999:7:::
Если все хорошо, записываем их:
# hg commit -m 'add dummy user' -u root
Еще для наглядности можно запустить встроенный веб-сервер:
# hg serve -d
И смотреть на репозиторий станет еще приятнее (только не забудьте сперва закрыть файрволом порт 8000 - ибо едва ли содержимое вашего /etc является зрелищем, достойным внимания всего интернета).

среда, 22 августа 2012 г.

Python MIME-библиотека и строка From в Unix-стиле



При создании тела письма с помощью питоновского класса email.message.Message (и его потомков типа email.mime.base.MIMEBase или email.mime.multipart.MIMEMultipart) первой строкой автоматически добавляется  знакомая каждому старому юниксоиду строка From без двоеточия.
Например:

$ python
>>> import  email.mime.multipart
>>> msg = email.mime.multipart.MIMEMultipart()
>>> print msg

From nobody Wed Aug 22 11:02:28 2012
Content-Type: multipart/mixed; boundary="===============1046125271=="
MIME-Version: 1.0

--===============1046125271==

--===============1046125271==--

Конечно всякий нормальный емейл-клиент реагирует на эту строку спокойно: ведь она существует в мире уже третий десяток лет, но - увы - современный мир полон ненормальными почтовыми клиентами. В одном из их - Lotus Notes 8.5.1 - наличие строки From в заголовке приводит к тому, что MIME-структура письма не отображается - и письмо выводится как простой текст.   
Как заставить Message не включать в письмо данную строку? В документации обнаружено два способа:
  1. прямой. Message имеет метод as_string(self, unix_fromline=False). Если в прошлом примере вместо print msg сделать print msg.as_string() (или - для не надеющихся на умолчательное поведение - print msg.as_string(False)), то мы получим текст сообщения без строки From.
  2. прикольный. Строку From можно заменить любой своей строкой - для этого у нашего класса есть метод set_unixfrom(self, string). Т.к. по стандарту мы можем беспрепятственно добавлять в письмо любые заголовки, начинающиеся с "X-", то сделав что-то типа: msg.set_unixfrom("X-Mailer: Python Is Not Lotu$ Note$") мы получим тело письма, которое ничем не смутит нашего капризного клиента. 

среда, 15 августа 2012 г.

Заработавший rp_filter в CentOS 6.3

Продолжающиеся разборки со свежеустановленной CentOS 6.3 принесли новые неожиданные результаты. Примерная конфигурация такая:
Компьютер администратора имеет ip-адрес 10.1.1.101 в сети 10.1.1.0/24;
Сервер (как раз CentOS 6.3 x86_64) имеет интерфейс eth0 адресом 10.1.1.201 в той же сети и eth1 адресом 10.1.2.201 в сети 10.1.2.0/24.
Маршрутизация между этими сетями настроена, с роутера все три адреса успешно пингуются.
С компьютера администратора пингуется 10.1.1.201, но никак не пингуется 10.1.2.201.
В принципе такое поведение нельзя назвать неправильным - на интерфейсе eth1 оказывается пакет, который по всем правилам должен был прийти на eth0 - и ответа на него не посылается. Другое дело, что за прошлую жизнь админ так привык к неправильному поведению, что правильное ему кажется неудобным. Поиск по настройкам sysctl достаточно скоро находит виновного:
net.ipv4.conf.eth1.rp_filter = 1
Из документа http://linuxgazette.net/issue77/lechnyr.html как раз и явствует что:
The rp_filter can reject incoming packets if their source address doesn't match the network interface that they're arriving on, which helps to prevent IP spoofing.
Установка:
net.ipv4.conf.eth1.rp_filter = 0
приводит к тому, что желанный пинг появляется.
А напоследок - как всегда - самое смешное. В CentOS 5-ой ветки, на которых автор этих строк собственно и успел пристраститься к "неправильным" пингам, установки net.ipv4.conf.*.rp_filter по умолчанию - точно такие же, как и в 6.3. Только не вызывают они заявленного поведения. Одно из двух - либо давно объявленную фичу наконец-то заставили работать, либо где-то таится еще какая-то настройка, которая говорит системе, реагировать ей на rp_filter - или нет.