프로세스가 고아 프로세스를 남기는지 테스트합니다.

프로세스가 고아 프로세스를 남기는지 테스트합니다.

나는 그들을 기다릴 필요가 없습니다. 단지 예 또는 아니오만 있으면 됩니다.

나는 분할 종료를 유발할 것으로 알고 있는 프로그램을 따르고 있습니다(아이들도 분할 종료를 겪을 수 있음). 올바르게 실행되면 모든 하위 항목을 처리하고 완료되면 종료해야 합니다. 이것이 사실인지 확인하기 위해 테스트를 작성해야 합니다. 분리된 프로세스는 init 프로세스에 할당되므로 더 이상 pstree에서 볼 수 없습니다.

SIGKILL을 보낼 수 있도록 PID 목록을 얻을 수 있다면 보너스 포인트가 됩니다. 이상적으로는 POSIX-y 항목이라면 *BSD에서 작동할 것입니다.

답변1

이를 찾는 한 가지 방법은 를 사용하여 ps -ef상위 ID가 "1"인 행을 찾는 것입니다. 예를 들어 다음과 같습니다.

#!/bin/sh
orphans="$(ps -ef | awk '$3 == 1{ print $2; }')"
echo "Processes which might be orphans: $orphans"

하지만,많은프로세스의 상위 프로세스는 "1"입니다. 관심 있는 항목을 결정하는 가장 좋은 방법은 프로그램에서 생성한 하위 프로세스를 기억하는 것입니다.

만약 당신이 알고 있다면로그인 이름(그리고/또는사용자 ID) 이러한 프로세스를 생성하는 경우 몇 가지 가능성이 제거됩니다. 첫 번째 열이 ps표시될 수 있습니다(시스템 유형에 따라 다름).로그인 이름또는 해당사용자 ID.POSIX여기에는 몇 가지 도움이 있지만 다양한 시스템을 쉽게 찾을 수 있으며 문서에는 다음 사항이 반영되어 있습니다.

  • 예를 들어 FreeBSD 10은 표시되지 않습니다.로그인 이름옵션 -f. just를 사용하면 ps -ef상위 프로세스의 프로세스 ID를 표시하지 않고 첫 번째 열에 프로세스 ID를 표시합니다. -l(대신) 표시하려면 옵션이 필요합니다 .사용자 ID.
  • OSX는 두 경우 모두 사용자 ID( ps -ef또는 )를 제공합니다 ps -efl.
  • -l옵션이 있으면 Solaris 10은 첫 번째 열과 두 번째 열에 프로세스 플래그를 표시합니다. 이것은 POSIX에서 언급되었지만콘텐츠플래그 수는 지정되지 않습니다(내용이 다르기 때문에).유닉스플랫폼).
  • Linux는 POSIX에 따라 로그인 이름과 프로세스 플래그를 제공합니다.

보시다시피 사용 가능한 시스템의 일부 하위 집합에 대해 ps -efl처음 세 열은 "동일한" 결과를 제공합니다. 보다 일반적인 콘텐츠의 경우 헤더(첫 번째 행)를 보고 프로세스 소유자에 해당하는 정보가 포함된 열을 확인해야 합니다(로그인 이름또는사용자 ID) 및 프로세스 ID 및그것은상위 프로세스의 프로세스 ID입니다.

특정 시스템에 대해(사용 가능한 옵션을 알고 ps일치하는지 확인)로그인 이름또는사용자 IDawk), 일치하는 데 사용할 수 있습니다저것필드에도 마찬가지입니다.

#!/bin/sh
orphans="$(ps -ef | awk -v user=$LOGNAME '($1 == user && $3 == 1){ print $2; }')"
echo "Processes which might be orphans: $orphans"

$LOGNAME여기서는 POSIX의 이 용어 사용을 설명하기 위해 를 사용합니다.로그인 이름, 이는 오해의 소지가 있습니다(원칙적으로 프로세스는 을 통해 이루어질 수 있지만 sudoPOSIX에서 용어를 사용하는 것은 "로그인"을 통해 이루어진다는 의미이기 때문입니다).

추가 자료:

답변2

프로세스가 종료되면 해당 하위 프로세스의 PPID는 1(init에 의해 채택)로 설정되지만 PGID(프로세스 그룹 식별자)와 SID(세션 식별자)는 변경되지 않습니다.

이 프로세스의 하위 항목은 데몬이 될 의도가 없는 한 프로세스 그룹을 변경할 수 없습니다. 그렇지 않다고 가정하면 자체 프로세스 그룹에서 테스트하려는 프로세스를 시작하십시오. 분기 후 setpgid(getpid(), getpid())테스트 중인 프로그램 실행을 호출하기 전에 테스트 프레임워크에서 호출됩니다. PGID를 사용하여 실행 중인 프로세스가 있는지 테스트하기 위해 ( 음수 매개 변수 및 신호 값 0을 사용하여 ) execve호출됩니다 . 그들을 죽이려면 신호 인수로 전달하십시오 .kill(-test_program_pid, 0)killpidtest_program_pidSIGKILL

test_program_pid = fork();
if (test_program_pid) {
    waitpid(test_program_pid, &status, 0);
    if (kill(-test_program_pid, 0)) {
        record_failue("some child processes were not terminated properly");
    }
    kill(-test_program_pid, SIGKILL);
} else {
    setpgid(getpid(), getpid());
    execve("/program/to/test", …);
}

또 다른 접근 방식은 임시 파일을 만들어 다른 곳에서 여는 대신 테스트 중인 프로그램에서 여는 것입니다. 프로그램이 을 호출하는 경우 열린 파일 설명자에 플래그 (또는 호출 ) execve가 없는지 확인하세요 . 이 방법은 프로그램이 명시적으로 사용되지 않은 파일 설명자를 닫지 않는다고 가정합니다. 그런 다음 실행하여 파일이 열려 있는 프로세스를 나열하고 종료할 수 있습니다. 이 접근 방식의 변형은 파일 설명자를 사용하지 않는 프로그램을 닫는 데에도 사용할 수 있지만 프로그램이 현재 디렉터리를 변경하지 않는다고 가정합니다. 즉, 임시 디렉터리를 만들고 해당 디렉터리로 변경하여 프로그램을 실행합니다.O_CLOEXECfcntl(fd, FD_CLOEXEC, 0)fuser /temp/filefuser -k /temp/file

관련 정보