28 июня 2016 г.

Как отсыпать совсем немножечко рута для Java и разрешить захватывать сетевые пакеты

В различных дистрибутивах Linux такие программы, как tcpdump и wireshark, использующиеся для анализа сетевого трафика, обычно требуют прав суперпользователя для получения доступа к возможностям захвата пакетов. Точно также дело обстоит и с Java-программами, которые используют системную библиотеку libpcap. Причем в этом случае вам придется запустить с неограниченными правами саму виртуальную машину Java, которая уже в свою очередь будет исполнять ваш код. Я думаю, мало кто любит лишний раз сорить суперправами направо и налево, поэтому в Linux, начиная с ядра 2.2 появилась такая штука, как Linux Capabilites, которая позволяет наделить непривилегированные процессы только необходимыми возможностями суперпользователя. В данном случае, например, нас интересует только возможность перехвата и отправки сетевых пакетов. Для установки и просмотра Linux Capabilites необходимы программы setcap и getcap, соответственно. У меня в openSUSE эти утилиты находятся в пакете libcap-progs, а в Ubuntu в пакете libcap2-bin.

Установка возможности захвата и отправки сетевых пакетов и возможности изменения конфигурации интерфейсов выглядит так:
setcap cap_net_raw,cap_net_admin=eip /usr/local/lib64/jdk1.8.0_77/bin/java
Просмотр установленных возможностей:
getcap /usr/local/lib64/jdk1.8.0_77/bin/java
/usr/local/lib64/jdk1.8.0_77/bin/java = cap_net_admin,cap_net_raw+eip
Всё просто, но если после установки этих возможностей попробовать запустить программу java из под обычного пользователя, то это не очень получится:
java -version
java: error while loading shared libraries: libjli.so: cannot open shared object file: No such file or directory
Это происходит из-за того, что при наличии у непривилегированного процесса возможностей, которыми он вроде как обладать не должен, загрузчик динамических библиотек запрещает загрузку библиотек из недоверенных каталогов. Доверенными каталогами по умолчанию являются /lib и /usr/lib (а также /lib64 и /usr/lib64).

С помощью утилиты ldd посмотрим, какие динамические библиотеки использует java: 
ldd /usr/local/lib64/jdk1.8.0_77/bin/java
        linux-vdso.so.1 (0x00007ffc91ffd000)
        libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fc3dc124000)
        libjli.so => /usr/local/lib64/jdk1.8.0_77/bin/../lib/amd64/jli/libjli.so (0x00007fc3dbf0d000)
        libdl.so.2 => /lib64/libdl.so.2 (0x00007fc3dbd09000)
        libc.so.6 => /lib64/libc.so.6 (0x00007fc3db961000)
        /lib64/ld-linux-x86-64.so.2 (0x00005584e041d000)
Как видно из вывода команды ldd, при запуске java не удалось загрузить как раз ту самую библиотеку, которая находится в недоверенном каталоге ../lib/amd64/jli/.

Это можно легко пофиксить, добавив файл с расширением .conf  в каталог /etc/ld.so.conf.d, в котором перечислить все необходимые пути. В случае с java это всего лишь один каталог:
echo /usr/local/lib64/jdk1.8.0_77/lib/amd64/jli > /etc/ld.so.conf.d/java.conf
После изменения файлов в /etc/ld.so.conf.d может потребоваться перестроить кэш библиотек, для этого нужно выполнить:
ldconfig
Проверяем, что загрузчик видит нашу библиотеку:
ldconfig -v |grep jli
/usr/local/lib64/jdk1.8.0_77/lib/amd64/jli:
     libjli.so -> libjli.so
Ну и на всякий случай, команда для удаления всех дополнительных возможностей у программы:
setcap -r /usr/local/lib64/jdk1.8.0_77/bin/java
Ещё хотелось бы отметить, что не стоит без лишней необходимости добавлять нестандартные возможности вашей глобальной системной Java-машине, потому что в этом случае любая запущенная Java-программа сможет ими воспользоваться. Для разработки и запуска программ с завышенными потребностями лучше завести отдельный экземпляр Java-машины.

Где отрыто

Как приструнить Wireshark
Небаг в багтрекере Java
Куришка: man capabilities


28 марта 2016 г.

Установка Java Development Kit в Linux из архива tar.gz

Данный пост, это просто обновление поста 2010 года, который до сих пор пользуется довольно большой популярностью, а так как с тех времен уже немало воды утекло, то я посчитал своим долгом актуализировать эту информацию. По пути также кое-что было переработано, надеюсь, в сторону понятности.
Если вам потребовался стандартный JDK от Oracle, вместо OpenJDK, который поставляется с современными свободными дистрибутивами Linux, то его можно скачать либо с дополнительных сторонних репозиториев для вашего дистрибутива, либо напрямую с сайта www.oracle.com. Если ставить Java из репозиториев для вашего дистрибутива, то скорее всего всё само настроется и заработает, и ни о чем беспокоится вам не придется, но если вы скачали JDK или JRE в виде архива tar.gz с сайта Oracle, придется совершить несколько дополнительных телодвижений.

