시스템 타이머에 의해 시작된 모니터링 bash 스크립트를 실행하는 시스템 서비스가 있습니다. Type=oneshot
가장 잘 어울릴 것 같은 것을 사용했어요 . 그러나 때로는 스크립트가 포크되는 다른 프로그램을 호출해야 하는 경우도 있습니다. 완료되면 스크립트가 완료되고 종료되지만 스크립트가 종료되면 systemd는 나머지 하위 프로세스를 모두 종료합니다.
이를 방지하기 위해 사용할 수 있지만 KillMode=process
스크립트의 다른 경로에서는 종료 후에도 다른 프로세스(포크되지 않음)가 계속 실행될 위험이 있습니다.
이 문제를 처리하는 가장 좋은 방법은 무엇입니까?
그런데 포크된 프로그램은 dhcpcd이지만 질문은 일반적으로 적용된다고 생각합니다. dhcpcd는 처음에 ifplugd에 의해 시작됩니다. 이는 시스템이 dhcpcd가 더 이상 실행되지 않는 상태로 끝나는 경우를 대비한 안전 스크립트입니다.
답변1
프로세스는 다음과 같이 서비스와 연결된 제어 그룹(cgroup)에 속하기 때문에 종료됩니다(시스템 서비스의 경우).
/sys/fs/cgroup/systemd/system.slice/your-service.service
프로세스를 cgroup 밖으로 이동하려면,다른 cgroup에 할당. "부모 cgroup"이 올바른 것 같습니다. 시스템 서비스의 경우 다음과 같습니다.
echo <PID> > /sys/fs/cgroup/systemd/system.slice/tasks
# or even to the general systemd cgroup
echo <PID> > /sys/fs/cgroup/systemd/tasks
처음부터 이 cgroup에서 일부 명령을 실행하려면 cgroup에 자신을 할당하는 쉘을 실행한 후 exec
실제 명령을 실행하십시오.
sh -c 'echo "$$" > /sys/fs/cgroup/systemd/tasks; exec /the/forking/program'
/the/forking/program
새 cgroup에 이미 있는 쉘은 교체됩니다. 포크되면 포크된 인스턴스는 새 cgroup에서 자체적으로 발견됩니다. 기본 스크립트가 종료되면 systemd는 서비스와 연결된 cgroup의 프로세스를 종료하지만 문제의 프로그램은 해당 서비스에 포함되지 않습니다.
어쩌면 단위 파일 등을 사용하여 문제를 해결하는 더 적합한 방법이 있을 수 있습니다. 하지만 모르겠어요.