Что делать при зависании программ в Linux?
Ни одна современная операционная система (ОС), какой бы совершенной она ни была, не избавлена от вероятности зависаний и/или сбоев. Однако, какими бы ни были зависания и как бы часто они не происходили, всегда следует уметь выходить из подобных ситуаций с наименьшими потерями и ущербом для системы. О том, как правильно это делать в системах Linux. Какие вообще бывают ситуации, связанные с зависанием процессов или самой системы, будет изложено в данной статье.
Почему зависают программы и приложения?
В первую очередь это происходит из-за действий пользователей. Система не может предусмотреть все без исключения ситуации, которые потенциально могут вызвать сбой или зависание. А действия самого пользователя порой бывают чрезмерно необдуманными.
Некачественное программное обеспечение (ПО), которое не было должным образом протестировано разработчиками. А также ПО сомнительного происхождения также являются частой причиной зависаний.
Аппаратная составляющая также оказывает существенное влияние на работу ОС. Например достаточный объём оперативной памяти, стабильные частоты, на которых она работает, высокоскоростная дисковая подсистема. Всё это является важным фактором, существенно снижающим вероятность зависаний.
Системы на основе Linux заслуженно и неоспоримо считаются наиболее устойчивыми к различного рода сбойным ситуациям. Ядро этих систем действительно, работает очень стабильно и способно «переваривать» нагрузки в круглосуточном режиме на протяжение очень длительного времени. Системы Windows такими показателями похвастаться не могут. Именно поэтому, управление самыми высоконагруженными серверами, где критически важна надёжная работа системы. Доверяют именно Unix/Linux.
Но, как бы ни была надёжна Linux, сбои и зависания происходят и в этой ОС. В подавляющем большинстве случаев они связаны либо с устаревшей, маломощной аппаратной составляющей, либо с нестабильным ПО. В последнем случае это касается по большей части настольных компьютеров обычный пользователей. Где используются различные графические оболочки. Что и говорить, графическая подсистема — одна из наиболее уязвимых для сбоев в ОС Linux.
Завершение зависших приложений в командной оболочке
Прежде всего необходимо знать и понимать, каким образом идентифицировать зависший процесс. Ну а дальше попытаться его завершить принудительно.
Каждому процессу в системе соответствует свой уникальный идентификатор (PID). При помощи которого система им управляет, в частности может завершить. Самым простым способом узнать PID процесса является команда pidof:
В данном случае в качестве аргумента указывается имя процесса. Для примера используется утилита psensor. Считывающая показания, предоставляемые различными провайдерами для системных датчиков: lm-sensors, hddtemp, udisks2 и т. д. Если, к примеру, замечено, что psensor не обновляет показания датчиков, т. е. предполагается, что эта утилита зависла. То завершить её можно командой kill, передав ей соответствующий PID:
Эта команда предназначена для отправки сигналов управления процессам. По-умолчанию завершает процесс. Для завершения процессов по их имени существует команда killall:
Однако, использование kill по идентификаторам процессов более корректно. К тому же команда kill более предпочтительна для крепко зависших процессов. И обладает более гибкими возможностями.
Вообще в таких случаях может быть проблематично использовать или запустить командную консоль. Поскольку она также может зависнуть. Тогда можно попытаться переключиться на параллельный сеанс комбинацией клавиш . Где N – номер функциональных клавиш от 1 до 12, например F1, F2, . . . F12. И уже оттуда продолжить работу с процессами.
Зависание графической оболочки в Linux
Как уже было отмечено выше, если в системе установлена и работает какая-либо из графических оболочек (GNOME, KDE, Xfce и т. д.), то это лишний повод увидеть перед собой зависшее окно какого-либо приложения, либо даже целиком некликабельный рабочий стол. В таком случае удобно воспользоваться графическим менеджером процессов и управлять ими визуально. Используя элементы интерфейса и контекстное меню процесса.
Но бывает также и так, когда рабочий стол не реагирует ни на клики мыши, ни на привязанные к нему клавиатурные комбинации. В этом случае остаётся задействовать виртуальные терминалы. Переключившись на один из них, как это указано в предыдущей главе по нажатию сочетаний клавиш . Стоит отметить, что при переключении на такой терминал необходимо сначала авторизоваться в системе через него. После этого можно попытаться перезапустить графическую оболочку и/или X-сервер, например для Ubuntu:
Здесь lightdm или ssdm зависит от того, какая графическая оболочка используется. В последних версиях дистрибутивов Ubuntu в основном используется композитный менеджер ssdm.
Нехватка памяти и полное зависание системы
В некоторых случаях зависание процесса может быть вызвано нехваткой памяти. Особенно когда сам процесс потребляет её слишком много, т. е. Как говорят, «сильно течёт». Иногда это не очевидно, если такой процесс выполняется в фоне, а пользователь непосредственно с ним не работает. Такие случаи выявляются по первичным признакам в виде общей «заторможенности» всей системы. Когда зависший процесс отобрал большую часть ресурса памяти. В данном случае нужно выявить такой процесс, воспользовавшись командой ps. И отсортировав все процессы по количеству используемой памяти:
Будет выведена таблица, среди столбцов которой есть столбец «%MEM», указывающий количество памяти в процентном соотношении от доступной в системе и используемой соответствующим процессом, запущенным командой, указанной в столбце «COMMAND».
К примеру, если это веб-браузер Firefox, то у него может быть много связанных с ним процессов:
Их можно разом завершить:
Но может и случиться так, что даже Linux-система может зависнуть наглухо, не реагируя ни на что. В таких случаях, как правило, само ядро продолжает работать и ему можно отдавать команды, в том числе и через клавиатуру. Таким образом, можно попытаться более-менее корректно, с наименьшими потерями выполнить ручную поэтапную перезагрузку, передавая ядру соответствующие команды через клавиатурные сочетания. Эти команды следует отдавать, нажимая следующие клавиши через каждые 3-4 секунды, при этом удерживая сочетание клавиш :
- R – возврат управления клавиатурой непосредственно ядру.
- E – отправка сигнала SigTerm всем запущенным процессам.
- I — отправка сигнала SigKill всем запущенным процессам.
- U – перемонтирование всех файловых систем в режиме «только чтение».
- S – сохранение всех актуальных буферов и временных данных файловых систем на диск.
- B – собственно, перезагрузка.
На этапах 2 и 3 стоит объективно оценивать время работы команды. Если процессов запущенно много, то и времени на их завершение и уничтожение может также потребоваться несколько больше, чем 3-4 секунды.
Заключение
В заключение, стоит отметить, что хотя в системах Linux далеко не так часто случаются вообще какие-либо зависания. Однако всё же необходимость правильно и быстро вывести систему из нештатного состояния может возникнуть в любой момент. Такими состояниями являются рассмотренные в данной статье как зависания отдельных процессов, так и целых подсистем, например графической. Также был рассмотрен вариант с ручной перезагрузкой системы в случае её полного зависания.
Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.
Источник
Анализ зависшего процесса
# 2 года, 4 месяца назад (отредактировано 9 месяцев, 1 неделя назад)
Цель чисто ознакомительная — ознакомить с основными моментами и утилитами. Все это есть в интернете, но разбросано по разным статьям. Просто приходилось несколько раз этим заниматься, а потому имелись некоторые наброски, с которыми и решил поделиться.
Повторюсь, это небольшая часть, чтобы не теряться и иметь хоть какой то план действий для проведения анализа, что при желании всегда можно расширить, благо интернет пока работает.
Процесс — это объект, который состоит из адресного пространства памяти и набора структур данных. Процессы являются частью операционной системы.
Грубо говоря, процесс это запущенная программа или служба … но следует отметить, что работающая программа содержит один или более процессов.
Также следует отметить, что наряду с процессами есть понятие задача, которую выполняет командный процессор. Задача — это рабочая единица командного процессора. Задачи находятся на более высоком уровне, чем процессы, операционная система ничего о них не знает.
Обычно, если процесс в течение некоторого времени не отвечает на запросы, то принято это событие считать зависанием процесса.
Хотя, если быть точным, для процесса не существует понятия зависания, он не может зависнуть в понимаемом нами смысле. Вот что об этом пишут умные дяди, привожу без перевода, (буду приводить такие цитаты и в дальнейшем — отношение свое к этому высказывать не буду, пусть каждый решает сам)
Но мы также будем употреблять термин зависание процесса в его обычном понимании.
Как правило к зависанию процесса приводят следующие основные причины
— нехватка оперативной памяти
— использует 100% CPU
— уход в бесконечный цикл
— блокировки
— можно отнести и дисковые операции ввода/вывода
Команда, позволяющая определить зависание процесса отсутствует. А потому чтобы выяснить, что процесс завис, необходимо задействовать целый комплекс утилит, при условии, конечно, что есть доступ к терминал-эмулятору или консоли. И конечно в результе анализа необходимо будет установить — завис процесс или не завис и установить причину этого зависания.
Привожу опять цитату умных дядей
1. А потому начинать лучше с самого простого — узнать потребление памяти, нагрузку cpu.
Для этого можно использовать простую утилиту ps
— сортировка по памяти (1-ая команда) или сортировка по нагрузке cpu (2-ая команда)
PS — вместо head -5 можно применить grep
Но если причина в нехватке памяти, то будут тормоза как при открытии терминала, так и ввода команды, так и при ожидании ответа при выполнении команды. В этом случае рекомендую использовать прямую связь с ядром (использовать волшебные кнопки)
ALT+SysRq+f — вызов oom_kill, чтобы убить самый жрущий процесс (действует не сразу, придется подождать несколько минут)
PS 1 — не забывем, что значение /proc/sys/kernel/sysrq должно быть равно 1.
PS 2 — рекомендую читать логи (обычно запускаю journalctl -f) — oom_kill работает хитро, если он считает, что памяти достаточно, то ни одно приложение убито не будет, просто выдаст сообщение. Привожу пример запуска в нормальном состоянии
На любителя можно использовать top, htop, atop, vmstat и др., которые позволяют узнать нагрузки памяти и процессора (некоторые позволяют узать и нагрузку на дисковые операции ввода/вывода).
2. Имеются простые способы узнать/оценить, находится процесс в зависшем состоянии или нет. Правда в поиске виновника это нам не поможет, но хотя бы прояснит немного ситуацию.
2.1 Посмотреть параметр state процесса
можно добавить это в команду ps -eo pid,state,pcpu,pmem,comm | grep
или сразу обратится к первоисточнику, из которого ps черпает эту информацию
cat /proc/
/status | grep State
2.2 Есть еще два интересных параметр voluntary_ctxt_switches и nonvoluntary_ctxt_switches (показывают сколько раз процессор получал кванты CPU и отдавал назад)
cat /proc/
/status | grep voluntary
Если с течением времени эти параметры не меняются, то это говорит о том, приложение зависло.
2.3 Можно узнать место в коде ядра, где зависло — узнать имя функции, которая привела процесс к состоянию спячки/ожидания.
Для этого можно использовать ту же утилиту ps, но добавив поле wchan
ps -eo pid,pcpu,pmem,comm,status,wchan | grep
или посмотреть параметр stack
cat /proc/
/stack
Верхняя функция (верхушка стэка) и покажет эту функцию. Что означает эта функция, можно нагуглить.
Есть и другие ядерные вещи, но, имхо, толку от них обычным юзерам мало, нам нужно узнать хотя бы причину, намек, виновника блокировки, если это блокировка.
А потому здесь нужны более серъезные утилиты.
PS 1 — уточнение для утилиты ps в части wchan — это адрес события, которого ожидает процесс. У активного процесса эта колонка пустая.
PS 2 — можно для нахождения значений wchan использовать и такую штуку
cat /proc/
/stat | ./procstat
Например, для активного нормального процесса palemoon
где procstat — небольшая програмка для распарсивания вывода cat /proc/
/stat (имеется исходник procstat.c, который нужно скомпилить).
3. Посмотрели и убедились, что приложение зависло, далее нужно использовать другие утилиты.
Привожу опять цитату умных дядей
Явный признак такого состояния — 0% CPU, что означает, что процесс находится в каком-то блокирующем системном вызове, который приводит к тому, что ядро усыпляет процесс.
3.1 В этом случае рекомендуют утилиту strace (приаттачится к процессу)
вообщем на любителя и описывать нюансы работы утилиты strace не буду (всего не опишешь).
Только отмечу один момент — блокировки — в конце вывода будет строка типа — flock(3, LOCK_EX, что говорит о том, что файл, имеющий дескриптор 3, заблокирован.
Нужно узнать что это за файл — ls /proc/
/fd , получим что то типа /tmp/file.lock
и далее находим процесс, удерживающий этот файл — lsof | grep /tmp/file.lock
3.2 Можно использовать и утилиту gdb, но для получения информативности необходимо чтобы пакет исследуемого приложения был собран с отладочной информацией. Хотя если анализировать только стэк, то можно и без отладочной информации — как правило, если трассировка стека не меняется с течением времени (достаточно несколько проверок с периодичностью в несколько минут), то приложение висит. Также на вершине стэка увидим функцию, которая к этому привела.
А вот чтобы выполнить отладку зависшего процесса, необходимо, во 1-ых, чтобы пакет был собран с отладочной информацией и, во 2-ых, иметь навык использования отладки с помощью gdb.
4. И напоследок — иногда наблюдается не зависание, как таковое, а небольшая задержка при выполнении/старте приложения (может доходить до нескольких секунд). В этом случае может помочь комбайн sysdig — описывать не буду, а даю ссылку на один из топиков, в котором был найден виновник, с использованием sysdig (там же можно найти и установку и ссылку на описание).
EDIT 1 — и, конечно, у кого появится что то новенькое, уточняющее неплохо выкладывать здесь же — пусть все будет в одном месте.
.
Дополнение/уточнение от 05.06.2019
В части зависания можно придерживаться следующих правил (но не забывать, что бывают и исключения)
Приложение скорее всего заблокировано и ничего не делает если cpu и mem не загружены.
Приложение находится в бесконечном цикле — cpu под 100% и возможно загружена память.
Приложению не хватает памяти — сильное торможение, долгий ответ на запросы, загружена память.
ОЖИДАНИЕ — пассивное состояние процесса, процесс заблокирован (скорее всего на каком-то системном вызове), точнее, процесс не может выполняться, так как ожидает некоторого события, вероятнее всего завершения операции ввода-вывода и менее вероятно получения сообщения от другого процесса или освобождения какого-либо необходимого ему ресурса.
И если процесс висит долго, то, как правило, убить процесс не удается, так как теряется связь ядра с процессом и не срабатывают даже волшебные клавиши. Но пробовать их всеравно нужно, чтобы уточнить наличие/отсутствие связи с ядром.
Дополнение в части определения ядерного кода/функции/ или как говорят системного вызова на котором заввисли.
Вместо cat /proc/
/stack можно также использовать и cat /proc/
/syscall , вывод которого покажет нам номер системного вызова — будет что то типа такого, где 7 (1-ая цифра) это номер системного вызова
и далее узнаем название системного вызова по его номеру
grep 7 /usr/include/asm/unistd_64.h
#define __NR_poll 7
В части определения зависшего дескриптора (при использование strace) вместо ls /proc/
/fd можно использовать readlink /proc/
И еще про волшебные кнопки — комбинация Alt+SysRq+t — выведет всю информацию о запущенных процессах и плюс стэк — будет слишком большой вывод, но возможно и пригодится (лучше использовать в паре с journalctl -f)
PS — ‘t’ — show-task-states. Will dump a list of current tasks and their information to your console.
.
Уточнение от 06.12.2020
Источник