На данный момент скачать JDK с сайта Oracle можно в двух видах: это RPM-пакет и вышеупомянутый архив tar.gz. Про то, на сколько удачно ставится JDK из RPM-пакета, мне сказать нечего - не пробовал. Я предпочитаю устанавливать JDK именно из архива, потому что так я получаю полное управление и понимание того, что и откуда у меня будет запускаться, а также универсальное решение, которое подойдет для всех дистрибутивов, а не только для RPM-based.

План действий
  1. Скачать нужную версию JDK (архив tar.gz)
  2. Распаковать архив
  3. Настроить переменные окружения
  4. Настроить update-alternatives
Куда распаковать?

Итак, скачали JDK. Распаковываем. Но куда? Вроде бы тупой вопрос, но я далеко не сразу пришёл к правильному  для себя  решению. Сейчас я все JDK распаковываю в каталог /usr/local/lib64 и там у меня одновременно живёт несколько версий JDK. Например, на данный момент, там у меня есть каталоги jdk1.7.0_79 и jdk1.8.0_77. В дополнение к этим каталогам, в /usr/local/lib64 у меня находится симлинк с именем jdk, который сегодня чаще всего указывает на каталог jdk1.8.0_77. К такой конфигурации я пришел, когда потребовалось периодически переключаться между различными версиями JDK, причем переключаться нужно было глобально во всей системе. Каким образом такая конфигурация помогает переключаться между версиями, станет понятно ниже.

13 февраля 2016 г.

USB redirection error в Spicy на openSUSE

Столкнулся в openSUSE с тем, что в gtk-клиенте для spice не работает проброс USB-устройств внутрь гостевой системы. После выбора устройства для проброса появляется окно с просьбой ввести пароль суперпользователя. Вводим пароль, жмём OK и получаем сообщение вроде этого:
Could not redirect Kingston DataTraveler 3.0 [0951:1666] at 2-13: Error setting USB device node ACL: 'Error setting facl: Operation not permitted'
Оказывается, что в пакете spice-gtk вместе с клиентом spicy есть еще такая программка с длинным названием spice-client-glib-usb-acl-helper. При подключении USB-устройства через spicy эта программа, по всей видимости, проверяет и назначает файлу этого устройства дополнительные права через ACL. Проблема в том, что для этого не помешало бы быть root'ом, но не смотря на запрос пароля суперпользователя, spice-client-glib-usb-acl-helper выполняется с правами обычного пользователя из-под которого запущен spicy. Короче, где-то недокостылили. Самым простым решением этой проблемы является установка бита setuid на файл spice-client-glib-usb-acl-helper:
chmod u+s /usr/bin/spice-client-glib-usb-acl-helper
После этого действия USB-устройства начинают успешно пробрасываться.

Для удобства теперь можно также отключить запрос пароля суперпользователя. Делается это через polkit. В файле /usr/share/polkit-1/actions/org.spice-space.lowlevelusbaccess.policy надо отредактировать содержимое элемента defaults следующим образом:



23 августа 2015 г.

Skype 4.3 без PulseAudio

Как известно, Microsoft безжалостно выпилила поддержку ALSA из Skype 4.3. А я, в свою очередь, недавно пару вечеров старательно выпиливал этот PulseAudio из openSUSE 13.2, после того, как никакими молотками и "волшебными" русскими словами не смог заставить этот самый PulseAudio видеть порт line-in на старой карте видео-захвата. Кроме того, я попытался снять звук обычной звуковой картой и получил на записи великолепный белый шум, хотя ожидал услышать немного другое.

После "лечения" системы от PulseAudio осталась только одна проблема - неработающий Skype. В интернетах сразу нашел совет использовать эмулятор PulseAudio для ALSA - apulse. Нормальный такой рабочий костыль. Один из вариантов настройки apulse заключается в создании файла ~/.asoundrc. У меня он, например, такого содержания:

pcm.!default {
  type asym
    playback.pcm {
      type plug
      slave.pcm "hw:1,0"
    }
    capture.pcm {
      type plug
      slave.pcm "hw:3,0"
    }
}

Где "hw:1,0" и "hw:3,0" это ALSA-идентификаторы устройств воспроизведения и захвата звука, соответственно. Но такой подход оказался не очень удобным, потому что в компьютере у меня одновременно было 2 устройства воспроизведения и 3 устройства захвата звука. И если ID основного устройства для вывода звука оказывался всегда "hw:1,0", то нужное устройство захвата периодически оказывалось то с ID "hw:3,0", то "hw:2,0". Ну и, понятное дело, чтобы Skype начал получать звук с правильного устройства, надо было поменять его ID в файле .asoundrc и после этого перезапустить Skype через apulse:

apulse skype

Наверное, можно прибить гвоздями все ID к соответствующим звуковым устройствам через UDEV, но как-то мне всегда лень "лазить через Google" в его конфиги. Поэтому предлагаю более простой и универсальный вариант динамической настройки apulse.

