programing

Java에서 SIGKILL 신호를 정상적으로 처리하는 방법

copyandpastes 2022. 9. 25. 21:48
반응형

Java에서 SIGKILL 신호를 정상적으로 처리하는 방법

프로그램이 킬 시그널을 수신했을 때 청소는 어떻게 처리합니까?

를 들어, 앱이 ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★finish명령어를 입력합니다.그것을 보내는 가장 좋은 방법은 무엇입니까?finish되었을 때 를 할 수 있습니다.kill -9

편집 1: kill -9를 캡처할 수 없습니다.정정해 주셔서 감사합니다.

edit 2: 이 경우는 ctrl+c와 같은 kill을 호출하는 경우라고 생각합니다.

어떤 프로그램에서도, 어떤 언어로든, SIGKILL을 처리하는 것은 불가능합니다.그 때문에, 프로그램이 버그가 있는 경우나 악의가 있는 경우라도, 항상 프로그램을 종료할 수 있습니다.그러나 SIGKILL만이 프로그램을 종료하는 방법은 아닙니다.다른 하나는 SIGTERM을 사용하는 거야 프로그램이 신호를 처리할 수 있어 프로그램은 제어되지만 빠른 셧다운을 수행하여 신호를 처리해야 합니다.컴퓨터가 셧다운되면 셧다운 프로세스의 마지막 단계는 나머지 모든 프로세스에 SIGTERM을 전송하고 몇 초간의 유예기간을 준 후 SIGKILL을 전송합니다.

이 문제를 해결하는 방법은kill -9셧다운 훅을 등록하는 것입니다.(SIGTERM)을 사용할 수 있는 경우kill -15셧다운 훅이 동작합니다.(SIGINT)kill -2 그러면 프로그램이 정상적으로 종료되고 셧다운 후크가 실행됩니다.

새 가상 시스템 종료 후크를 등록합니다.

Java 가상 시스템은 다음 두 가지 이벤트에 대해 종료됩니다.

  • 마지막 비데몬 스레드가 종료되거나 종료(System.exit) 메서드가 호출되면 프로그램은 정상적으로 종료됩니다.
  • ^C 입력과 같은 사용자 인터럽트 또는 사용자 로그오프 또는 시스템 종료와 같은 시스템 전체 이벤트에 대한 응답으로 가상 시스템이 종료됩니다.

과 OSX 10.6.3에서 다음 테스트 .에서 다음 테스트 프로그램을 사용해 보았습니다.kill -9예상대로 셧다운 훅이 실행되지 않았습니다.에서kill -15매번 셧다운 훅을 실행합니다.

public class TestShutdownHook
{
    public static void main(String[] args) throws InterruptedException
    {
        Runtime.getRuntime().addShutdownHook(new Thread()
        {
            @Override
            public void run()
            {
                System.out.println("Shutdown hook ran!");
            }
        });

        while (true)
        {
            Thread.sleep(1000);
        }
    }
}

수 있는 방법은 .kill -9떤떤프어

드문 경우지만 가상 시스템이 중단될 수 있습니다. 즉, 완전히 종료되지 않고 실행을 중지할 수 있습니다.이 문제는 Unix의 SIGKILL 신호 또는 Microsoft 윈도우즈의 TerminateProcess 호출과 같이 가상 시스템이 외부에서 종료될 때 발생합니다.

를 처리하는 kill -9다른 워처 프로그램이 메인 프로그램을 감시하도록 하거나 래퍼 스크립트를 사용하는 것입니다.은, 「URL」, 「URL」을 한셸해 실시할 수 .ps명령어를 사용하여 목록에서 프로그램을 찾고 프로그램이 사라졌을 때 그에 따라 행동합니다.

#!/usr/bin/env bash

java TestShutdownHook
wait
# notify your other app that you quit
echo "TestShutdownHook quit"

JVM은 적어도 신호 및 의 경우 어플리케이션에 의해 생성된 모든 실행 스레드를 정상적으로 중단()thread.interrupt()할 것으로 예상됩니다.

이렇게 하면 신호가 전송되어 표준적인 방법으로 그레이스 풀스레드 취소 및 자원 최종화가 가능하게 됩니다.

그러나 이는 해당되지 않습니다(적어도 JVM 구현의 경우:Java(TM) SE Runtime Environment (build 1.8.0_25-b17), Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode)

다른 유저 코멘트에 의하면, 셧다운 훅의 사용은 필수인 것 같습니다.

그럼 어떻게 대처해야 하죠?

