Posts categorized under: Linux

Gnome3 и suspend при закрытии крышки ноутбука

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

Установка прошла как по маслу и все вроде бы шло не плохо, пока я не закрыл крышку ноута и не оказалось, что ноутбук не переходит в состояние сна. Просто продолжал работать как и раньше. Открываешь - вот оно все. Даже пароль не просит.

Это не дело и жить с этим нельзя. Копнул поглубже и вот вам решение проблемы, если вы столкнулись с таким же.

В файл /etc/acpi/events/lidbtn пишем эти строки:

# /etc/acpi/events/lidbtn

event=button[ /]lid
action=/etc/acpi/lid.sh

Теперь сам скрипт, который будет блокировать рабочий стол и отправлять машинку в suspend - /etc/acpi/lid.sh:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
#!/bin/bash

RUNTIME=`grep -l DISPLAY /run/systemd/users/* | xargs grep RUNTIME | awk -F= '{print $2}'`
USERNAME=`grep -l DISPLAY /run/systemd/users/* | xargs grep NAME | awk -F= '{print $2}'`
DISPLAY=`grep -l DISPLAY /run/systemd/users/* | xargs grep DISPLAY | awk -F= '{print $2}'`

export XAUTHORITY=${RUNTIME}/gdm/Xauthority
export DISPLAY=:${DISPLAY}
export `cat ${RUNTIME}/dbus-session`