Он основывается на том, что указать устройства для apulse можно с помощью установленных переменных окружения APULSE_PLAYBACK_DEVICE и APULSE_CAPTURE_DEVICE. А с помощью программ aplay и arecord можно легко выдернуть циферки, которые присвоены вашим звуковым устройствам.

Например, вот мой вывод команды aplay -l:

**** List of PLAYBACK Hardware Devices ****
card 0: HDMI [HDA Intel HDMI], device 3: HDMI 0 [HDMI 0]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 0: HDMI [HDA Intel HDMI], device 7: HDMI 1 [HDMI 1]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 0: HDMI [HDA Intel HDMI], device 8: HDMI 2 [HDMI 2]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 1: PCH [HDA Intel PCH], device 0: ALC1150 Analog [ALC1150 Analog]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 1: PCH [HDA Intel PCH], device 1: ALC1150 Digital [ALC1150 Digital]
  Subdevices: 1/1
  Subdevice #0: subdevice #0

Интересующее меня устройство вывода называется ALC1150 Analog. Команда play -l говорит что ему присвоены идентификаторы card 1 и device 0. Из этих сочетаний в моем случае надо сформировать имя "hw:1,0". В других дистрибутивах имя может строиться немного по-другому, например, "plughw:1,0".

Таким образом, всё что надо сделать это выдернуть циферки, назначенные устройствам воспроизведения и захвата, сформировать для них валидные ALSA-идентификаторы и записать их в соответствующие переменные окружения. Автоматизировать эту процедуру можно добавлением следующих строчек в ваш файл ~/.profile, который будет выполнятся при каждом входе в систему под вашим именем:

PLAY_DEV_NAME="ALC1150 Analog"
REC_DEV_NAME="U0x46d0x804"

PLAY_CARD=`aplay -l |grep "$PLAY_DEV_NAME" | grep -E -o "card +[0-9]+"`
PLAY_DEV=`aplay -l |grep "$PLAY_DEV_NAME" | grep -E -o "device +[0-9]+"`
APULSE_PLAYBACK_DEVICE="hw:${PLAY_CARD##card },${PLAY_DEV##device }"

REC_CARD=`arecord -l |grep "$REC_DEV_NAME" | grep -E -o "card +[0-9]+"`
REC_DEV=`arecord -l |grep "$REC_DEV_NAME" | grep -E -o "device +[0-9]+"`
APULSE_CAPTURE_DEVICE="hw:${REC_CARD##card },${REC_DEV##device }"

export APULSE_PLAYBACK_DEVICE APULSE_CAPTURE_DEVICE

Только нужно поменять значения переменных PLAY_DEV_NAME и REC_DEV_NAME на имена ваших устройств.



29 июня 2015 г.

Eclipse Mars, GTK+ 3, Adwaita и маленький CSS-напильник

С переходом на новый Eclipse Mars, я решил кое-что ещё поменять в своей жизни. Хотя правильнее сказать, что сам Eclipse предложил мне эти изменения, а я не стал сопротивляться. Как известно, Eclipse Mars теперь по умолчанию использует GTK+ версии 3. Для второй версии GTK+ у меня уже много лет стоит тема oxygen-gtk. Страшненькая, да... но уже привычная. Поэтому как-то даже мысли не возникало попробовать поменять её. А тут оказалось, что для GTK+ 3 у меня вообще эта тема не стоит, и используется тема по умолчанию, которая называется Adwaita. И что-то я так поглядел на неё, и в принципе мой глаз посчитал её чуть менее страшной и чуть более секси, чем oxygen-gtk. Осталось только решить несколько бросившихся сразу в глаза проблем.

Проблемы

Проблема 1. Какое-то неадекватно большое значение padding у большинства GUI-элементов.


Проблема 2. Странный tooltip для javadoc с белым шрифтом на чёрном фоне.

 
Проблема 3. Смазанные шрифты после скролинга некоторых окон (Project Explorer, Package Explorer, Outline). Особенно ярко проблема проявляется, если скролить колесом мыши.


Решение

В GTK+ 3 для описания тем больше не используются rc-файлы собственного формата. Теперь для стилизации применяются более понятные CSS-подобные файлы.

Проблемы 1 и 2 решаются созданием файла ~/.config/gtk-3.0/gtk.css со следующим содержанием:
* {
    padding: 1px;
}

GtkToolbar {
    padding: 2px;
}

GtkMenuBar {
    padding: 2px;
}

GtkMenuItem {
    padding: 2px 6px;
}

.tooltip {
    background-color: #CAE1FF;
    color: #333;
    text-shadow: none;
}

Кратко поясню. Сначала устанавливаем padding абсолютно для всех элементов равным 1px. Затем для элементов GtkToolbar, GtkMenuBar и GtkMenuItem делаем отступы чуть более разумными. CSS-класс tooltip вероятно прописан где-то в коде и назначен, как для всплывающего окна javadoc, так и для хинтов различных графических элементов. Свойство text-shadow необходимо, чтобы ликвидировать тень текста хинта, которая становится заметной и неуместной после изменения его фона и цвета текста:


Обратите внимание, что файл ~/.config/gtk-3.0/gtk.css будет действовать и переопределять стили для любой темы GTK+ 3, выбранной пользователем, у которого в домашнем каталоге есть этот файл, а не только для темы Adwaita.

Проблему 3 я решил довольно тупо, сняв флажок с Use mixed fonts and colors for labels в настройках внешнего вида (Window / Preferences / General / Appearance). Мне легче смириться с одноцветным черным лейблом, чем с таким поломанным шрифтом.

Тут я вынужден обновить сообщение и добавить, что после решения проблемы 3 появилась проблема 4 :) которая выглядет, как практически нечитаемый выбранный пункт во всплывающем окне автодополнения.


Эта неприятность также фиксится добавлением некоторых строчек в gtk.css:
GtkTreeView:selected {
    color: #FFF;
    background-color: #4A90D9;
}

Результаты






Ссылки

Тем, кто захочет ещё что-нибудь подкрутить или сделать более тонкую настройку, а не такую кувалдообразную, как у меня, рекомендую сначала заглянуть сюда, и конкретно вот сюда. А ещё здесь интересно.

Когда терпение кончилось

Спустя некоторое время, должен признать, что это далеко не все глюки с UI, которые мне повстречались при использовании GTK+ 3 в Eclipse. И у меня больше нет сил подкручивать эти гайки. Я устал, я ухожу. Теперь перед запуском Eclipse у меня выполняется export SWT_GTK3=0, что заставляет Eclipse использовать GTK+ 2 по старинке.

10 июня 2015 г.

Перенос существующей базы данных Redmine с SQLite на PostgreSQL

Разглагольствовать не буду. Скажу лишь, что попробовал несколько различных способов, кроме ручного исправления дампа SQLite, ибо лень. Самым простым и жизнеспособным оказался метод с использованием программы Taps. Эта чудо-ruby-штука поднимает http-сервер с подключением к базе данных А и позволяет с помощью клиента выполнять обмен данными между этой базой А и какой-либо базой Б, даже если они управляются различными СУБД. Конечно, её возможности не безграничны, но для миграции базы данных Redmine их хватило.

Все ниже описанные действия выполнялись на openSUSE 13.2.

Кратко и по сути

1. Установить через RubyGems программу Taps:
gem install taps
2. Подготовить базу данных PostgreSQL для Redmine:
createuser -U postgres redmine
psql -U postgres
postgres=# ALTER USER redmine WITH PASSWORD 'redmine_password';
postgres=#\q
createdb -U postgres -O redmine redmine
3. Запустить сервер Taps с подключением к новой созданной в PostgreSQL базе для Redmine:
taps.ruby2.1 server postgres://redmine:redmine_password@localhost/redmine taps taps_password
4. Используя клиент Taps, запушить все данные из исходной базы SQLite в PostgreSQL:
taps.ruby2.1 push sqlite:///usr/local/redmine/db/redmine.db.sqlite3 http://taps:taps_password@localhost:5000
5. Не забыть изменить настройки подключения к БД в Redmine (redmine/config/database.yml):
production:
  adapter: postgresql
  database: redmine
  host: localhost
  username: redmine
  password: "redmine_password"
5. Перезапустить Redmine

Грабли

