Linux мониторинг процесса и перезапуск

Обновлено: 04.07.2024

На самом деле я не уверен, стоит ли мне использовать Shell Scripts или уже есть какие-то способы. Но какой бы подход мы ни использовали, я бы хотел, чтобы Служба работала постоянно.

Скажем, iptables в качестве примера. Затем ..

(Может быть, я мог бы дать достаточно частую проверку, если проблема заключается в проверке в реальном времени . Так скажем, каждые 5 минут)

Единственный способ, которым я мог придумать, это использовать сценарии оболочки с Cron Tab.

4 ответа 4

Обновление март 2018

Этот ответ сейчас довольно старый, и с момента его написания, systemd выиграл войну pid1 в Linux. Таким образом, вам, вероятно, следует создать системный модуль, если systemd встроен в ваш дистрибутив (а это большинство из них).

Ответ ниже сохраняется для потомков.

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

Стоит помнить, что ваша операционная система уже решила проблему управления процессами. Традиционно в Linux используется sysvinit, который представляет собой набор скриптов, которые вы видите в init.d. Однако он довольно тупой и не может отслеживать процессы, сценарии init.d сложны и заменяются по уважительной причине.

Более современные операционные системы начинают заменять sysvinit, а лидерами являются Upstart и Systemd. Debian склоняется к systemd, Ubuntu разработал и уже почти перешел на Upstart, и, подобно Debian Redhat/CentOS/Fedora, движется к systemd. Таким образом, если вы используете ОС, которая уже заменила sysvinit, я бы порекомендовал использовать встроенную. Сценарии гораздо проще написать, чем сценарии инициализации.

Я использовал runit и мне это очень нравится, но проще всего использовать supervisor. Он также очень хорошо документирован, работает практически везде и упакован во все основные дистрибутивы.

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


У тех, кто далек от химии, но близок к IT, ассоциация немного другая, но в целом похожая — обычно это экран с кучей графиков, на которых творится какая-то магия, как в голливудских сериалах. Для многих администраторов так оно и выглядит — Graphite/Icinga/Zabbix/Prometheus/Netdata (нужное подчеркнуть) как раз рисуют красивый интерфейс, в который можно задумчиво глядеть, почесывая бороду и гладя свитер.

Большинство этих систем работают одинаково: на конечные ноды, за которыми мы хотим наблюдать, устанавливаются так называемые агенты, или коллекторы, а дальше все происходит по методике push или pull. То есть либо мы указываем этому агенту мастер-ноду, и он начинает периодически отсылать туда отчеты и heartbeat, либо же, наоборот, мы добавляем ноду в список для мониторинга на мастере, а тот уже, в свою очередь, сам ходит и опрашивает агенты о текущей ситуации.

Нет, я не буду рассказывать в подробностях, как настраивать подобные системы. Вместо этого мы голыми руками докопаемся до того, что вообще происходит в системе. Кстати, хороший перечень утилит для сисадмина приведен в статье Евгения Зобнина «Сисадминский must have». Настоятельно советую взглянуть.

Средняя температура по больнице

Об одной из самых базовых метрик часто рассказывают на первых же занятиях по Linux даже в школах. Это всем известный uptime, он же время непрерывной работы системы с момента последней перезагрузки. Утилита для его измерения называется точно так же и выдает целую строчку полезной информации:

В начале идет текущее время, потом собственно аптайм, потом количество залогинившихся в систему пользователей, а дальше показатели load average, те самые таинственные три цифры, о которых часто спрашивают на собеседованиях. Кстати, есть еще команда w , которая выдает ту же самую строчку плюс чуть более подробную информацию о том, что каждый из юзеров делает.

Информацию об uptime можно посмотреть напрямую в /proc , только в таком случае она будет слегка менее интерпретируемой:

Здесь первое число — это сколько секунд система работала с момента старта, а второе — сколько из них она работала «вхолостую», не делая толком ничего.

Но давай остановимся подробнее на load average, ибо тут есть один подвох. Еще раз взглянем на числа, в этот раз воспользовавшись интерфейсом /proc (числа те же самые, различается только способ):