grep -q closed /proc/acpi/button/lid/*/state

if [ $? == 0 ]; then
  su ${USERNAME} -c 'gnome-screensaver-command -l'
  /usr/sbin/pm-suspend >> /tmp/lid.log
fi

Не забудьте поставить пакет с утилитами:

apt install pm-utils

Перезагружаем acpid и проверяем:

/etc/init.d/acpid restart

Ошибка ttf-mscorefonts-installer

Последнее время достает ошибка ttf-mscorefonts-installer.

Решение проблемы:

sudo dpkg -P ttf-mscorefonts-installer  
wget http://ftp.de.debian.org/debian/pool/contrib/m/msttcorefonts/ttf-mscorefonts-installer_3.6_all.deb
sudo dpkg -i ttf-mscorefonts-installer_3.6_all.deb
sudo fc-cache -fv
fc-cache ~/.fonts

ISC DHCP сервер и маршрут по умолчанию

она описана внутри этого скрипта:

# if we have $new_rfc3442_classless_static_routes then we have to
# ignore $new_routers entirely

Т.е. скрипт просто игнорирует значение опции:

option routers ....

Чтоб это исправить нужно добавить в classless маршрут по умолчанию:

option classless-routes code 121 = array of unsigned integer 8;
option classless-routes 0,               192,168,1,1, 
                        24, 192,168,100, 192,168,1,2,
                        24, 10,4,0,      192,168,1,2;
option classless-routes-win code 249 = array of unsigned integer 8;
option classless-routes-win 0,               192,168,1,1, 
                            24, 192,168,100, 192,168,1,2,
                            24, 10,4,0,      192,168,1,2;

Ищем причину зависания сервера

Игрался я тут как-то с Orange Pi Zero и стала она подвисать на ровном месте. Монитор я не подключал к нему, т.к. это такая себе была игровая площадка для всяких датчиков и т.п. В общем, надо было понять в чем дело и почему подвисает железка.

В Linux есть такая возможность ядра как Netconsole. Netconsole позволяет послать сообщения от ядра на удаленный компьютер. Вспомнил о ней и решил вот написать как ей пользоваться. Может кому-то еще пригодится.

Для настройки netconsole нужен другой (постоянно включенный) компьютер который примет сообщение по сети.

Настраиваем проблемный сервер

  1. В /etc/modules добавляем netconsole
  2. В /etc/modprobe.d/netconsole.conf пишем

    options netconsole netconsole=SRCPORT@SRCHOST/eth0,DSTPORT@DSTHOST/DSTMAC

Где SRCPORT и SRCHOST соответственно порт и IP адрес сервера который отлаживаем.
А DSTPORT и DSTHOST порт и IP адрес сервера который будет принимать сообщения.

DSTMAC — это MAC адрес сервера который будет принимать сообщения ЕСЛИ он в той же сети. Если он за роутером или где нибудь в интернете, то нужно указывать MAC адрес ближайшего роутера (Gateway).

Должно получится чтото типа:

options netconsole netconsole=6666@192.168.1.2/eth0,6666@192.168.1.3/e0:91:f5:7d:e6:38

Настраиваем сервер с логом

Нам нужно как-то запустить программу которая будет слушать UDP порт DSTPORT и куда-либо записывать сообшения.

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

Запускаем screen

screen -U -D -RR

Запускаем в окне netcat

netcat -l -u DSTHOST DSTPORT

Как понять что все работает?

Можно подождать какого нибудь события, но как убедится что сообщения реально ходят?

kmsg

echo test > /dev/kmsg

После выполнения этой команды в лог прилетит отправленный текст

SysRq

Можно активировать SysRq механизм ядра.
echo 1 > /proc/sys/kernel/sysrq
echo h > /proc/sysrq-trigger

После этого на сервере который принимает сообщения в окне с netcat появится текст типа
[ 7849.700372] SysRq : HELP : loglevel(0-9)....

Создаем htpasswd для nginx (без Apache)

Если вы, как и я, любите nginx и давно не используете Apache, то устанавливать apache2-utils только ради утилиты htpasswd кажется глупым. И это верно. У вас на борту, скорее всего уже есть openssl. Используем его:

 $ printf "${USER}:`openssl passwd -apr1`\n" >> .htpasswd

${USER} - можно поменять на любое имя пользователя. Если оставить так, то будет подставлено текущее имя пользователя.

Пароль команда запросит ввести дважды.

Кластеризация Ejabberd

Небольшая заметка о моих изысканиях и попытках заставить ejabberd работать в режиме кластера. Возможно я что-то делаю не так, но другим способом заставить работать это поделие у меня не вышло. Предыстория

Пришлось поднимать кластер из ejabberd серверов. Скрипт подключения ноды в кластер постоянно ругался на то, что имя ноды уже кем-то используется и он не может подлючить эту ноду в кластер. Подключаем ноду в ручном режиме

Первая нода

Установить ejabberd можно несколькими способами:

apt

$ sudo apt install ejabberd

deb пакет

$ wget "https://www.process-one.net/downloads/downloads-action.php?file=/ejabberd/16.09/ejabberd_16.09-0_amd64.deb"
$ dpkg -i ejabberd*.deb

run скрипт

$ wget "https://www.process-one.net/downloads/downloads-action.php?file=/ejabberd/16.09/ejabberd-16.09-linux-x86_64-installer.run"
$ chmod 755 ejabberd*.run
$ sudo ./ejabberd-16.09-linux-x86_64-installer.run

После установки правим ejabberd.cfg, но главное — в INET_DIST_INTERFACE указываем ip адрес ноды.

Запускаем ноду:

$ ejabberdctl --node ejabberd@first.example.com start

Проверяем, что нода запустилась корректно:

$ ejabberdctl --node ejabberd@first.example.com status

Вторая нода

После того, как мы подняли первую ноду, необходимо подготовить Mnesia для работы второй ноды.

Проделываем действия по установке настройке и конфигурации INET_DIST_INTERFACE для второй ноды. Файл куки

Erlang использует специальный файл-куку для авторизации нод кластера. Т.е. этот файл должен быть одинаков для всех нод в кластере. Этот файл располагается в домашнем каталоге ejabberd (обычно это /opt/ejabberd/var/lib/, и файл обычно называется .erlang.cookie), но все зависит от способа установки. Скопируйте этот файл с первой ноды на вторую. Настройка репликации mnesia

Переключитесь в пользователя, от которого запускается ejabberd:

$ sudo su - ejabberd

Теперь собственно настройка репликации:

$ cd /opt/ejabberd/var/lib/ejabberd
$ export HOME=/opt/ejabber/var/lib/ejabberd
$ erl -name ejabberd@second.example.com -mnesia extra_db_nodes "['ejabberd@first.example.com']" -s mnesia

пример вывода

you are now in an erlang shell:

Erlang R14B02 (erts-5.8.3) [source] [smp:4:4] [rq:4] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.8.3 (abort with ^G)
(ejabberd@second.example.com)1> mnesia:info().
schema : with 29 records occupying 3580 words of mem
opt_disc. Directory "/opt/ejabber/var/lib/ejabberd/Mnesia.ejabberd@second.example.com" is NOT used.
use fallback at restart = false
running db nodes = ['ejabberd@first.example.com','ejabberd@second.example.com']
stopped db nodes = []
master node tables = []
remote = [acl,caps_features,captcha,config,iq_response,
last_activity,local_config,mod_register_ip,motd,
motd_users,muc_online_room,muc_registered,muc_room,
offline_msg,passwd,privacy,private_storage,
reg_users_counter,roster,roster_version,route,s2s,
session,session_counter,sr_group,sr_user,vcard,
vcard_search]
ram_copies = [schema]
disc_copies = []
disc_only_copies = []
[] = [local_config,caps_features,mod_register_ip]
[{'ejabberd@second.example.com',ram_copies},
{'ejabberd@first.example.com',disc_copies}] = [schema]
[{'ejabberd@first.example.com',disc_copies}] = [config,privacy,passwd,roster,
last_activity,sr_user,
roster_version,motd,acl,sr_group,
vcard_search,motd_users,muc_room,
muc_registered]
[{'ejabberd@first.example.com',disc_only_copies}] = [offline_msg,vcard,
private_storage]
[{'ejabberd@first.example.com',ram_copies}] = [reg_users_counter,route,s2s,
captcha,session_counter,session,
iq_response,muc_online_room]
3 transactions committed, 0 aborted, 0 restarted, 0 logged to disc
0 held locks, 0 in queue; 0 local transactions, 0 remote
0 transactions waits for other nodes: []
ok

Копируем данные. Эти команды надо вводить в erlang shell, который будет открыт после запуска предыдущей команды:

(ejabberd@second.example.com)4> mnesia:change_table_copy_type(schema, node(), disc_copies).
(ejabberd@second.example.com)5> mnesia:add_table_copy(roster, node(), disc_copies).
(ejabberd@second.example.com)6> mnesia:add_table_copy(passwd, node(), disc_copies).
(ejabberd@second.example.com)7> mnesia:change_table_copy_type(acl, node(), disc_copies).
(ejabberd@second.example.com)8> mnesia:change_table_copy_type(config, node(), disc_copies).
(ejabberd@second.example.com)9> mnesia:add_table_copy(offline_msg, node(), disc_only_copies).
(ejabberd@second.example.com)10> mnesia:add_table_copy(vcard, node(), disc_only_copies).
(ejabberd@second.example.com)11> mnesia:add_table_copy(private_storage, node(), disc_only_copies).
(ejabberd@second.example.com)12> q().

Теперь надо перенести данные Mnesia в правильное место:

$ mv Mnesia* ejabberd@second.example.com

Запускаем вторую ноду:

$ ejabberdctl --node ejabberd@second.example.com start

Проверяем, что нода запустилась:

$ ejabberdctl --node ejabberd@second.example.com status

Бонус

Если вам надо заменить какую-то ноду с тем же именем, то перед подключением в кластер нужно удалить эту ноду. Делается это в erlang shell на первой ноде:

mnesia:del_table_copy(schema, 'ejabberd@second.example.com').

Есть ли почта в консоли?

Я очень долгое время использовал для работы с почтой Mozilla Thunderbird. Но с каждым годом эта ранее быстрая и легковесная программа превращалась в неповоротливого монстра. И вот мне наконец надоело и я решил попробовать использовать старый, но от того не разросшийся до невменяемого состояния, консольный почтовый клиент mutt.

Справка

mutt — почтовый клиент с текстовым интерфейсом для Unix-подобных операционных систем. Написан Майклом Элкинсом в 1995 году и распространяется по лицензии GPL. Изначально напоминал Elm, затем программа больше походила на slrn.

Mutt поддерживает большинство форматов почтовых ящиков (в том числе mbox и Maildir) и протоколов (POP3, IMAP и т. д.). Также включает поддержку MIME, PGP/GPG и S/MIME-интеграцию.

Mutt является чистым Mail User Agent (MUA) и не может отсылать e-mail самостоятельно. Для этого ему необходимо иметь соединение с Mail Transfer Agent (MTA) (почтовым сервером) либо SMTP-клиентом.

Установка в Ubuntu

В Ubuntu есть две версии mutt:

  1. Классический mutt
  2. Mutt с кучей патчей по улучшению отображения и работы

Я поставил себе патченную версию, т.к. она мне показалась более логичной:

$ sudo apt-get install mutt-patched

Настройка

Настройка производится в файле \~/.muttrc. Я не буду расписывать всю настройку, документации полно в сети, а лишь покажу то, что сделано у меня:

# GENERAL
set realname = "Vasya Pupkin"                        # Имя пользователя
set use_from = yes
set sort = reverse-threads                           # Сортировка по обсуждениям в обратном порядке
set sort_aux = last-date-received                    # Сортировка по дате получения
set mail_check = 5                                   # Проверять почту раз в 5 секунд
set timeout = 10                                     # Таймаут соединения
set net_inc = 5
set signature = ~/.signature                         # Файл подписи
set delete = yes                                     # Удалять без подтверждения
set copy = no                                        # Копировать с подтверждением
set move = yes                                       # Перемещать письма без подтверждения
set edit_headers                                     # Показывать заголовки при написании письма
set editor = "/usr/bin/sublime-text -w"              # Редактор
set include = yes                                    # Добавлять цитирование при ответе
set mark_old = no                                    # Не помечать прочитанные для перемещения в mbox
set save_empty = no                                  # Не созранять пустые сообщения
set pgp_verify_sig = yes                             # Автоматически проверять PGP подпись письма

# Не показывать эти заголовки (нажатие 'h' покажет все)
ignore X-Mailer Delivered-To X-Delivery-ID X-Priority X-MSMail-Priority X-MimeOLE X-Spam-Checker-Version X-Spam-Level X-Spam-Status Precedence X-No-Archive List- DomainKey-Signature In-Reply-To User-Agent DKIM-Signature X-Google-Sender-Auth

# Bindings
macro index,pager S s+Junk                           # Shift+s отправит письмо в спам
macro index,pager A s+Archives.2016                  # Shift+a отправит письмо в папку Archives -> 2016
bind index G imap-fetch-mail                         # Shift+g получит новые письма

unhdr_order *                                        # Сбрасывает настройки порядка показа заголовков
hdr_order date from to cc subject                    # Порядок показа заголовков

# IMAP
set from = user@example.com                          # Адрес отправителя
set imap_user = user@example.com                     # IMAP логин
set imap_pass = Pa$sw0rd                             # IMAP пароль
set smtp_url = smtp://user@example.com:25/           # SMTP логин@сервер
set smtp_pass = Pa$sw0rd                             # SMTP пароль
set imap_keepalive = 900
set folder = imaps://example.com:993                 # IMAP сервер
set spoolfile = +INBOX #or +[Gmail]/Important        # Имя папки входящих сообщений
set postponed = +Drafts                              # Имя папки с черновиками
set header_cache = ~/.mutt/cache/headers             # Файл кеша заголовков
set message_cachedir = ~/.mutt/cache/bodies          # Файл кеша сообщений
set certificate_file = ~/.mutt/certificates          # Файл кеша сертификатов
set ssl_starttls = yes                               # Использовать StartTLS
set ssl_force_tls = yes                              # Обязательно использовать TLS
unset imap_passive                                   # Отключить пассивный решим IMAP
set imap_check_subscribed                            # Проверять подписки на папки

# HTML
set implicit_autoview                                # Использовать фильтры по содержимому
set mailcap_path="~/.mailcap"                        # Файл с описанием фильтров

# GPG
source /usr/share/doc/mutt/examples/gpg.rc           # Подключить PGP/GnuPG шифрование
# Ссылка на публичный ключ в сети
my_hdr X-PGP-Key: https://blog.lyalyuev.info/wp-content/uploads/05420A87.pub

set pgp_use_gpg_agent = yes                          # Использовать GPG Agent
set pgp_sign_as = 05420A87                           # Подписывать письма ключем 05420A87
set pgp_timeout = 3600
set crypt_autosign = no                              # Автоматически не подписывать сообщения
set crypt_replyencrypt = yes                         # Отвечать шифрованием на шифрованные сообщения

Из комментариев к конфигу все должно быть понятно. Осталось два файла:

  1. \~/.signature - это файл с подписью, которая будет автоматически добавляться к письму. Может содержать в себе что угодно.
  2. \~/.mailcap - файл с описанием типа вложения и программой, которая должна его открывать:

    text/html; firefox %s; needsterminal;

В данном случае имеется ввиду, что файлы вложений типа text/html открывать надо с помощью firefox. Так я открываю HTML письма, которые не содержат в себе текстовой части.

Работа в mutt

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

? - справка по клавишам
m - создать письмо
r - ответить на письмо
c - сменить папку
q - выход
y - подтверждение действия

Следите за подсказками в верхней строке и почаще заглядывайте в хелп. И все у вас получится. ;)

Nginx + LDAP авторизация

Задача

Довольно часто в корпоративной среде встречаются два сервиса:

  1. Nginx
  2. LDAP

И очень часто надо сделать авторизацию к какому-то сервису авторизацию через LDAP на Nginx. Сам Nginx не имеет встроенного модуля авторизации в LDAP, в отличие от Apache или Tomcat.

Итак, давайте сделаем basic авторизацию пользователей в Nginx через LDAP.

Сервер авторизации

Метод, который предлагают сами разработчики Nginx заключается в следующем: необходимо поднять промежуточный сервер, который будет проверять введеные данные в LDAP и возвращать результат в Nginx. В случае ответа HTTP/200 - пользователь авторизован. В любом другом случае - даные не верны.

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

Клонируем репу к себе на сервер:

$ git clone https://github.com/nginxinc/nginx-ldap-auth.git /opt/nginx-ldap-auth

и запускаем этот сервер (дополнительной настройки он не требует):

$ /opt/nginx-ldap-auth/nginx-ldap-auth-daemon-ctl.sh start

Остальная настройка будет производиться из конфига Nginx. Для этого нам надо добавить в Nginx что-то типа такого:

        location = /auth-proxy {
            internal;
            proxy_pass_request_body off;
            proxy_set_header Content-Length "";
            proxy_pass http://127.0.0.1:8888;
            proxy_set_header X-Ldap-URL "ldap://127.0.0.1:389";
            proxy_set_header X-Ldap-Template "(uid=%(username)s)";
            proxy_set_header X-Ldap-BaseDN "dc=example,dc=com";
        }
        location /private-storage {
            auth_request /auth-proxy;
            proxy_pass http://application-backend;
        }

По умолчанию, будет произведена попытка simple bind с анонимным пользователем. Если же у вас не поддерживается этот метод, то вам необходимо раскомментировать строки и указать DN и пароль пользователя, который может искать по дереву LDAP. Это самая простая конфигурация и она может быть расширена другими модулями авторизации.

Ошибка выполнения внешних команд в Nagios

Если в Nagios при выполнении внешних команд вы видите ошибку:

    Error: Could not stat() command file ‘/var/lib/nagios3/rw/nagios.cmd’!

то все не так плохо, как кажется. Лечится так:

sudo /etc/init.d/nagios3 stop
sudo dpkg-statoverride --update --add nagios www-data 2710 /var/lib/nagios3/rw
sudo dpkg-statoverride --update --add nagios nagios 751 /var/lib/nagios3
sudo /etc/init.d/nagios3 start

Смена имени диска в Linux

Посмотреть/поменять имя диска в Linux с файловой системой ext2/ext3/ext4 не просто, а очень просто.

Посмотреть имя диска:

$ sudo e2label /dev/sda1

Выведет установленное имя. Если вывод будет пустой строкой, то имя диска не установлено.

Поменять имя диска:

$ sudo e2label /dev/sda1 WebRoot

Выполнение этой команды установит имя «WebRoot» для диска /dev/sda1, после чего можно монтировать диск по имени:

$ sudo mount -L WebRoot /mnt/mount/point

Так же можно указывать монтирование дисков по имени и в fstab:

LABEL=WebRoot /mnt/mount/point ext4 defaults 1 2