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

Дата: 09.06.2018Метки: ,

Запустил бэкап диска с передачей данных на другой сервер:

dd if=/dev/sda | gzip -3 - | ssh root@1.1.1.1 dd of=/storage/image.gz

Главная проблема данного метода состоит в том, что отсутствует информация о прогрессе выполнения команды dd. Посмотреть на каком этапе находится процесс создания бэкапа можно следующим образом.

Открываем еще одну консоль и в ней выполняем команду:

pkill -USR1 dd

Возвращаемся в консоль, где запущен команда dd и видим примерно следующий результат:

46581824+0 records in
46581823+0 records out
23849893376 bytes (24 GB) copied, 650.728 s, 36.7 MB/s
52076416+0 records in
52076415+0 records out
26663124480 bytes (27 GB) copied, 736.246 s, 36.2 MB/s
232366273+0 records in
232366272+0 records out
118971531264 bytes (119 GB) copied, 1193.34 s, 99.7 MB/s
234441648+0 records in
234441648+0 records out
120034123776 bytes (120 GB) copied, 1198.1 s, 100 MB/s

Что бы каждый раз не вбивать команду в консоли, можно сделать так:

watch -n 10 pkill -USR1 dd

Linux disk write timeout

Дата: 30.04.2018Метки:

При интенсивных операциях записи в Debian 9 поймал disk write timeout. К сожалению, точное содержание ошибки не записал, но в общем суть понятна. Система выдавала таймаут при записи на диск. Сначала пытался увеличить следующее значение:

echo 180 > /sys/block/sda/device/timeout

Но конкретно данная манипуляция не дала никакого результата. В итоге удалось решить проблему указав значения параметров кэширования в Linux dirty_background_ratio и dirty_ratio:

echo 5 > /proc/sys/vm/dirty_background_ratio
echo 10 > /proc/sys/vm/dirty_ratio

dirty_background_ratio — основной инструмент настройки, обычно уменьшают этот параметр. Если ваша цель снизить количество данных, хранимое в кэше, так что данные будут писаться на диск постепенно, а не все сразу, то уменьшение этого параметра наиболее эффективный путь. Более приемлемо значение по умолчанию для систем имеющих много оперативной памяти и медленные диски.

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

/bin/sh can’t access tty

Дата: 15.10.2017Метки:

На одном из серверов упал сайт. В браузере отображалась информация об отсутствии подключения к MySQL. Запускаться вручную MySQL отказывался. Отправил сервер на перезагрузку, после чего система отказалась запускаться. Если подключится к консоли можно увидеть вот такое сообщение об ошибке:

/bin/sh can't access tty

У меня была установлена система Debian 8, вылечилось достаточно просто. Запустил проверку файловой системы:

fsck -t ext4 /dev/sda1

В процессе проверки были найдены ошибки, на всех запросах жал Y для подтверждения. После перезапуска система ожила.

SMART мониторинг SSD в Linux

Дата: 21.06.2017Метки:

У каждого производителя SSD есть специализированная утилита для мониторинга состояния диска в Windows. Что касается Linux, то ситуация состоит сложнее. По моему опыту я сталкивался с наличием такой утилиты под Linux только для PRO и энтерпрайз серии SSD дисков. Но если говорить по сути, то особой нужды в них нет. В качестве альтернативы мы будем использовать утилиту smartmontools доступную для большинства дистрибутивов Linux.

Для начала выполним установку. В CentOS необходимо выполнить команду:

yum install smartmontools

Для Debian и Ubuntu аналогично:

apt-get install smartmontools

Если не знаете название диска, то список всех подключенных дисков можно посмотреть командой:

find /dev -name 'sd*'

Теперь, когда известно название диска, можем вывести информацию SMART. У меня результат выполнения команды выглядит следующим образом:

# smartctl -A /dev/sda
smartctl 6.2 2013-07-26 r3841 [x86_64-linux-3.10.0-514.21.1.el7.x86_64] (local build)
Copyright (C) 2002-13, Bruce Allen, Christian Franke, www.smartmontools.org