Тебе не составит труда найти информацию, что в UNIX-системах эти числа означают усредненное количество процессов, стоящих в очереди за ресурсами CPU, причем взятые в трех временных периодах до текущего момента: 1 минуту, 5 минут и 15 минут назад. Дальше, четвертая колонка — это разделенные слешем количество процессов, выполняющихся в системе сейчас, и количество процессов в системе вообще, а пятая — последний выданный системой PID. Так где же здесь подвох?

А подвох в том, что это верно для UNIX, но не для Linux. С виду все нормально: если числа уменьшаются — нагрузка снижается, если увеличиваются — растет. Если ноль — система простаивает, если равна числу ядер — значит, загрузка под 100%, если в выводе десятки и сотни… стоп, что? Формально Linux учитывает не только процессы в статусе RUNNING, но и процессы, находящиеся в UNINTERRUPTIBLE_SLEEP, то есть висящие на вызовах в ядро. Это значит, что на эти числа могут также оказывать влияние I/O-операции, да и далеко не только они, потому что вызовы в ядро не ограничиваются I/O. Пожалуй, я здесь остановлюсь, а за подробностями рекомендую проследовать вот в эти две статьи: «Как считается Load Average», «Load Average в Linux: разгадка тайны».

Файлы, которых нет

Если говорить совсем откровенно, в Linux основным источником информации как о процессах, так и о железе служит именно файловая виртуальная файловая система procfs (/proc ), а также sysfs (/sys) . И у них довольно богатая и интересная история.

Дело в том, что одно из официальных положений идеологии UNIX гласит: «Всё есть файл», то есть взаимодействие с любым системным компонентом теоретически должно вестись через реальный или виртуальный файл, доступный через обычное дерево каталогов. Эту идею до абсолюта довели в наследнике UNIX под названием Plan 9, где все процессы превратились в каталоги и взаимодействовать с ними можно было даже посредством команд cat и ls , поскольку они были текстовыми. Именно так появилась файловая система procfs, которая позже перекочевала в Linux и BSD.

Но, как и в случае с load average, конкретно в Linux есть свои тонкости (это я так политкорректно называю адскую кашу-малашу). Например, линуксовый /proc , вопреки названию, с самого начала был универсальным интерфейсом получения информации от ядра в целом, а не только от процессов. Более того, именно взаимодействовать с процессами через эту систему практически не получается, только извлекать информацию по их PID’ам.

С течением времени в /proc появлялось все больше и больше файлов, содержащих информацию о самых разных подсистемах ядра, железе и многом другом. В конечном итоге он превратился в помойку, и разработчики решили вынести информацию хотя бы о железе в отдельную файловую систему, которую к тому же можно было бы использовать для формирования каталога /dev . Так и появилась /sys со своей странной структурой каталогов — ее трудно разгребать вручную, но она очень удобна для автоматического анализа другими приложениями (такими как udev, который и формирует содержимое каталога /dev на основе информации из /sys ).

В итоге куча информации до сих пор дублируется в /proc и /sys просто потому, что, если выкинуть файлы из /proc , можно сломать некоторые фундаментальные системные компоненты (легаси!), которые до сих пор не переписаны.

Ну а еще есть /run , конечно же. Это файловая система, которая монтируется одной из первых и служит перевалочным пунктом для данных рантайма основных системных демонов, в частности udev и systemd (о нем поговорим отдельно чуть позже). Кстати, сам проект udev в 2012 году влился в systemd и дальше развивается как его часть.

В общем, как писал Льюис Кэрролл, «все чудесатее и чудесатее».

Но вернемся к нашим замерам. Для того чтобы смотреть, какие PID присвоены процессам, есть команды pidstat и htop (из одноименного пакета, более продвинутая версия top, заодно показывает чертову прорву всего, аналог графического диспетчера задач).

Кроме того, команда time позволяет запустить процесс, попутно измерив время его выполнения, точнее, целых три времени:

