“su -c <command> &”가 왜 끊지 않고 백그라운드에서 명령이 실행되도록 허용합니까?


11

백그라운드 프로세스가 간헐적으로 죽어가는 문제를 겪고있는 동료를 돕고있었습니다.

서버에 로그인하고 다음을 실행하여 백그라운드 프로세스를 시작하고 있음을 알았습니다.

su - <user> -c '<command>' &

"아하", 나는 외쳤다. "&"로 명령을 시작하면 제어 터미널을 종료 할 때 정지됩니다.이를 달성하려면 nohup과 같은 것을 사용해야합니다. 실제로이 프로세스는 tut tut 데몬으로 실행하는 것을 지원해야합니다. "

우리는 위의 명령을 테스트하여 요점을 보여주었습니다 ... 작동하는 것처럼 보입니다 : 명령으로 시작한 프로세스 가 위 명령을 실행 한 터미널을 종료했을 때 종료되지 않았습니다.

command 는 출력이 파일로 이동하는 사용자 정의 Python 스크립트입니다. 내가 알 수있는 한, 스크립트에는 기능과 같은 지능적인 "데모 니즈"가 없습니다. Wikipedia : Daemon (computing) : Creation 페이지에 나열된 데몬으로 실행하는 데 필요한 작업은 수행하지 않습니다 .

명령을 다음과 같이 실행하면 예상대로 작동합니다.

<command> &
exit

위의 경우 터미널을 종료하면 명령으로 시작된 백그라운드 프로세스가 종료됩니다.

내 질문은 이것입니다 :

  1. 터미널이 종료 될 때 프로세스가 종료되지 않도록하는 "su--c &"를 추가하면 어떻게됩니까? 제어 터미널, 표준 입력 및 출력 등에 대해 자세히 이해하고 싶습니다.

  2. 이 명령을 백그라운드 프로세스로 실행하려는 목표를 달성하기위한 합리적인 방법입니까? 왜 그렇지 않습니까?

회사 내에서 모범 사례를 전파하고 싶지만 권장 사항을 입증하고 백업 할 수 있어야합니다.

또한 정확히 무슨 일이 일어나고 있는지 이해하고 싶습니다.

답변:


12

터미널 종료로 인해 프로세스가 종료 될 수있는 몇 가지 방법이 있습니다.

  1. 첫 번째 방법은 커널의 터미널 드라이버 가 터미널을 제어 터미널 인 제어 프로세스SIGHUP 신호보내는 것 입니다. 대부분의 경우 제어 프로세스는 터미널에서 처음 시작되는 쉘이고 제어 터미널은 stdin, stdout 및 stderr이 연결된 것입니다. 프로세스가 제어 터미널에서 호출되면 연결이 끊어집니다 .setsid

  2. 두 번째 방법은 쉘이 SIGHUP을 수신 할 때 해당 신호를 서브 프로세스로,보다 정확하게는 백그라운드 작업으로 재전송하는 것입니다. 일부 쉘 (ksh, bash, zsh)에는 disown특정 작업에 SIGHUP을 보내지 않도록 쉘에 내장되어 있습니다.

  3. 터미널이 사라지고 프로그램이이를 읽으려고하면 파일 끝 조건 (또는 백그라운드 작업의 경우 EIO)이 통지됩니다. 터미널이 사라지고 프로그램이 쓰기를 시도하면 쓰기는 EIO 오류와 함께 반환됩니다. 이로 인해 프로그램이 종료 될 수 있습니다.

따라서 su여기서 변경되는 것은 (2) 일반적으로 초기 셸이 백그라운드 작업을 종료 시키지만 백그라운드 프로세스가 다른 사용자로 실행되므로 신호를 전달할 수 없으며 백그라운드 프로세스가 계속 작동한다는 것입니다.


루트 사용자가하는 것을 보았습니다 chroot --userspec root:root / sh -c "exec some_forever_process" &. 작업이 명시 적으로 nohup이전 또는 disown이후에 동일한 사용자로 실행 중 입니다. 따라서이 경우 신호가 종료시 어떻게 전달되지 않습니까?
Toddius Zho

@ToddiusZho Presumable some_forever_process은 영구적으로 실행되도록 설계 되었으므로 (데몬) 자신의 프로세스 그룹에서 실행하여 터미널 종료에서 SIGHUP을 수신하지 않도록 보호합니다.
Gilles 'SO- 악마 그만해'

bash / tail은 SIGHUP으로부터 보호하지 않지만 여전히 작동합니다.```local $ ssh root @ REMOTE_HOST remote # chroot --userspec root : root / sh -c "exec bash -c 'tail -f / dev / null ' "& [1] 6376 원격 # ps -p $! --no-heading -o pid, uid, command -ww 6376 0 tail -f / dev / null remote # exit local $ ssh root @ REMOTE_HOST remote # ps -p 6376 --no-heading -o pid, uid, command -ww 6376 0 꼬리 -f을 / dev / null```
Toddius Zho
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.