Linux

Systemd линукс система управления сервисами

Запуск сервиса от имени пользователя

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

Пользовательские сервисы находятся в ~/.config/systemd/user/

Старт сервиса. Нужно просто добавить --user

systemctl start myservice --user

Изменение настроек системного сервиса

Это относится ко всем сервисам, не только локальным.

Бывает, что вам нужны какие-то свои настройки, допустим, запускать бинарник с каким-то определенным ключом. И если у сервиса нет своего личного файла настроек, то единственный способ это сделать - это редактирование файла сервиса. Но при следующем же обновлении пакета ваши изменения перезапишутся. Чтобы такого не случилось есть штатный механизм создании пользовательских настроек.

Итак, пользовательские настройки создаются командой:

systemctl edit myservice

Но при такой команде открывается пустой документ, в который нужно прописать разницу между оригиналом и своим конфигом.

Более удобнее пользоваться командой:

systemctl edit --full myservice

Тогда откроется копия существующего конфига, который можно редактировать.

Сообщение о ошибке при сборке модуля ядра LinuxОшибка актуальна для сборки собвственного модуля ядра Linux, или же пересборки старого чужого модуля.
error: ‘struct file_operations’ has no member named ‘ioctl’

означает, что в структуре file_operations было поле ioctl, a теперь его нет.

Во многих примерах используется старый вариант, который при сборке выдаёт ошибку.

Немного истории:

Раньше, вызов ioctl() для устройств приводил к глобальной блокировке всего ядра (Big Kernel Lock [BKL]). Особенно это замедляло работу многопроцессорных систем, ведь при вызове ioctl() блокировались все процессы.
Начиная с версии ядра 2.6.11 появилась альтернативная функция unlocked_ioctl(), которая выполняла действия без глобальной блокировки ядра. Начался переходный период, когда можно было встретить и старые и новые варианты.

Начиная с версии 2.6.36 переходный период кончился, и функция ioctl() была удалена. Вместо неё теперь функции unlocked_ioctl() и compat_ioctl().

Разница между unlocked_ioctl() и compat_ioctl()

unlocked_ioctl() вызывает функцию ядра без глобальной блокировки ядра

compat_ioctl() сделана для обращений 32-битных приложений к 64-битному ядру.

Резюмируя: ioctl() надо заменять на unlocked_ioctl() (если, конечно у вас не 32-битное приложение под 64-битным ядром)

Как исправить ошибку компиляции

Обратите внимание, что меняется не только структура, но и сигнатура функции.

Старый вариант

int device_ioctl(struct inode *inode, struct file *file, unsigned int ioctl_num, unsigned long ioctl_param)
{
// code
}

static struct file_operations FileOps =
{
    .owner      = THIS_MODULE,
    .read         = device_read,
    .write         = device_write,
    .open       = device_open,
    .ioctl         = device_ioctl,
    .release    = device_close,
};

Новый вариант

long device_ioctl(struct file *file, unsigned int ioctl_num, unsigned long ioctl_param)
{
// code
}

static struct file_operations FileOps =
{
    .owner          = THIS_MODULE,
    .read             = device_read,
    .write             = device_write,
    .open           = device_open,
    .unlocked_ioctl = device_ioctl,
    .release        = device_close,
};

php 7Я обслуживаю несколько сайтов, висящих на одном сервере. Сайты как на движке Joomla, таки на Wordpress. В какой-то момент Joomla 3.5 написала в админки, что мой PHP 5.6 устарел, больше не поддерживается, и поэтому там могут быть проблемы с безопасностью. И посоветовала перейти на PHP 7. А почему бы и нет...

Что хорошего обещают в PHP 7

PHP 7 в основном славиться производительность и уменьшением потребляемой памяти. Разработчики и блоггеры утверждают, что код выполняется почти вдвое быстрее по сравнению с php5.6

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

Но, главная проблема с PHP7 - она не обратносовместима с PHP5.6. Т.е. разработчики не гарантируют, что ваш старый код будет работать в новой версии PHP. Подробнее ниже.

Проблемы при переходе на PHP7

WordPress

Сайты с WordPress перешли на php7 довольно легко: пришлось лишь удалить один плагин, прячущий раскрывающиеся текст под знак плюса.

Joomla 2.5 не поддерживает PHP 7

Большой неожиданностью было то, что Joomla 2.5 не поддерживает PHP7. Сайт ещё худо-бедно работает, отображая не все страницы, а в админку не зайти совсем. Поэтому перед переходом на PHP7 придётся обвить старую Джумлу до Joomla 3.5 а потом до Joomla 3.7.

Плагины и компоненты Joomla и php7

Даже если у вас Joomla 3.7 не факт, что при переходе на php7 ничего не сломается: некоторые плагины и компоненты ещё не поддерживают php7. При переезде рекомендуется отключить все плагины и модули, а после переезда включать их по-одному. В противном случае может не открываться админка.