Как выше я уже проговорился, любая программа может проводить разное время в kernel space и user space, то есть выполняя вызовы в ядро или свой собственный код. Поэтому при базовом взгляде на эти цифры можно в некоторых случаях уже сделать вывод об узком месте в программе: если первый показатель сильно выше, то, вполне возможно, затык в I/O, а если второй — то, возможно, в коде есть неэффективно написанные куски, которые стоит запрофилировать подробнее.

А вот третье время, total time, оно же wall clock time или real time, — это время, которое реально заняло выполнение программы с момента запуска до момента возврата управления. Кстати, user time может быть сильно больше real time, потому что оно рассчитывается как сумма по всем ядрам CPU. Если такое происходит — значит, программа неплохо параллелится.

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

Если будут сильные перекосы в загрузке ядер — значит, какая-то из программ, напротив, параллелится крайне плохо. А единичка значит «обновляй-ка раз в секунду».

Получше, чем у золотой рыбки

Что в науке, что в инжиниринге периодически возникает одна и та же «проблема» — нельзя просто так взять и ответить на, казалось бы, простой вопрос. Все потому, что есть нюансы и тонкости, а задающий вопрос человек начинает злиться и говорить: «Не надо мне этого всего, ты мне цифру назови». А потом зависает, когда внезапно оказывается, что разные утилиты показывают абсолютно разные значения, скажем, для размера файла или для количества доступной оперативки…

Кстати, об оперативке. Поскольку это у нас железо, то мы можем первым делом опять нахально проследовать в /proc :

…и получить кучу разных цифр, из которых большая часть абсолютно непонятна, так как это вообще все параметры нашей RAM, которые видит ядро. Поэтому лучше все-таки использовать старую добрую команду free :



Кстати, почему мы получаем информацию об оперативке не из /sys , как я описал во врезке? Да потому что «пошел ты, вот почему». Вот ссылка на заметочку, в которой написано, где там память в /sys и как с ней работать: How memory is represented in sysfs. Если кратко — придется перемножать в уме и читать кучу разных файлов.

Как ни странно, есть возможность получить и более низкоуровневую информацию об оперативке, чем /proc/meminfo . Это утилита dmidecode из одноименного пакета. Она общается непосредственно с BIOS и возвращает даже имена вендоров-производителей. Правда, не всегда верные (особенно весело запускать ее под гипервизором, но это совсем другая история).



Кстати, top и htop, как и банальный ps aux , тоже выводят информацию о занятой памяти, а второй еще и диаграмму в ASCII рисует по ней и по ядрам. Цветную. Лепота.

Первые две колонки очевидны:

  • PID — идентификатор процесса;
  • User — пользователь, от которого он запущен.

А вот две следующие чуть интересней: Priority и Niceness, причем первая в общем случае равна второй + 20. По сути, Priority показывает абсолютное значение приоритета процесса в ядре, а Niceness показывает значение относительно ноля (ноль обычно назначается по умолчанию). Этот самый приоритет учитывается при выдаче процессу квантов процессорного времени, поэтому, формально говоря, при увеличении приоритета командой renice можно заставить какую-нибудь сильно CPU-bound задачу выполняться чуточку быстрее. Для процессов реального времени в колонке Priority будет стоять rt, то есть real time, «как только — так сразу».

Дальше следуют данные о памяти:

  • VIRT — виртуальная память, «обещанная» процессу системой;
  • RES — фактически используемая память (кстати, благодаря механизму copy-on-write может быть несколько (N) форков одного и того же процесса с одним и тем же числом M в этой колонке, что вовсе не значит, что сожрано N*M памяти, потому что они разделяют ее между собой);
  • SHR — shared memory, то есть память, которая потенциально может использоваться для межпроцессного взаимодействия.

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

  • CPU% — сколько процентов CPU жрет процесс; легко может быть больше 100%, если параллелится на несколько ядер;
  • MEM% — процент памяти, потребляемой процессом;
  • TIME+ — сколько времени процесс бежит;
  • COMMAND — какая команда (программа + аргументы) запущена.

