systemd 타이머에 의해 시작되는 모니터링 bash 스크립트를 실행하는 systemd 서비스가 있습니다. 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
실제 명령에 s를 할당하는 셸을 실행합니다.
sh -c 'echo "$$" > /sys/fs/cgroup/systemd/tasks; exec /the/forking/program'
/the/forking/program
이미 새 cgroup에 있는 쉘을 교체합니다. 포크되면 포크된 인스턴스는 새 cgroup에서 자체적으로 발견됩니다. 기본 스크립트가 종료되면 systemd는 서비스와 관련된 cgroup의 프로세스를 종료하지만 문제의 프로그램은 그 프로세스에 포함되지 않습니다.
어쩌면 단위 파일 등을 사용하여 문제를 해결하는 더 적절한 방법이 있을 수 있습니다. 하지만 나는 그것을 모른다.