Проблема тут в том что в php 7 изменили порядок применения операторов:

Исходный код:
$foo->$bar['baz']
В версии php5.6 понимается как:
$foo->{$bar['baz']}
А, php7 понимает его уже совсем по-другому:
($foo->$bar)['baz']

В принципе, если компонент очень ценен для вас, то вы можете самостоятельно исправить проблему, расставив в нужных местах скобки: $foo->{$bar['baz']}. Для этого в админке Joomla включаете показ всех возможных ошибок, а потом по именам файлов и номерам строчек ищете соответствующие проблемы.

Nginx выдаёт белый экран

Проблема тут не в php, а в переходе на Nginx 1.10. У него изменился синтаксис конфигурационных файлов.
Теперь вместо:
include fastcgi_params;
нужно писать:
include fastcgi.conf;

Ощущения после перехода на php7

Действительно ли php7 работает быстрее?

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

Ещё один способ оценить прирост скорости - посмотреть на время загрузки страницы. Удобнее всего посмотреть его в GoogleWebmasters: там время показано на графике за период в несколько месяцев. Для моих сайтов время загрузки страницы не изменилось. Возможно даже стало чуть медленнее.

Nginx 504 Gateway Time-out

Очень часто стало вылетать при пользовании админкой Joomla 3.7. Особенно при публикации комментариев компонента JComments. Пока не очень ясно проблема ли это Joomla, либо негативно сказался переход на php7.

Совет прописать больший timeout в настройках nginx:
fastcgi_read_timeout 300;
- ничего не дал. Nginx действительно дольше ожидает ответа php-fpm, но в конце всё-равно выдаёт Gateway Time-out.

Заключение

Переходить на php7 всё-равно когда-нибудь потребуется, как и переходить на Joomla 3.7. И переход этот не будет безболезненным: скорее всего потребуется что-то исправлять или от чего-то отказываться.

В качестве совета счастливым владельцам сайта на Joomla могу посоветовать подождать ещё немного: возможно кто-то из разработчиков компонентов/модулей/плагинов выпустит новую версию, совместимую с PHP7.

ssh-туннель

Что мы получим в итоге?

Допустим, у вас или у вашего друга есть сервер, например vasya.com. Пробросив свои локальные порты через сервер, мы набирая в браузере vasya.com:5000 попадать на веб-сервер своего компьютера, не имеющий внешний IP. А подключаясь по ssh: ssh -p5001 Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript. мы всегда можем попасть на свой домашний компьютер, находящийся за NAT.

Предисловие

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

Настройка SSH на сервере

Спева необходимо включить проброс портов в настройках ssh-сервера.

На сервере vasya.com редактируем файл /etc/ssh/sshd_config

И редактируем (или добавляем) там строчку:

GatewayPorts yes

Перезагружаем ssh-сервер

Открываем порты на сервере

На каждом хорошем сервере должен стаять файрвол. Он блокирует все порты кроме разрешённных.

У меня Ubuntu Server и файрвол UFW.
На сервере редактируем /etc/ufw/user.rules

И добавляем туда:

### SSH TUNNELS ###
# 5000 - home web
# 5001 - home ssh
# 5002 - dacha web
# 5003 - dacha ssh
-A ufw-user-input -p tcp --dport 5000 -j ACCEPT
-A ufw-user-input -p tcp --dport 5001 -j ACCEPT
-A ufw-user-input -p tcp --dport 5002 -j ACCEPT
-A ufw-user-input -p tcp --dport 5003 -j ACCEPT

Перезагружаем ufw-демон.

Создаём туннель

На своём домашнем компьютере набираем:

ssh -N -p22 Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript. -R 5000:localhost:80

-p22 - порт сервера ssh (по умолчанию 22, но для безопасности лучше бы его заменить на какой-нибудь другой).

-N не выполнять команды в ssh-сессии

-R 5000:localhost:80 - прокидываем свой локальный порт 80 на порт vasya.com:5000

Проверяем

Набираем в браузере vasya.com:5000 и убеждаемся, что там показывается наш домашний веб-сервер.

 

 

 Joomla smtp mail

Отправлять почту со своего выделенного VPS сервера

Пользуясь выделенным сервером (VPS) для хостинга своего сайта часто возникает проблема с отправкой почты: поднимать свой полноценный сервер слишком трудоёмко, и даже следуя всем инструкциям результат не гарантирован. Хорошее решение проблемы - использовать сторонний сервер.