Но мы же хотим идти еще глубже, надо больше подробностей!



Здесь тоже много колонок, для простоты взглянем на четыре:

  • r — размер очереди процессов на доступ к памяти;
  • b — число процессов в uninterruptible sleep;
  • si/so — сколько страниц памяти в текущий момент пишется в своп / читается из свопа.

Надо ли явно подчеркивать, что в идеальном мире в них должны быть ноли?

Где хранить коллекцию лютневой музыки

Если ты хоть раз размечал диск руками (например, при установке Arch Linux), то наверняка знаешь о существовании утилиты fdisk . С ее помощью проще всего посмотреть разделы на этом самом диске:



Есть ее более развесистая версия с псевдографическим интерфейсом, называется cfdisk, а также еще пара утилит, которые, на первый взгляд, делают весьма похожие вещи — позволяют управлять разделами на дисках. Это parted (к которому, кстати, есть неплохой GUI на GTK в лице gparted) и gdisk. Наличие такого зоопарка связано с тем, что существует несколько вариантов структурирования разделов на диске, и исторически для разных вариантов использовались разные программы. Наверняка ты уже встречал такие аббревиатуры, как MBR и GPT. Я не буду подробно останавливаться на различиях, но почитать можно, например, в статье «Сравнение структур разделов GPT и MBR». Там оно обсуждается с позиции настройки Windows, но суть от этого не меняется. И да, в современном же мире fdisk уже умеет работать с обоими вариантами, как и parted, поэтому выбирать можно исключительно из личных предпочтений.

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

Как и раньше, -h тут отвечает за «человеческий» вывод размеров. Ну и как ты помнишь, размеры файлов у нас можно посмотреть командой du :

Наверняка часть читателей сейчас подумала: «Ну что за банальщина, это даже школьники знают, давай чего посвежее». Ладно, давай привнесем реалтайма, как уже делали с оперативкой:



Эта команда выводит средние значения количества операций чтения-записи для всех блочных устройств в системе, обновляя информацию раз в секунду. Это больше «железные» параметры, поэтому есть еще одна команда для просмотра статистики I/O попроцессно, и она, по аналогии, называется iotop.



При попытке запуска без прав root она начнет очень мило оправдываться, что, мол, есть один такой баг CVE-2011-2494, который может приводить к утечке потенциально важных данных от одних пользователей другим, «поэтому настрой-ка ты, дружочек, sudo». Оно и верно.

Пакеты брать будете?

Что еще из операций ввода-вывода у нас осталось? Правильно, сетевое взаимодействие. Здесь царит та еще чехарда — «официальные» утилиты меняются от релиза к релизу, что, с одной стороны, круто, потому что удобств становится больше, с другой — надо переучиваться каждый раз.

Скажем, какой утилитой смотреть существующие в системе интерфейсы? Кто сказал ifconfig ? На современных системах ifconfig, как правило, уже вообще отсутствует, ибо есть



Вроде выглядит немного по-другому, а вроде то же самое. Кстати, для управления сетевыми мостами из консоли часто необходимо ставить пакет bridge-utils. Тогда в консольке появится утилита brctl , с помощью которой можно будет их просматривать ( brctl show ), ну и менять. Но иногда бывает по-другому. Мне встречался случай, когда бриджи были, а brctl их не показывал. Оказалось, что для их создания использовался Open vSwitch и кастомный модуль ядра, для настройки которого надо взять другую утилиту — ovs-vsctl . Если вдруг у тебя окружение на OpenStack, где эта штука активно используется, — может быть полезно.

Дальше — как насчет таблиц маршрутизации? Как, говоришь, route -n ? Нет, мимо. Сейчас чаще используются netstat -nr и ip route show . Ну и самое банальное — как посмотреть открытые порты и процессы, которые их запросили? Например, вот так:



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



Да, sar — это еще одна отличная утилита для мониторинга. Умеет показывать не только сетевые операции, но и диски и активность процессора. Почитать о ней можешь, например, в статье «Простой мониторинг системы с помощью SAR».