우선, 모든 프로그램에는 관심이 없습니다.사용자의 취소나 예기치 않은 종료에 대해 추적하고 싶은 프로그램에만 관심이 있습니다.예를 들어, Java 프로그램이 다른 사람이 관리하는 프로세스라고 가정해 보십시오.하는 것이 .SIGTERM(시작 시 작업을 자동으로 다시 시작하기 위해) 또는 셧다운이 발생했습니다.

기본적으로, 저는 항상 장기 실행 스레드를 주기적으로 인터럽트 상태를 인식하도록 하고, 인터럽트 상태를 슬로우합니다.InterruptedException할 수 있습니다(조작과 수도 있습니다).이를 통해 개발자가 제어하는 방식으로 실행을 완료할 수 있습니다(또한 표준 차단 작업과 동일한 결과를 생성합니다).스택의 InterruptedException캡처되어 적절한 청소가 수행됩니다.이러한 스레드는 인터럽트 요청에 응답하는 방법을 알 수 있도록 코드화되어 있습니다.높은 응집력 설계.

이 경우 셧다운 훅을 추가합니다.이 셧다운 훅은 JVM이 기본적으로 수행해야 할 작업입니다.즉, 어플리케이션이 아직 실행 중인 데몬 이외의 스레드를 모두 중단합니다.

Runtime.getRuntime().addShutdownHook(new Thread() {
    @Override
    public void run() {
        System.out.println("Interrupting threads");
        Set<Thread> runningThreads = Thread.getAllStackTraces().keySet();
        for (Thread th : runningThreads) {
            if (th != Thread.currentThread() 
                && !th.isDaemon() 
                && th.getClass().getName().startsWith("org.brutusin")) {
                System.out.println("Interrupting '" + th.getClass() + "' termination");
                th.interrupt();
            }
        }
        for (Thread th : runningThreads) {
            try {
                if (th != Thread.currentThread() 
                && !th.isDaemon() 
                && th.isInterrupted()) {
                    System.out.println("Waiting '" + th.getName() + "' termination");
                    th.join();
                }
            } catch (InterruptedException ex) {
                System.out.println("Shutdown interrupted");
            }
        }
        System.out.println("Shutdown finished");
    }
});

https://github.com/idelvall/kill-test에서 테스트 신청을 완료하십시오.

특정 JVM에서 자체 신호를 처리하는 방법이 있습니다. 예를 들어 HotSpot JVM에 대한문서를 참조하십시오.

Sun sun.misc.Signal.handle(Signal, SignalHandler)메서드 호출: 신호 핸들러를 등록할 수도 있지만, 아마도 다음과 같은 신호에는 등록할 수 없습니다.INT또는TERMJVM에 의해 사용되기 때문입니다.

신호를 처리할 수 있으려면 JVM을 벗어나 운영 체제 영역으로 뛰어들어야 합니다.

통상적으로 비정상적인 종료를 검출하기 위해 하는 것은 Perl 스크립트 내에서 JVM을 기동하는 것이지만 스크립트는 Perl 스크립트를 사용하여 JVM을 대기시킵니다.waitpid시스템 콜을 실행합니다.

그런 다음 JVM이 종료될 때마다 종료된 이유와 필요한 조치를 취할 수 있습니다.

하시면 됩니다.Runtime.getRuntime().addShutdownHook(...)단, 어떤 경우에도 호출된다는 보장은 할 수 없습니다.

레퍼런스 https://aws.amazon.com/blogs/containers/graceful-shutdowns-with-ecs/

import sun.misc.Signal;
import sun.misc.SignalHandler;
 
public class ExampleSignalHandler {
    public static void main(String... args) throws InterruptedException {
        final long start = System.nanoTime();
        Signal.handle(new Signal("TERM"), new SignalHandler() {
            public void handle(Signal sig) {
                System.out.format("\nProgram execution took %f seconds\n", (System.nanoTime() - start) / 1e9f);
                System.exit(0);
            }
        });
        int counter = 0;
        while(true) {
            System.out.println(counter++);
            Thread.sleep(500);
        }
    }
}

kill-9에 반응하는 한 가지 방법이 있습니다. 즉, 프로세스를 감시하고 필요에 따라 프로세스를 정리하는 별도의 프로세스를 갖는 것입니다.이것은 IPC를 수반해, 많은 작업이 필요하게 되어, 양쪽의 프로세스를 동시에 정지하는 것으로 덮어쓸 수 있습니다.대부분의 경우 수고를 들일 가치가 없다고 생각합니다.

-9로 프로세스를 종료하는 사람은 이론적으로 자신이 무엇을 하고 있는지 알고 있어야 하며, 일관성이 없는 상태가 될 수 있습니다.

언급URL : https://stackoverflow.com/questions/2541597/how-to-gracefully-handle-the-sigkill-signal-in-java

반응형