Варианта тут три:

  • Отправлять почту через sendmail или встроенные средства языка PHP без всякой авторизации. Обычно такие способы настроены по умолчанию во всех современных движках сайтов (Joomla, WordPress). Проблема лишь только одна: ваши письма всегда будут попадать в спам. Потому, что без авторизации на почтовом сервере к письму не добавляется информация о подлинности, и у принимающего сервера нет уверенности, что письмо отправил действительно хозяин почтового ящика. Оно попадает в спам.
  • Использовать чужой почтовый сервер со своим доменным именем. Например почта у вас будет Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript.,  а почтовый сервер будет mail.ru. Настроить всё можно за час, а конечные пользователи не заметят разницы
  • Если вам не обязательно отправлять почту со своего доменного имени, а вполне устроит @gmail.com или @mail.ru, то проще всего настроить отправку почты с авторизацией по SMTP

Joomla: настройка отправки почты через SMTP

Примерные настройки показаны на скриншоте:

Настройка IMAP в Joomla 

Важно удостовериться, что поле "Имя пользователя" и "Email сайта" совпадают.

Ошибка в перечисленных адресах отправителей

Если вы видите эту ошибку, причин может быть несколько:

  • Неправильный логин/пароль от почты
  • поле "Имя пользователя" и "Email сайта" не совпадают. Иными словами, авторизируясь как vasya@ вы пытаетесь отправить почту от имени petya@.
  • Неправильные настройки vps-сервера. Об этом отдельно

Неправильные настройки VPS сервера при отправке почты

Как проверить

Можно написать простой скрипт на питоне:

to = Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript.'
gmail_user = Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript.'
gmail_pwd = 'mypass'
print "smtp.."
smtpserver = smtplib.SMTP("smtp.gmail.com",587)
#smtpserver = smtplib.SMTP("64.233.162.108",587)
print "ehlo..."
smtpserver.ehlo()
print "starting tsl..."
smtpserver.starttls()
print "ehlo2..."
smtpserver.ehlo() # extra characters to permit edit
print "logining..."
smtpserver.login(gmail_user, gmail_pwd)
header = 'To:' + to + '\n' + 'From: ' + gmail_user + '\n' + 'Subject:Hello \n'
print header
msg = header + '\n this Hello from lubov 5 try \n\n'
print "sending"
smtpserver.sendmail(gmail_user, to, msg)
print 'done!'
smtpserver.quit()

Видите в скрипте закомментированную строчку с IP вместо имени почтового сервера?
Попробуйте по ip, если не заработает по имени.

Запускаем через:

time python ./script.py

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

Причина 1. Не открыт исходящий порт для IMAP соединений

Если у вас VPS сервер, то скорее всего у вас настроен файрвол (если нет, то скорее же его поставьте).

В настройках iptables нужно открыть 25 порт для исходящих соединений. На разных дистрибутивах это делается немного по-разному, поэтому конкретные команды писать не буду.

Также нужно не забывать что если у вас настроена сеть по Ipv6, то нужно также настроить правила для ip6tables.

Причина 2. Хостер не пропускает почтовые соединения по IPv6

У меня в итоге оказалась именно эта проблема. Хостер DigitalOcean не пропускает соединения к почтовым серверам по ipv6.

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

Не отправляется почта по ipv6. Решение для Joomla 2.5

Решение состоит в том, чтобы принудительно подключаться к почтовому серверу по ipv4.
Идём в www/libraries/phpmailer/phpmailer.php

Ищем там функцию SmtpConnect, и внутри неё ищем код:

 if (preg_match('/^(.+):([0-9]+)$/', $hosts[$index], $hostinfo)) {
          $host = $hostinfo[1];
          $port = $hostinfo[2];
        } else {
          $host = $hosts[$index];
          $port = $this->Port;
        }

И вставляем строчку:

$host = gethostbyname($host);

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

 if (preg_match('/^(.+):([0-9]+)$/', $hosts[$index], $hostinfo)) {
          $host = $hostinfo[1];
          $port = $hostinfo[2];
        } else {
          $host = $hosts[$index];
          $host = gethostbyname($host);
          $port = $this->Port;
        }

Смысл в том, чтобы принудительно получать IPv4 хоста, и обращаться уже по IP-адресу.

Решение не очень элегантное, т.к. приходится исправлять код Joomla, и при очередном обновлении это исправление вполне может слететь.

Не отправляется почта по ipv6. Решение для Joomla 3.7

Всё аналогично Joomla 2.5, только нужный нам файл находится по адресу: www/libraries/vendor/phpmailer/phpmailer/class.phpmailer.php

Ищем там функцию smtpConnect, внутри неё ищем первое упоминание $host:

$host = $hostinfo[3];
$port = $this->Port;
$tport = (integer)$hostinfo[4];

И вставляем строчку:

$host = gethostbyname($host);

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

$host = $hostinfo[3];
$host = gethostbyname($host);
$port = $this->Port;
$tport = (integer)$hostinfo[4];

Да... решение временное и будет слетать при каждом обновлении Joomla... но другого пока нет.

Поиск