Босс: Осмелитесь выйти в интернет, не зная принципа kill-9? Не используйте его завтра!

JVM Linux

Путь Java-инженера, получившего 14,5 тысяч звезд на GitHub, к тому, чтобы стать богом, открыт для чтения!

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

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

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

Однако в процессе перезапуска мой коллега обнаружил, что обычное приложение команды перезапуска не отвечает, а затем попытался использовать команду kill, чтобы «убить» процесс Java, но это все равно не сработало. Поэтому он в частном порядке решил использовать «kill -9», чтобы завершить жизнь процесса.

Хотя процесс приложения был убит, это принесло много проблем.Во-первых, внезапно возникло большое количество аварийных сигналов в вышестоящей системе.Соответствующая разработка обнаружила, что вызов нашего RPC-сервиса не имел ответа и часто истекал тайм-аут.

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

Почему обычный kill не может «убить» процесс, в то время какkill -9может? Почемуkill -9Не вызовет ли это цепную реакцию? Когда выполняется обычное уничтожение, как JVM справится с этим?

Чтобы разобраться в этих проблемах, мы должны начать с команды kill.

убить команду

мы все знаем, хотимЕсть два способа завершить процесс в Linux: если это процесс переднего плана, вы можете использовать клавишу Ctrl+C для его завершения, если это фоновый процесс, вам нужно использовать команду kill для его завершения.(На самом деле, Ctrl+C также является командой уничтожения)

Формат команды kill:

kill[参数][进程号]

如:
kill 21121
kill -9 21121

Если [параметр] является необязательным, идентификатор процесса можно получить с помощью таких инструментов, как jps/ps/pidof/pstree/top.

Параметры команды kill следующие:

-l сигнал, если числовой параметр сигнала не добавлен, использование параметра "-l" выведет список всех имен сигналов

-a При обработке текущего процесса не ограничивает соответствие между именем команды и номером процесса

-p указывает, что команда kill печатает только идентификатор соответствующего процесса без отправки каких-либо сигналов.

-s указывает отправить сигнал

-u указывает пользователя

Как правило, мы используем-l(сигнал) время больше, как мы упоминали ранееkill -9середина9это сигнал.

Сигнал Если не указано, будет прерван сигнал по умолчанию (15). Обычно используются следующие сигналы:

Отключение клеммы HUP 1

Прерывание INT 2 (аналогично Ctrl + C)

QUIT 3 для выхода (аналогично Ctrl + \)

СРОК 15 Прекращение

KILL 9 Принудительное завершение

CONT 18 Продолжить (напротив команды STOP, fg/bg)

STOP 19 Пауза (аналогично Ctrl + Z)

Чаще используется强制终止信号:9и终止信号:15,Кроме того,中断信号:2Фактически, это Ctrl + C, о котором мы упоминали ранее, чтобы завершить процесс переднего плана.

Так,kill -9иkill -15Какая разница? Как выбрать?

Разница между убийством -9 и убийством -15

Сигнал команды kill по умолчанию равен 15. Прежде всего, поговорим об этом значении по умолчанию.kill -15Сигнал.

когда используешьkill -15, система отправит сигнал SIGTERM соответствующей программе. Когда программа получает сигнал, она может решить, как с ним поступить.

На этом этапе приложение может выбрать:

  • 1. Немедленно остановите программу

  • 2. Остановите программу после освобождения ресурса ответа

  • 3. Игнорировать сигнал и продолжить выполнение программы

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

Однако приложение может проигнорировать сигнал завершения, если оно сталкивается с блокировкой или другими проблемами в процессе «подготовки».

Вот почему мы иногда не можем «убить» приложение командой kill, потому чтоСигналом уничтожения по умолчанию является SIGTERM(15), а сигнал SIGTERM(15) можно заблокировать и игнорировать.

иkill -15по сравнению с,kill -9Чтобы быть относительно жесткой, система выдает сигнал SIGKILL, который требует, чтобы программа, получившая сигнал, немедленно завершила работу и не могла быть заблокирована или проигнорирована.

так,по сравнению сkill -15Заказ,kill -9Во время выполнения у приложения нет времени на «подготовку», поэтому это обычно имеет некоторые побочные эффекты, такие как потеря данных или невозможность восстановления терминала в нормальное состояние и т. д.

Как Java обрабатывает SIGTERM(15)

Все мы знаем, что в Linux Java-приложение работает как независимый процесс, а завершение Java-программы реализуется на основе завершения работы JVM.Есть три способа закрыть JVM:

Мягкое завершение работы: когда завершается последний поток, не являющийся демоном, или вызывается System.exit, или завершается другими специфичными для платформы методами (полученные сигналы SIGINT(2), SIGTERM(15) и т. д.).

Принудительное завершение работы: вызовом метода Runtime.halt или принудительным уничтожением в операционной системе (получен сигнал SIGKILL(9)).

Аварийное завершение работы: во время работы возникает исключение RuntimeException и т. д.

Процесс JVM получаетkill -15Когда сигнал уведомлен, вы можете выполнить некоторые действия по очистке, такие как удаление временных файлов.

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

И этоСпособ настройки действия очистки JVM реализуется с помощью обработчика выключения, предоставленного в JDK. JDK предоставляет метод Java.Runtime.addShutdownHook(Thread hook), который может зарегистрировать ловушку завершения работы JVM.

Примеры следующие:

package com.hollis;

public class ShutdownHookTest {

    public static void main(String[] args) {
        boolean flag = true;
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            System.out.println("hook execute...");
        }));

        while (flag) {
            // app is runing
        }

        System.out.println("main thread execute end...");
    }
}

Выполнение заказа:

➜ jps
6520 ShutdownHookTest
6521 Jps
➜ kill 6520

Вывод консоли:

hook execute...
Process finished with exit code 143 (interrupted by signal 15: SIGTERM)

Видно, что когда мы используем kill (по умолчанию kill -15) для закрытия процесса, программа сначала выполнит зарегистрированный мной shutdownHook, а затем выйдет и выдаст подсказку:interrupted by signal 15: SIGTERM

Если мы выполним командуkill -9:

➜ kill -9 6520

Вывод консоли:

Process finished with exit code 137 (interrupted by signal 9: SIGKILL)

Видно, что когда мы используем kill -9 для принудительного закрытия процесса, программа не выполняет shutdownHook, а завершается напрямую и выдает подсказку:interrupted by signal 9: SIGKILL

Суммировать

Команда kill используется для завершения процесса Linux.По умолчанию, если сигнал не указан, kill эквивалентенkill -15.

kill -15Во время выполнения система отправляет сигнал SIGTERM (15) соответствующей программе, которую можно выполнить, заблокировать и проигнорировать, поэтому после того, как приложение получит сигнал, оно может выполнить некоторую подготовительную работу, а затем завершить программу.

иногда,kill -15Программа не может быть завершена, потому что она может быть проигнорирована, в этом случае вы можете использоватьkill -9, система выдаст сигнал SIGKILL(9), который нельзя игнорировать и заблокировать, поэтому приложение немедленно завершает работу.

Это также принесет много побочных эффектов, таких как потеря данных и т. д., поэтому не используйте его, если в этом нет необходимости.kill -9Команды, особенно в веб-приложениях, предоставляющие службы RPC, выполняющие запланированные задачи, включающие длительные транзакции и т. д., потому чтоkill -9Недостаточно времени для завершения контейнера spring, сервера tomcat, службы dubbo, обработчика, конечного автомата и т. д.

В конце концов, многие люди скажут, что после всего этого вам не нужно использовать kill -9?

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

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

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