Job Control
때때로 실행되는 동안에 수행 중인 job을 중단해야하는 경우가 있다.
명령어를 실행했는데 너무 오래 걸리는 경우엔 Ctrl-C가 만사형통이긴 하다만,
이게 내부적으론 어떻게 실행되는 거고 왜 가끔은 실패하는거지?
killing a process
shell은 프로세스간의 정보를 전달하기 위해 Signal이라는 unix 메커니즘을 사용한다.
프로세스가 시그널을 받으면 프로세스의 진행을 잠시 멈추고 시그널을 처리한다.
이 처리 결과에 따라 프로세스의 실행 흐름이 달라질 수 있다.
따라서 시그널은 소프트웨어 인터럽트이다.
import signal, time
def handler(signum, time):
print("\nI got a SIGINT, but I am not stopping")
signal.signal(signal.SIGINT, handler)
i = 0
while True:
time.sleep(.1)
print("\r{}".format(i))
i += 1
Python
복사
Ctrl-C는 프로세스에 SIGINT를 전달한다.
위 예제 코드는 SIGINT를 무시하는 프로그램이며 실행 후 ctrl-c로 중단해보려 한 결과는 아래에!
보다시피 ctrl-c로 중단되지 않는다. 중단하려면 ctrl-\(SIGQUIT)
SIGINT와 SIGQUIT 둘 다 터미널 관련된 요청을 처리하긴 하지만, 프로세스를 종료하기 위한 더 일반적인 방법은 SIGTERM 신호이다.
SIGTERM 신호를 보내기 위해선 kill -TERM <PID>명령어를 사용한다.
pausing and backgrounding processes
시그널은 프로세스를 종료하는 것 외에도 쓰임새가 있다. SIGSTOP은 프로세스를 중단한다.
ctrl-z를 타이핑함으로써 터미널에 SIGTSTP(terminal stop)신호를 보낼 수 있다.
•
fg, bg 명령어를 통해 foregroup나 backgroud에 있는 중단된 작업을 수행할 수 있다.
•
jobs 명령어는 현재 터미널 세션에서 미완인 작업들을 보여준다.
•
% 심볼 뒤에 job number를 붙이면 해당 프로세스를 나타낼 수 있다.
•
$! 심볼을 통해 최신의 백그라운 작업을 나타낼 수 있다.
•
명령어 뒤에 &를 붙이면 작업을 백그라운드로 수행할 수 있다. → 하지만 여전히 쉘의 STDOUT을 사용하고 있음
이런 백그라운드 포르세스들 역시 터미널의 자식 프로세스이기 때문에 터미널을 닫으면 종료된다.
이를 막기 위해선
•
nohup 명령어를 사용하거나
•
이미 프로세스가 이미 시작된 경우 disown 명령어
•
혹은 terminal multiplexer를 사용!
$ sleep 1000
^Z
[1] + 18653 suspended sleep 1000
$ nohup sleep 2000 &
[2] 18745
appending output to nohup.out
$ jobs
[1] + suspended sleep 1000
[2] - running nohup sleep 2000
$ bg %1
[1] - 18653 continued sleep 1000
$ jobs
[1] - running sleep 1000
[2] + running nohup sleep 2000
$ kill -STOP %1
[1] + 18653 suspended (signal) sleep 1000
$ jobs
[1] + suspended (signal) sleep 1000
[2] - running nohup sleep 2000
$ kill -SIGHUP %1
[1] + 18653 hangup sleep 1000
$ jobs
[2] + running nohup sleep 2000
$ kill -SIGHUP %2
$ jobs
[2] + running nohup sleep 2000
$ kill %2
[2] + 18745 terminated nohup sleep 2000
$ jobs
Shell
복사