Также sar позволяет мониторить открытие/закрытие соединений и ретрансмиты (это повторные отправки тех же данных, когда сетевое оборудование сбоит или коннект крайне нестабильный, очень помогает траблшутить) в реальном времени.



Ну и последнее — конечно, по порядку, а не по значению — это просмотр самого сетевого трафика. Чаще всего для этого используют две утилиты: tcpdump и wireshark. Первая — консольная, ей можно, к примеру, запустить прослушивание на всех интерфейсах и записать трафик в дамп-файл в формате pcap:

Вторая же — графическая. Из нее можно точно так же запустить прослушивание, а можно просто открыть в ней готовый файл дампа, слитый с удаленного сервера. И наслаждаться красотой слоев модели OSI (точнее, TCP/IP).

Если тебя окружили демоны — логируй их немедленно!

Один из самых простых и банальных способов проверить, что происходит в системе, — это посмотреть системные логи. Вот тут можно почитать о том, какие секреты скрываются в каталоге /var/log и откуда они там берутся. До недавнего времени основным механизмом записи логов был syslog, точнее, его относительно современная реализация rsyslog. Она до сих пор активно используется, если интересно почитать, где там что, — можно глянуть, например, сюда.

А что в авангарде? В современных дистрибутивах Linux на основе systemd используется свой механизм логирования, которым можно управлять через утилиту journalctl. Там есть крайне удобная фильтрация по разным параметрам и прочие плюшки. Ссылка на хороший обзор.

Сам же systemd до сих пор остается довольно жарким топиком для обсуждения, поскольку «подминает» под себя многие устоявшиеся инструменты и предоставляет альтернативы к существующим решениям. Например, как запускать какой-то процесс регулярно? Crontab? Вовсе не обязательно, теперь у нас есть systemd timers. А как насчет настройки реакций на системные и «железные» события? В systemd есть поддержка watchdog. А что там со сменой корня — старый добрый chroot? Необязательно, теперь есть новенький systemd-nspawn.

Информация — это новое золото

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

Список процессов

Вывести на экран список текущих процессов, запущенных пользователем, можно командой:

Чтобы посмотреть список всех процессов с дополнительной информацией, вводим:

Мы увидим, примерно, следующее:

USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 661 0.0 0.0 4072 8 tty1 Ss+ Jul03 0:00 /sbin/mingetty
root 662 0.0 0.0 4072 8 tty2 Ss+ Jul03 0:00 /sbin/mingetty
root 16355 0.0 0.0 171636 3308 pts/0 S 15:46 0:00 sudo su
root 16366 0.0 0.0 140896 1556 pts/0 S 15:46 0:00 su
root 16368 0.0 0.0 108316 1944 pts/0 S 15:46 0:00 bash
root 18830 0.0 0.0 110244 1172 pts/0 R+ 16:20 0:00 ps u

  • USER — учетная запись пользователя, от которой запущен процесс.
  • PID — идентификатор процесса.
  • %CPU — потребление процессорного времени в процентном эквиваленте.
  • %MEM — использование памяти в процентах.
  • VSZ — Virtual Set Size. Виртуальный размер процесса (в килобайтах).
  • RSS — Resident Set Size. Размер резидентного набора (количество 1K-страниц в памяти).
  • TTY — терминал, из под которого был запущен процесс.
  • STAT — текущее состояние процесса. Могут принимать значения:
    1. R — выполнимый процесс;
    2. S — спящий;
    3. D — в состоянии подкачки на диске;
    4. T — остановлен;
    5. Z — зомби.
    6. W — не имеет резидентных страниц;
    7. < — высоко-приоритетный;
    8. N — низко-приоритетный;
    9. L — имеет страницы, заблокированные в памяти.
  • START — дата запуска процесса.
  • TIME — время запуска процесса.
  • COMMAND — команда, запустившая процесс.

Ключи