При запуске сервер валится приблизительно с такой портянкой:
/usr/lib/ruby/gems/2.1.0/gems/sinatra-1.0/lib/sinatra/base.rb:298:in `': uninitialized constant Tilt::CompileSite (NameError)
        from /usr/lib/ruby/gems/2.1.0/gems/sinatra-1.0/lib/sinatra/base.rb:297:in `'
        from /usr/lib/ruby/gems/2.1.0/gems/sinatra-1.0/lib/sinatra/base.rb:21:in `'
        from /usr/lib/ruby/2.1.0/rubygems/core_ext/kernel_require.rb:73:in `require'
        from /usr/lib/ruby/2.1.0/rubygems/core_ext/kernel_require.rb:73:in `require'
        from /usr/lib/ruby/gems/2.1.0/gems/taps-0.3.24/lib/taps/server.rb:1:in `'
        from /usr/lib/ruby/2.1.0/rubygems/core_ext/kernel_require.rb:73:in `require'
        from /usr/lib/ruby/2.1.0/rubygems/core_ext/kernel_require.rb:73:in `require'
        from /usr/lib/ruby/gems/2.1.0/gems/taps-0.3.24/lib/taps/cli.rb:61:in `server'
        from /usr/lib/ruby/gems/2.1.0/gems/taps-0.3.24/lib/taps/cli.rb:27:in `run'
        from /usr/lib/ruby/gems/2.1.0/gems/taps-0.3.24/bin/taps:6:in `'
        from /usr/bin/taps.ruby2.1:23:in `load'
        from /usr/bin/taps.ruby2.1:23:in `
'
В этом случае необходимо проверить какие версии библиотеки Tilt у вас установлены:
zypper se -s tilt
Если среди установленных есть Tilt версии 2, то необходимо её снести и поставить 1.4. Как правило, zypper сам ставит версию 1.4 вместо удалённой 2.

Ещё

Уже после публикации этой статьи, я наткнулся ещё на одну чудо-ruby-штуку под названием YamlDb. Жалко, что она сразу мне не попалась, меньше бы времени потратил. И на Хабре давно уже есть статейка.

11 октября 2014 г.

Автоматический запуск скриптов при подключении NetworkManager

Я очень долго отказывался от использования NetworkManager (далее NM) и жил с традиционным и понятным ifup. Но теперь, пожалуй, пришло время приобщиться к цивилизации. Тем более, что NM стал уже не такой сурово глючный, как раньше, да и что там говорить, удобно на ноутбуке перещёлкиваться между проводом, WiFi и GSM-модемом.

Единственной преградой на пути к благам цивилизации для меня было то, что мне приходится использовать программу VTun для создания туннеля между домом и работой, через который я также хожу в глобальную сеть, а NM не поддерживает VTun из коробки. Конечно, всегда можно наваять пару скриптов, которые будут периодически смотреть поднятые интерфейсы, пинговать различные ip-адреса и заниматься прочими делами, чтобы понять в каком состоянии находится сеть. Но, как оказалось, можно решить эту задачу и более красивым способом с помощью NetworkManager Dispatcher Service. В systemd он обычно имеет имя NetworkManager-dispatcher.service.

NetworkManager Dispatcher Service это сервис, который при изменении состояния NM, дёргает скрипты из каталога /etc/NetworkManager/dispatcher.d и передает в них в качестве параметров командной строки имя сетевого интерфейса, у которого изменилось состояние, и новое значение этого самого состояния - up или down (vpn-up и vpn-down для VPN-соединений). 

4 апреля 2014 г.

Баг с shortcut'ами в qt4

Вдруг странным образом перестали работать сочетания клавиш в qt-программах. Например Ctrl+C, Ctrl+V, Ctrl+X в Dolphin или Ctrl+Alt+T в Yakuake. Скорее всего, к этому списку относятся все сочетания с участием Ctrl и Alt. Оказалось, что ковыряясь в настройках раскладки KDE после сноса бесполезного ibus, я переместил русский язык на первое место, тем самым сделав его раскладкой по умолчанию. Возвращение US-раскладки в зад, т.е. на первую строчку, всё чинит. Такая вот багулька.


29 октября 2013 г.

Выбор года и месяца в GWT DatePicker с помощью ListBox

Стандартный DatePicker в GWT очень неудобный. Для выбора нужного года и месяца пользователь вынужден кликать по соответствующим стрелочкам и перемещаться на один месяц вперед или на зад. Например, если пользователю необходимо выбрать свою дату рождения, скажем, 29 февраля 1980 года, а в календаре по умолчанию установлена текущая дата 25 октября 2013 года, то представьте сколько раз нужно будет кликнуть бедняге по стрелочке, чтобы добраться до дня своего рождения!
Стандартный DatePicker в GWT
Конечно, в качестве простого решения, можно просто дать пользователю возможность ввести дату самому в текстовое поле. И в общем-то нет, наверное, ничего плохого в таком решении. Но иногда просто хочется сделать немного более красиво. В этом смысле Datepicker из jQuery UI вполне себе красив и позволяет выбирать год и месяц с помощью выпадающих списков, что очень сокращает путь до необходимой даты.

jQuery Datepicker
На самом деле, такую же возможность очень несложно реализовать и в GWT DatePicker. Для этого нужно просто написать свою собственную реализацию абстрактного класса MonthSelector, который представляет из себя визуальный компонент, отвечающий за установку текущего года и месяца в DatePicker. 

2 октября 2013 г.

Небезопасно посылаем e-mail из bash'a используя сторонний smtp

Как известно, все настоящие админы лентяи, в хорошем смысле этого слова. По этой причине они стараются автоматизировать всё что можно и что нельзя. Одним из главных инструментов тотальной админоавтоматизации является ужасно прекрасный (или прекрасно ужасный) bash. Огромная куча поэтично сложенных bash-скриптов постоянно трудится без обеда, что бы админ мог изучить что-то новое или просто почитать Хабр :) Но бывает так, что случается беда и столкнувшийся с ней скрипт обязан призвать админа для спасения организации. Призывом админа проще, конечно же, заниматься посредством e-mail. Только не всегда есть желание ставить и настраивать какой-нибудь postfix на каждой машине, которая должна оповещать админа о проблемах. Иногда просто хочется одной командой послать письмо, использовав уже настроенный smtp организации. Сделать это можно при помощи программки msmtp. Я применяю этот подход только для использования smtp, находящегося внутри локальной сети организации, т.к. он не очень правильный с точки зрения безопасности, но в качестве примера покажу, как можно отправлять письма используя гугловский smtp.

Пример:
#!/bin/bash

printf "Subject:%b\nFrom:%b\nTo:%b\n%b\n" \
       "From good admin" "someuser@gmail.com" "ded@moroz.ru" \
       "Hello Ded Moroz! I worked hard all year, and so I want to get a red bike for the New Year!"|\
msmtp -t --host=smtp.gmail.com \
      --port=587 \
      --user=someuser \
      --passwordeval="echo some_incredible_password" \
      --from=someuser@gmail.com \
      --tls=on \
      --tls-certcheck=off \
      --auth=on 

Наверное, тут практически всё ясно и без слов, но немного поясню. Команда printf формирует само письмо, состоящее из заголовков Subject, From, To и тела письма, после чего вывод перенаправляется в команду msmtp, которая и отправляет письмо.

Параметры msmtp:
    -t - заставляет программу msmtp брать адреса назначения из заголовков To, Cc и Bcc
    --host - smtp-сервер, который надо использовать для отправки
    --port - порт smtp-сервера
    --user - пользователь
    --passwordeval - команда, которая выводит пароль на стандартный вывод
    --from - отправитель письма
    --tls - включает/выключает TLS/SSL шифрование
    --tls-certcheck - включает/выключает проверку сертификата
    --auth - включает/выключает аутентификацию

Заголовки Subject, From и To можно и не создавать, просто в таком случае письмо будет без темы и поля To, а в качестве From будет установлено значение параметра --from. Но так делать некрасиво :)

Параметр -t тоже можно не использовать, а вместо него в качестве последних параметров через пробел указать адреса, на которые нужно отправить письмо.

Если не указать параметр  --passwordeval, то при запуске команды нужно будет ввести пароль руками.

Исходя из вышесказанного, можно переделать процедуру отправки письма как-нибудь так:
#!/bin/bash

printf "%b\n" \
       "Hello Ded Moroz! I worked hard all year, and so I want to get a red bike for the New Year!"|\
msmtp --host=smtp.gmail.com \
      --port=587 \
      --user=someuser  \
      --from=someuser@gmail.com \
      --tls=on \
      --tls-certcheck=off \
      --auth=on \
      ded@moroz.ru \
      santa@klaus.com

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

1 августа 2013 г.

Патчим драйвер NVIDIA 319.32 для ядра Linux 3.10

Обновил себе ядро Linux до версии 3.10 и, как это всегда бывает в таких случаях, после перезагрузки нужно было пересобрать драйвер NVIDIA. Однако, оказалось, что последний драйвер NVIDIA (на этот момент версии 319.32) не поддерживает моё новое ядро. Вариантов в таком случае два: даунгрэйдить ядро до 3.9 или патчить драйвер NVIDIA (если есть чем патчить). Так уж сложилось, что даунгрэйдить я очень не люблю, а вот к добрым ребятушкам, которые в свободное время пописывают всякие патчи и улучшают наш тленный мирок, испытываю самые тёплые и нежные чувства. Конечно же, патч решающий мою проблему, был уже давно написан и выложен, за что автору большое спасибо. Осталось только разобраться, как его использовать. Разобрался. Делюсь.

Качаем патч, например, в домашний каталог. По умолчанию имя будет pastie-7942599.diff.

Распаковываем все внутренности скрипта с драйвером:

> NVIDIA-Linux-x86-319.32.run -x
Creating directory NVIDIA-Linux-x86-319.32
Verifying archive integrity... OK
Uncompressing NVIDIA Accelerated Graphics Driver for Linux-x86 319.32...

Переходим в созданный каталог:

> cd NVIDIA-Linux-x86-319.32

Патчим драйвер:

> patch -p1 < /home/user/pastie-7942599.diff
patching file kernel/nv-i2c.c
patching file kernel/nv-procfs.c
Hunk #4 succeeded at 161 with fuzz 1.

Выходим из каталога с драйвером:

> cd ..

Запаковываем наши пропатченные кишочки обратно:

> ./NVIDIA-Linux-x86-319.32/makeself.sh --target-os Linux --target-arch x86 NVIDIA-Linux-x86-319.32 NVIDIA-Linux-x86-319.32-patched-3.10.run "NVIDIA Accelerated Graphics Driver patched for Linux-x86 3.10 kernel" ./nvidia-installer

Устанавливаем пропатченный драйвер, как обычно:

> sh NVIDIA-Linux-x86-319.32-patched-3.10.run

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


15 ноября 2012 г.

Сборка jNetPcap из исходников в openSUSE 12.1

Набрел тут на интересную java-обёртку для libpcap. Называется она jNetPcap. По описаниям и примерам выглядит достойно. Но главное, что в отличие от Jpcap, с которой я как-то давненько имел интимные отношения, jNetPcap продолжает развиваться.

Если кто не в курсе, кратко поясню, что libpcap это библиотека для захвата и анализа пакетов, проходящих через сетевые интерфейсы. Её, например, используют такие программы, как wireshark, tcpdump, nmap, ipcad и многие другие.

На сайте разработчиков, есть готовые сборки для Ubuntu, RedHat Enterprise, Fedora и Windows. Архив сборки содержит два интересующих меня файла jnetpcap.jar и libjnetpcap.so. Сборка для Fedora сомнительно, но гордо называется Linux (Generic). Сначала я попробовал именно её. При запуске примера она искала libpcap.so.0.9, но ничего не нашла, т.к. у меня стоит версия 1.3.0. В принципе, простой симлинк в /usr/lib libpcap.so.0.9 -> libpcap.so.1.3.0 решает проблему, и пример начинает работать, но что-то меня смущает такая большая разница в версиях libpcap. Поэтому пришлось собирать jNetPcap из исходников.

Сборка прошла не совсем гладко, поэтому оставлю тут для себя, а может и ещё для кого, заметку поэтому поводу.

Теперь кратко о проблемах:
  1. При попытке собрать jnetpcap.jar (команда ant build-jar):
    [taskdef] Could not load definitions from resource cpptasks.tasks. 
    It could not be found.
    
    [typedef] Could not load definitions from resource cpptasks.types.
    It could not be found.
    
    build.xml:119: taskdef class org.vafer.jdeb.ant.DebAntTask cannot be found 
    using the classloader AntClassLoader[]
    
  2. При попытке собрать libjnetpcap.so (команда ant comp-jni-linux):
    [cc] /home/eqlbin/SRC/jnetpcap-src-1.3.0-1/src/c/jnetpcap.cpp:996:6: 
    error: invalid suffix "xpackage" on integer constant
    
    [cc] :0:1: error: "not" cannot be used as a macro name as it is an
    operator in C++
    
Я, честно говоря, не совсем понял, как надо правильно настраивать сборку по мнению самих разработчиков, и в документации ничего путного не нашлось, а долго ковырять чужой билд-скрипт и проперти-файлы желания большого не было, поэтому проблемы решил так как получилось :)

Для сборки, помимо JDK, понадобятся такие естественные штуки, как gcc, gcc-c++, libpcap-devel, ant, ant-junit, ant-contrib. Возможно я что-то упустил, но это основное.

Поехали:
  1. Качаем и распаковываем исходники jNetPcap в гипотетический каталог ~/jnetpcap-src
  2. Качаем cpptasks для ant и кладём файл cpptasks.jar например в ~/jnetpcap-src/lib
  3. Дальше, если у вас есть желание создать из всего хозяйства файл deb, то понадобится найти библиотеку jdeb.jar с соответствующими тасками для ant. Её можно найти уже собранную или же собрать самому. У меня такого желания не образовалось, поэтому я просто  закомментировал строку в файле build.xml:
  4. Теперь необходимо подправить build.xml, чтобы ant смог найти cpptasks.jar и jdeb.jar (если вы, используете jdeb и не закомментировали строку, как в п.3): Вот это: Надо привести к виду, вроде этого: Всё, конечно, зависит от того, как называются ваши jar-файлы и где они лежат... Короче, думаю, что и так тут всё ясно.
  5. Добавить в файл Linux.properties строку compiler.LIBPCAP_VERSION = 100
  6. Запустить ant clean comp-jni-linux build-jar
  7. Забрать из ~/jnetpcap-src/build/lib вожделенные jnetpcap.jar и libjnetpcap.so (там еще у меня появился файл libjnetpcap.so.1.3.0, но судя по его размеру, это тот же libjnetpcap.so)

P.S. - Если build.xml кажется вам страшным и непонятным, почитайте это.

28 апреля 2012 г.

Автоматическое создание Runnable JAR в Eclipse и ресурсы

Когда разрабатывается относительно небольшое десктопное приложение на Java, частенько возникает вполне, на мой взгляд, естественное желание запихать все классы, библиотеки и ресурсы в один исполняемый JAR-файл. В некоторых случаях именно такое решение является предпочтительным.

В Eclipse IDE это можно сделать очень легко и, кроме того, автоматизировать это действие, чтобы в дальнейшем делать сборку JAR одной кнопкой.

Сборка 

Кликаем правой кнопкой по проекту, который надо упаковать в исполняемый JAR и нажимаем Export.

В окне выбираем Java -> Runnable JAR и жмём Next

11 апреля 2012 г.

Установка Magnolia Community Edition из WAR-файла

Magnolia Community Edition на первый взгляд очень достойная современная WCMS с открытым исходным кодом. Для её познания есть довольно неплохая документация и wiki. Однако, есть у меня подозрения, что эта штука не относится к числу простых и легкоподнимаемых CMS. Но выглядит, повторюсь, очень достойно. Пока что просто установим её под Linux.

Установка Magnolia CMS

1. Скачать и распаковать Apache Tomcat в какой-либо каталог, который далее будет обозначаться [tomcat]
2. В каталоге [tomcat]/bin создать исполняемый файл setenv.sh, со строкой export CATALINA_OPTS="$CATALINA_OPTS -XX:MaxPermSize=256m -Xms128M -Xmx768M -Djava.awt.headless=true"
Файл setenv.sh будет автоматически выполнен при запуске tomcat и JVM будет запущена с аргументами, которые указаны в файле. Кратко о каждом:
  • -Xms128M и -Xmx768M устанавливают, соответственно, минимальный и максимальный размер кучи. Параметр -Xms128M не особо обязательный, если речь не идёт о повышении производительности, а вот без -Xmx768M установка Magnolia скорее всего будет падать с java.lang.OutOfMemoryError: Java heapspace.
  • -XX:MaxPermSize=256m увеличивает размер области памяти, которая называется Permanent Generation. Эта память не относится к куче, в ней хранятся классы, методы и другие полезные вещи. Если до установки Magnolia не увеличить эту область памяти, то установка будет валиться с java.lang.OutOfMemoryError: PermGen space.
  • -Djava.awt.headless=true пригодится, если Magnolia будет запускаться на сервер, на котором не запущены Иксы.
После завершения установки, выделяемую память, вероятно, можно немного уменьшить, но это надо проверять.
3. Скачать WAR-файл с Magnolia. На данный момент последний доступный это magnolia-bundled-webapp-4.5.2.war.

4. В каталог [tomcat]/webapps положить две копии этого файла под именами magnoliaAuthor.war и magnoliaPublic.war.
При запуске tomcat magnoliaAuthor будет автоматически сконфигурирована как приватная авторская часть CMS, а magnoliaPublic как публичная. Авторская часть, как и в любых других CMS, используется для подготовки публикаций, которые могут создаваться постепенно и во время создания быть недоступны публично. При этом сам автор может просматривать то, что у него получается в ходе работы над контентом. Как только работа над контентом завершена, автор публикует его и контент становится доступным через публичную часть CMS.
5. Запустить Tomcat ([tomcat]/bin/startup.sh) и подождать пока распакуются оба WAR'а.

6. В браузере сначала постучаться по адресу http://localhost:8080/magnoliaAuthor, нажать "Start install", дождаться завершения и нажать "Start up Magnolia". Потом тоже самое проделать для http://localhost:8080/magnoliaPublic.

На этом установка завершена. Для доступа к http://localhost:8080/magnoliaAuthor введите superuser в качестве логина и пароля.По адресу http://localhost:8080/magnoliaPublic по умолчанию будет доступен демонстрационный сайт, над которым можно поиздеваться через magnoliaAuthor.



Возможные проблемы

Если установка или работа Magnolia CMS вдет себя странно, то гляньте в логи Tomcat:
  • Если увидите в логах java.lang.OutOfMemoryError, то попробуйте ещё увеличить размеры Heap или Permanent Generation.
  • Если обнаружите исключения с припиской "Too many open files", то нужно увеличить лимит на количество открытых файлов в Linux
Общее количество файлов
  • Установить в файле /etc/sysctl.conf параметр fs.file-max = 400000, и для обновления параметра в системе выполняем sysctl -p
  • Проверить можно так: sysctl -a |grep fs.file-max
Количество файлов на пользователя
  • В файле /etc/security/limits.conf написать eqlbin hard nofile 50000 и eqlbin soft nofile 10000, только вместо eqlbin, естественно, ваш пользователь, ну или символ * для любого пользователя
  • Файл limits.conf читается при загрузке. Чтобы сразу установить новое значение лимита выполните: ulimit -n 50000 из под того пользователя, под которым запускается Tomcat. Если эта операция запрещена в вашем дистрибутиве для обычного пользователя, то проще установить значение в limits.conf и перезагрузиться
  • Проверить: ulimit -n

5 апреля 2012 г.

Список CMS на Java

Давно хотел найти для себя какую-нибудь удобную CMS, а точнее WCMS, которая:
  1. Создана на стеке Java-технологий
  2. Open Source
  3. Легко разворачивается
  4. Имеет развитую и относительно простую систему шаблонов
  5. Более или менее легко интегрируется с другими веб-приложениями
  6. Проста в освоении для "нетехнических" людей, которые будут наполнять контент 
Понятное дело, что ничего идеального не бывает, поэтому просто хочется найти компромиссное решение. Это будет непросто, т.к. я никогда ни с какими CMS не общался достаточно тесно и знаю о них не особо много.

В качестве первого шага на пути к поиску наиболее подходящего кандидата, я поспрашивал у могучего Интернета, какие вообще есть открытые CMS, на Джаве писанные. Оказалось, что как и любых других CMS, решений на базе Java уже вагон и маленькая тележка, причем открытых. Этот список найденных CMS я тут и оставлю. В первую очередь это, конечно, для себя любимого, но может он будет полезен и ещё кому-нибудь.

Список я разделил на две части. В первом списке главные кандидаты. Это те CMS, с которыми я уже успел немного познакомиться: какие-то разворачивал и тыкал ранее, а какие-то просто внимательно изучал на официальных сайтах и они мне на первый взгляд понравились. Во втором списке системы, в которых я не особо уверен, потому что пока не уделил им достаточно внимания. Возможно, с течением времени эти списки будут пополняться или между ними будут происходить перестановки.

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

Итак, списки.

Главные претенденты:

Запасной состав:

Многие CMS из этих списков имеют версии Enterprise и Community, которые, соответственно, распространяются под разными лицензиями: закрытой и открытой. Также, некоторые кандидаты являются не только WCMS, а большими разухабистыми ECMS (как, например, Alfresco) с возможностями WCMS. А вот в запасной список наоборот могли закрасться те, которые вообще не умеют WCMS, а являются к примеру только DMS.