=== START OF READ SMART DATA SECTION ===
SMART Attributes Data Structure revision number: 1
Vendor Specific SMART Attributes with Thresholds:
ID# ATTRIBUTE_NAME          FLAG     VALUE WORST THRESH TYPE      UPDATED  WHEN_FAILED RAW_VALUE
  5 Reallocated_Sector_Ct   0x0033   100   100   010    Pre-fail  Always       -       0
  9 Power_On_Hours          0x0032   099   099   000    Old_age   Always       -       215
 12 Power_Cycle_Count       0x0032   099   099   000    Old_age   Always       -       9
177 Wear_Leveling_Count     0x0013   100   100   000    Pre-fail  Always       -       0
179 Used_Rsvd_Blk_Cnt_Tot   0x0013   100   100   010    Pre-fail  Always       -       0
181 Program_Fail_Cnt_Total  0x0032   100   100   010    Old_age   Always       -       0
182 Erase_Fail_Count_Total  0x0032   100   100   010    Old_age   Always       -       0
183 Runtime_Bad_Block       0x0013   100   100   010    Pre-fail  Always       -       0
187 Reported_Uncorrect      0x0032   100   100   000    Old_age   Always       -       0
190 Airflow_Temperature_Cel 0x0032   069   063   000    Old_age   Always       -       31
195 Hardware_ECC_Recovered  0x001a   200   200   000    Old_age   Always       -       0
199 UDMA_CRC_Error_Count    0x003e   100   100   000    Old_age   Always       -       0
235 Unknown_Attribute       0x0012   099   099   000    Old_age   Always       -       2
241 Total_LBAs_Written      0x0032   099   099   000    Old_age   Always       -       1357065631

Теперь немного информации о данных, которые содержат важную информацию о состоянии вашего диска. В первую очередь обратите внимание на значение RAW_VALUE для параметра Reallocated_Sector_Ct — количество переназначенных секторов. Нулевое значение говорит нам, что диск в полном порядке. Далее обратите внимание на Power_On_Hours, параметр отображает информацию о суммарном времени работы диска. Информация может быть полезна при аренде сервера и дает общее представление о времени его работы. Далее второй по значимости параметр Total_LBAs_Written — общее количество записанных байт.

Что бы предоставить информацию из Total_LBAs_Written можно воспользоваться онлайн калькулятором. В калькуляторе важно указать размер сектора диска, его можно посмотреть командой:

fdisk -l /dev/sda

Зомби процессы в Linux

Дата: 10.04.2017Метки:

Если в вашей системе завелись зомби процессы, не расстраивайтесь. Не смотря на страшное название зомби процесс не может нанести серьезный вред вашей системе. Для начала давайте разберемся как обычный процесс превращается в зомби.

Когда дочерний процесс получает команду на завершение, он освобождает все используемые ресурсы и продолжает как зомби существовать в системе с ранее присвоенным ему PID. Далее с помощью сигнала SIGCHLD система уведомляет родительский процесс о завершении зомби процесса. Если по какой-либо причине родительский процесс игнорирует этот сигнал, то зомби процесс так и продолжает отображаться в системе.

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

Что бы убить зомби процесс, для начала нужно получить его PID:

# ps aux | grep -w Z
root      2037  0.0  0.0      0     0 ?        Z    09:44   0:00 [httpd] 
root      8470  0.0  0.0 112652   984 pts/10   S+   10:43   0:00 grep --color=auto -w Z

В моем примере PID зомби процесса 2037. Теперь получим PID родительского процесса:

# ps o ppid 2037
 PPID
 2033

Когда мы знаем PID, правильнее всего определить что это за процесс командой top, а затем перезапустить его.

В крайнем случае можно убить родительский процесс:

# kill -9 2033

Добавить сервис в systemd

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

Уже прошло достаточно много времени с того момента, как большинство популярных дистрибутивов Linux перешли на системный менеджер systemd. Тем не менее, до сих пор старая система инициализации SysV продолжает параллельно функционировать на ряду с systemd. И как и раньше, большинство пакетов после установки добавляют стартовый скрипт в каталог init.d.

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

Для примера мы установили OpenVPN, для которого по умолчанию используется механизм запуска System V. Во время установки пакета в каталог /etc/init.d будет скопирован скрипт инициализации, который будет отвечать за автоматический запуск приложения после перезагрузки. Если в один прекрасный день OpenVPN упадет, без дополнительных настроек, нужно будет каждый раз запускать этот процесс вручную.

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

А теперь давайте рассмотрим, как быстро добавить сервис в systemd. Демон systemd запускает сервисы описанные в его конфигурации. Конфигурация состоит из файлов, которые называют юнитами. Для юнитов созданных вручную используется каталог:

/etc/systemd/system/

В простом варианте юнит состоит из трех секции: [Unit], [Service], [Install].

Секция [Unit]

Описание юнита:

Description=MyUnit

Далее указываем порядок загрузки, после какого сервиса systemd запустить наш юнит:

After=syslog.target
After=network.target

Секция [Service]

Задаем тип сервиса:

Type=simple

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

Type=forking

Указывают если служба запускается однократно и процесс разветвляется с завершением родительского процесса.

Расположение pid-файла:

PIDFile=/run/service.pid

Рабочий каталог приложения:

WorkingDirectory=/usr/local/service

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

User=unit
Group=unit

Задаем приоритет убийства процесса при нехватке памяти:

OOMScoreAdjust=-100

Минимальное значение -1000 — полный запрет.

Команды запуска, остановки и перезапуска сервиса:

ExecStart=/usr/sbin/service
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID

Таймаут запуска или остановки сервиса:

TimeoutSec=300

Контроль запуска сервиса и автоматический запуск в случае крєша:

Restart=always

Секция [Install]

Уровень запуска сервиса:

WantedBy=multi-user.target

В итоге мы получили следующий юнит:

[Unit]
Description=MyUnit
After=syslog.target
After=network.target

[Service]
Type=forking
PIDFile=/run/service.pid
WorkingDirectory=/usr/local/service
User=munit
Group=unit
OOMScoreAdjust=-100

ExecStart=/usr/sbin/service
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID
TimeoutSec=300

[Install]
WantedBy=multi-user.target

Добавляем юнит в каталог:

nano /etc/systemd/system/unit_name

Включаем, запускаем и смотрим статус юнита:

systemctl enable unit_name
systemctl start unit_name
systemctl -l status unit_name
systemctl daemon-reload

А теперь привожу примеры работающих юнитов.

Юнит systemd для запуска Nginx:

[Unit]
Description=The NGINX HTTP and reverse proxy server
After=syslog.target network.target remote-fs.target nss-lookup.target

[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true

[Install]
WantedBy=multi-user.target

Юнит systemd для запуска php-fpm:

[Unit]
Description=The PHP FastCGI Process Manager
After=syslog.target network.target

[Service]
Type=simple
PIDFile=/usr/local/php-fpm/var/run/php-fpm.pid
ExecStart=/usr/local/php-fpm/sbin/php-fpm --nodaemonize --fpm-config /usr/local$
ExecReload=/bin/kill -USR2 $MAINPID
PrivateTmp=true

[Install]
WantedBy=multi-user.target

Access denied for user ‘debian-sys-maint’@’localhost’

С проблемой можно столкнуться в результате некорректной установки MySQL. Полностью ошибка выглядит следующим образом:

mysql_upgrade: Got error: 1045: Access denied for user 'debian-sys-maint'@'localhost' (using password: YES) while connecting to the MySQL server

Суть проблемы состоит в том, что mysql_upgrade не может получить доступ к нашей базе под указанным в файле debian.cnf паролем. Если выполнить команду:

cat /etc/mysql/debian.cnf

Мы получить результат следующего вида:

# Automatically generated for Debian scripts. DO NOT TOUCH!
[client]
host     = localhost
user     = debian-sys-maint
password = n4aSHUP04s1J32X5
socket   = /var/run/mysqld/mysqld.sock
[mysql_upgrade]
user     = debian-sys-maint
password = n4aSHUP04s1J32X5
socket   = /var/run/mysqld/mysqld.sock
basedir  = /usr

Нас интересует параметр password. Копируем это пароль, после чего в MySQL необходимо выполнить запрос:

mysql> GRANT ALL PRIVILEGES ON *.* TO 'debian-sys-maint'@'localhost' IDENTIFIED BY 'n4aSHUP04s1J32X5';

С первого раза не сработало, MySQL ругался на то, что пароль не соответствует правилам безопасности. Тогда просто можно добавить к паролю любой символ и повторить команду. При этом не забудьте указать новый пароль в фале debian.cnf.

Для того чтобы имения вступили в силу, необходимо перезапустить MySQL.

Сброс пароля MySQL

В интернете достаточно много материалов про сброс пароля root в MySQL 5.7. Процесс достаточно простой и уже много раз описывался в сети, но связи с тем, что метод опробован на практике, решил записать последовательность своих действий. Все действия выполнялись в Ubuntu 16.04 и MySQL 5.7.

Проверим версию MySQL:

mysql --version
mysql  Ver 14.14 Distrib 5.7.16, for Linux (x86_64) using  EditLine wrapper

От версии пакета MySQL будет зависть SQL-запрос, который необходимо выполнить для изменения пароля. Далее останавливаем MySQL:

service mysql stop

Создаем каталог, устанавливаем на него права:

mkdir -p /var/run/mysqld
chown -R mysql /var/run/mysqld

Запускаем MySQL без загрузки grant tables, в целях безопасности отключаем сеть:

mysqld_safe --skip-grant-tables --skip-networking &

Теперь мы можем подключится к MySQL без использования пароля:

mysql -u root

Перезагрузим таблицы привилегий:

mysql> FLUSH PRIVILEGES;

Теперь осталось только изменить пароль root. Если у вас MySQL 5.7.6 или новее, MariaDB 10.1.20 или новее, используем следующую команду:

ALTER USER 'root'@'localhost' IDENTIFIED BY 'new_password';

Для версий MySQL 5.7.5 или старее, MariaDB 10.1.20 или старее, используем команду:

SET PASSWORD FOR 'root'@'localhost' = PASSWORD('new_password');

Результат выполнения команды должен выглядеть следующим образом:

Output
Query OK, 0 rows affected (0.00 sec)

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

mysql -u root -p

Таким образом, мы спросили пароль root и получили доступ к MySQL с правами администратора.

Включаем поддержку Brotli в Nginx

Этот алгоритм сжатия появился совсем недавно, связи с чем о использовании Brotli еще мало упоминаний в сети. Для начала необходимо упомянуть о том, что этот Brotli из себя представляет. Если кратко, Brotli — алгоритм сжатия данных основанный на современном варианте алгоритма LZ77. Brotli был разработан и представлен компанией Google в 2015 году как специализированный алгоритм для сжатия веб-шрифтов. В дальнейшем была представлена версия Brotli, которая содержала улучшения направленные на сжатие всего интернет-трафика (HTML, CSS, JS).

Сейчас момент Brotli используют для ускорения загрузки веб-страниц, его поддержка включена по умолчанию в Chrome 51+, Firefox 47+ и мобильным Chrome. По сравнению с gzip, алгоритм Brotli показывает сравнимую скорость, но при этом имеет лучшие показатели сжатия данных. Следует отметить, что Brotli несовместим с gzip и работает только для HTTPS-ресурсов.

На данный момент нет официального модуля для поддержки Brotli в Nginx. Зато мы имеем возможность использовать сторонние модули, которые параллельно развиваются Google и Cloudflare. В данном посте я расскажу о сборке Nginx с включенным модулем Brotli от Cloudflare. Если интересно, то исчерпывающую информацию по работе алгоритма Brotli можно найти в блоге Cloudflare.

Процесс аналогичен сборке Nginx с любыми другими модулями. Для начала необходимо скачать исходники Nginx. Добавим в файл /etc/apt/sources.list официальный репозиторий для mainline-ветки Nginx:

deb http://nginx.org/packages/mainline/debian/ codename nginx
deb-src http://nginx.org/packages/mainline/debian/ codename nginx

Скачиваем и устанавливаем PGP-ключ, после чего не забудьте обновить индекс пакетов apt:

cd /tmp/ && wget http://nginx.org/keys/nginx_signing.key && apt-key add nginx_signing.key
apt-get update

Устанавливаем пакет dpkg-dev и все необходимые для сборки Nginx зависимости:

apt-get install dpkg-dev
apt-get build-dep nginx
apt-get install git autoconf libtool

Скачиваем исходники Nginx:

cd /usr/src
apt-get source nginx

Получаем код модуля ngx_brotli_module:

git clone https://github.com/cloudflare/ngx_brotli_module.git

В каталог с модулем ngx_brotli_module необходимо загрузит исходники библиотеки libbrotli:

cd /usr/src/ngx_brotli_module
git clone https://github.com/google/brotli.git

Перед началом сборки и компиляции необходимо внести изменения в конфигурационный файл:

nano /usr/src/nginx-1.11.5/debian/rules

Необходимо добавить путь к исходникам ngx_brotli_module в содержимое переменно CFLAGS:

config.status.nginx: config.env.nginx
        cd $(BUILDDIR_nginx) && \
        CFLAGS="" ./configure --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --add-module=/usr/src/ngx_brotli_module --with-cc-opt="$(CFLAGS)" --with-ld-opt="$(LDFLAGS)"
        touch $@

Дополнительно рекомендую собрать Nginx c поддержкой APLN. Переходим к компиляции и сборке deb-пакета Nginx:

cd /usr/src/nginx-1.11.5
dpkg-buildpackage -rfakeroot -uc -b

Если в процессе не было ошибок, то в рабочем каталоге мы увидим собранные deb-пакета Nginx.

Для активации режима сжатия Brotli указываем следующие параметры:

brotli on;
# уровень компрессии от 1 до 11
brotli_comp_level 6;
# минимальный размер файла для использования сжатия
brotli_min_length Num;

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

Очистить журнал systemd

На сегодняшний день systemd стал де-факто стандартом для современных Linux-систем. Его компонент journal cобирает все системные сообщения: сообщения ядра, служб и приложений. После чего происходит их запись в виде бинарных файлов. Для просмотра и управления файлами логов используется утилита journalctl.

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

Однако ситуация требует внимания и нуждается в периодическом мониторинге. Чтобы посмотреть общий размер файлов журнала systemd, достаточно выполнить команду:

journalctl --disk-usage

Что бы ограничить бесконтрольное хранение журнала, нам необходимо выполнить настройку ротации логов. С помощью опций −−vacuum-size и −−vacuum-time мы можем соответственно установить предельно допустимый размер и срок хранения для хранимых на диске логов.

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

journalctl --vacuum-size=1G

Подобным образом образом работает опция −−vacuum-time. Команда установит для логов срок хранения, по истечении которого они будут удалены автоматически:

journalctl --vacuum-time=1years

Дополнительно нужно прописать настройки ротации логов в конфигурационный файл:

vi /etc/systemd/journald.conf

Настройки ротации логов включают следующие параметры:

# Максимальный объём логов на диске
SystemMaxUse=
# Объём свободного места на диске после сохранения логов
SystemKeepFree=
# Объём файла лога, по достижении которого он должен быть удален
SystemMaxFileSize=
# Максимальный объём, который логи могут занимать в /run
RuntimeMaxUse=
# Объём свободного места, которое должно оставаться в /run после сохранения логов
RuntimeKeepFree=
# Объём файла лога, по достижении которого он должен быть удален из /run.
RuntimeMaxFileSize=

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

systemctl restart systemd-journald