Ключ Описание
-A Все процессы.
-a Запущенные в текущем терминале, кроме главных системных.
-d Все, кроме главных системных процессов сеанса.
-e Все процессы.
f Показать дерево процессов с родителями.
T Все на конкретном терминале.
a Все, связанные с текущим терминалом и терминалами других пользователей.
r Список только работающих процессов.
x Отсоединённые от терминала.
u Показать пользователей, запустивших процесс.

Примеры

Поиск процесса с помощью grep:

ps aux | grep apache

Убить процесс

Останавливаем процесс по его PID:

Если процесс не завершается, убиваем его принудительно:

Остановить все процессы с именем nginx:

Как и в случае с kill, можно это сделать принудительно:

killall -9 nginx

Ищем процесс по имени, извлекаем его PID и завершаем его:

* обратите внимание, что запрос может вывести несколько процессов, которые будут попадать под критерии поиска — в таком случае, они будут завершены все.

Подробная информация о процессе

Для каждого процесса создается каталог по пути /proc/<PID>, в котором создаются папки и файлы с описанием процесса.

Примеры использования /proc/<PID>

Подробный вывод статуса:

Адрес в ячейках оперативной памяти, которые занял процесс:

Команда, которой был запущен процесс:

Символьная ссылка на рабочий каталог процесса:

Символьная ссылка на исполняемый файл, запустивший процесс:

Увидеть ссылки на дескрипторы открытых файлов, которые затрагивает процесс:

Потребление ресурсов процессами

Для просмотра статистики потребления ресурсов используем утилиту top:

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
21059 root 20 0 157884 2280 1496 R 18,8 0,1 0:00.03 top
1 root 20 0 190996 2964 1652 S 0,0 0,1 6:49.99 systemd
2 root 20 0 0 0 0 S 0,0 0,0 0:01.78 kthreadd
3 root 20 0 0 0 0 S 0,0 0,0 0:24.75 ksoftirqd/0
5 root 0 -20 0 0 0 S 0,0 0,0 0:00.00 kworker/0:0H

По умолчанию выставлено, что в случае падения сервиса Systemd ничего с ним не будет делать. Но пользователь всегда может выстроить настройки таким образом, чтобы в случае падения или остановки сервис автоматически перезапускался. Для этого используется директива Restart, которую надо добавить в секцию Service. Дальше рассмотрим пример настройки автоматического перезапуска сервиса Apache:

$ sudo systemctl edit apache2

[Service]

Restart=on-failure

RestartSec=5s

настройка автоматического перезапуска сервиса Apache:

Здесь RestartSec указывает, сколько ждать перед перезапуском сервиса. Когда завершите работу, сохраните изменения и выполните команду daemon-reload, чтобы перечитать конфигурацию:

Дальше, чтобы проверить все ли работает исправно, посмотрите состояние процесса, завершите процесс сигналом kill:

$ sudo systemctl status apache2

$ kill -KILL 32091

Процесс сигналом kill

Еще раз посмотрите состояние, процесс должен быть запущен. Для установки запуска инициализации каждый раз, используйте специальную директиву Restart: always. Но пользоваться ею необходимо крайне осторожно, ведь она не позволит завершить процесс, даже если в этом возникнет необходимость. Если процесс постоянно падает, чтобы он перезапускался, можно добавить лимит на количество перезапусков в секцию Service:

$ sudo systemctl edit apache2

[Service]

StartLimitIntervalSec=500

StartLimitBurst=5

Restart=on-failure

RestartSec=5s

Лимит на количество перезапусков в секцию Service

Здесь StartLimitBurst и StartLimitIntervalSec указывают на важность перезапуска сервиса пять раз, и если он все эти пять раз упадёт, то оставить его и не трогать. Вторая директива ограничивает время перезапусков сервиса до 500 секунд.

Автоматический перезапуск скриптом

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

Файл нужно сохранить и обязательно сделать его исполняемым:

chmod ugo+x /usr/local/bin/apache-monitor.sh

Не забудьте добавить запись в cron для периодического запуска скрипта:

$ sudo crontab -e

*/5 * * * * /usr/local/bin/apache-monitor.sh

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

Читайте также: