프로세스 관리

jobs / fg bg / kill / control(Ctrl-C,Z) / time

현대적인 운영체제들은 이른바 다중작업(multi-tasking)을 하도록 만들어졌으며 GNU/Linux 시스템도 다른 어떤 시스템에 못지 않은 다중작업 처리 능력을 과시하고 있다.[16] 현재 시스템에서 돌아가고 있는 수많은 작업들의 적나라한 모습을 보려면 이미 다룬 ps aux 또는 top 명령을 이용하자. [17]

root를 비롯한 특별한 이용자들과, 현재 시스템에 접속된 일반 이용자들이 각자 작업에 필요한 시스템의 자원(CPU 시간과 메모리 등)을 나눠서 이용하는 셈이며, 일반 이용자로서는 자신의 권한으로 실행시킨 작업들에 대해 -- 마치 자신의 파일을 관리하듯이 -- 죽이고 살리는 등의 "제어"를 할 수 있다. 여기서는 간단한 작업(프로세스, processes) 관리를 소개하겠다. 사용자 자신의 모든 프로세스를 살펴 보기 위해 ps ux 명령을 이용하자.

$ ps ux
USER PID  %CPU %MEM   VSZ  RSS TTY   STAT START TIME COMMAND
jedi 7759  0.0  0.3  3008 1464 pts/0 S    16:18 0:00 -bash
jedi 8812  0.0  0.2  2920  980 pts/0 S    22:50 0:00 /bin/sh /usr/X11R6/bin/Hanterm
jedi 8813  0.1  0.6  5644 2532 pts/0 S    22:50 0:00 hanterm -bg azure3 -fg gray32
jedi 8815  0.0  0.3  3328 1476 pts/1 S    22:50 0:00 -bash
jedi 8861  1.5  0.6  5924 2668 pts/0 S    22:51 0:00 vim force.xml
jedi 8862  5.0  0.1  2628  740 pts/1 R    22:51 0:00 ps ux

ps ux 명령의 실행 결과에서 가장 중요한 열(columns)은 바로 PID(프로세스식별자, Process ID)다. 다른 열이 무엇을 의미하는지는 각자가 쉽게 눈치챌 수 있을 것이고, 이 문서의 목적을 고려해 볼 때 VSZ, RSS에 대한 설명은 하지 않겠다. 시스템에는 수많은 프로세스가 동작 또는 잠자며 대기하고 있는데 그들 중엔 같은 USER가 내린 명령, 또는 같은 COMMAND 명칭이 있을 수 있다. 하지만 "PID는 모든 프로세스가 자기 고유의 값만 가지고" 있다. 따라서 프로세스 관리에 관련된 명령어들은 대개 PID를 옵션으로 받아서 처리하는 기능을 가지게 된다. 쉬운 비교를 추가한다면; 시스템에 같은 PID가 있을 수 없다는 말은 같은 이용자명이, 혹은 같은 절대경로의 파일이 둘 이상 있을 수 없다는 조건과 마찬가지로, '틀림없이' 그런 것이다!

한편 어떤 GNU/Linux 시스템에 여러 사용자가 제각각 여려 개의 터미널로 동시에 접속해 있을 때, 이들이 현재 이용하고 있는 터미널 역시 서로 구분된다. 위의 ps ux 명령 실행 화면에서 TTY라는 열이 바로 그것이다. 위의 예를 보기만 해도 알 수 있는 것은 - jedi라는 이용자가 두 개의 터미널을 이용 중이라는 사실, 그리고 먼저 띄운 터미널(pts/0)에서는 force.xml이라는 파일에 대해 vim 명령을 내린 상태고, 두 번째 터미널(pts/1)에서는 지금 이 명령, ps ux를 실행했다는 사실이다. 포스가 강한 사람이라면 "쉘 계정 로그인과 동시에 반드시 어떤 쉘이 동작한다"는 이야기를 기억할 것이다. COMMAND 열에서 -bash가 의미하는 것이 바로 로그인 쉘이다. 이렇게 하나씩 내용을 살펴보니 ps ux 명령이 사실 별 대단한 것도 아닌 것 같다 :-)

프로세스 관리를 위한 명령어들
$ jobs - 현재 터미널의 작업 확인

이 명령은 현재 터미널의 전면/후면 작업(fore/background processes)을 보기 위한 것이다. 전면 작업은 물론 사용자와 대화하고 그 명령(아무 것도 하지 않고 있으면 프롬프트를 보이고 있는 쉘 자체)이 되고, 후면 작업은 & 기호에 대한 설명에서 소개한 바로 그런 것이다.

$ $ sleep 200 &             # 200초동안 자는 명령을 후면에서 실행
[1] 28505               # 작업번호 [1], PID 28505 
$ sleep 80 &
[2] 28506               # 작업번호 [2], PID 28506
$ jobs
[1]-  Running                 sleep 200 &
[2]+  Running                 sleep 80 &

어떤 작업을 후면에서 실행시키면 이와 같이 그 작업의 번호와 PID를 출력함을 참고하자.

$ fg [%number] - 후면 작업을 전면으로

fg 명령은 작업번호(PID가 아님!)를 받아서 전면으로 가지고 온다. 작업번호를 명시할 때 %n과 같은 형식을 이용함을 기억하자. 즉 위의 보기에서 잠자는 작업을 전면으로 가지고 오려면(즉, 명령과 함께 자신도 잠시 자고 싶다면) fg %1 명령을 하면 된다.

실제로 이런 작업 관리는 따로 있는 명령이 아니라 Bash가 내부적으로 수행하는 주요 기능에 속한다. 그래서 달라지는 것이 무엇일까? fg %1 명령은 그냥 %1이라고만 해도 똑같이 수행된다. 쉘에서 작업 번호를 명시하기 위해 %를 이용하므로 다른 경우와 혼동될 일이 없는 것이다.

$ kill [signal] [pid] - 프로세스 종료

이름부터가 살벌한 이 명령은 수많은 프로세스들 중에서 특정 PID를 골라서 살해(?)한다. signal 옵션은 여러가지가 있는데 특별히 명시하지 않으면 TERM(terminates)이 기본으로 쓰이고, 기억해둘 것은 최강의 필살기인 KILL이다.

$ sleep 100 &
[1]12345
$ kill 12345 ; sleep 200 &          # 종료시키며 또 재우는 작업
[2] 12346
[1]- Terminated         sleep 100       # 종료됨
$ kill -KILL 12346
[2]+ Killed             sleep 200       # 죽었음

kill 명령의 확실한 용도를 알아 보려면 자신의 로그인 쉘을 죽여보라. 만약 후면에서 진행 중인 작업이 있다면 그냥 kill 명령을 내렸을 때 쉘이 그 사실을 알려줄 것이다. 하지만 kill -KILL 명령은? 원한다면 실제로 해보길!

$ time [command] - 작업에 소요된 시간 측정

간단하면서 때때로 유용한 명령이다. 시스템의 성능을 비교하기 위해, 또는 수치계산을 비롯한 작업의 전체 소요 시간을 알아보기 위해 활용할 수 있다.

$ time du /usr/
(du /usr/ 명령이 실행 - 한참동안 /usr/ 디렉토리의 내용을 쏟아냄)

real    0m12.265s       # 실제 시간 12초 소요
user    0m0.450s        # 이용자 시간 0.45초
sys     0m0.900s        # 시스템 시간 0.9초

다중 작업 환경과 관련해 마지막으로 중요한 개념 하나를 더 소개하겠다. 위의 결과에서 real이란 문자 그대로 '실제 세계에서의' [18] 시간을 말한다. user, 그리고 sys는 각각 사용자와 커널(시스템의 핵심) 모드에서 소요된, 'CPU가 실제로 이용한' 시간을 말한다. 위의 결과를 쉽게 풀이 - 만약 du /usr/ 명령을 수행하기 위해 시스템의 CPU가 다른 모든 일을 접고서 오직 이 일에 매달렸다면, 'user + sys'에 해당하는 시간만에 완료할 수 있다는 말이다. 이것이 실제 시간과 일치하지 않는 것은 시스템이 그동안 다른 많은 일도 했다는, 즉 "다중 작업"을 하고 있다는 의미다.

작업전환 및 종료를 위한 쉘 단축키

현재 전면에서 하고 있는 작업을 중단, 후면으로 보내고 다른 작업을 하려면 Ctrl-Z를 누른다. 작업이 중단되었다는 메시지와 함께 쉘 프롬프트가 뜰 것이다. 다시 그 작업을 계속하려면 마찬가지로 fg %n 명령을 한다.

$ mail yoda@jedi.net
Subject: Ctrl-Z                          # 문득 다른 작업을 하고 싶다!
[1]+  Stopped          mail yoda@jedi.net
$ (...다른 작업)
$ jobs
[1]+  Stopped          mail yoda@jedi.net
$ fg %1
mail yoda@jedi.net
Subject: Yoda, I am your father.. :-p   # 메일을 마저 작성함.

Ctrl-C는 현재 터미널의 전면(foreground)에서 동작 중인 어플리케이션에 "죽으라"는 신호를 보낸다. 예를들어 다음과 같이 해 보자.

$ sleep 60            # 60초 동안 잠자는 작업(?) 시작
Ctrl-C                   # 작업 종료 신호!
$                       # 즉시 작업이 종료되어 프롬프트로 돌아옴.


[16] 다중작업에는 시분할 방식과 선점형 방식 등이 있다. 시분할 방식을 이용하는 시스템은 MS-Windows, 그리고 선점형 방식을 이용하는 시스템은 바로 GNU/Linux가 대표적이다.

[17] 또다른 의미에서 '적나라한' 모습을 보기 위해 pstree 명령을 쓸 수도 있다. 이것은 init라는, 시스템의 최상위 프로세스 및 이것에서 파생된 프로세스들의 나무 구조(트리, tree)를 보여준다.

[18] 물론 많은 사람들은 낡은 관습과 강요에 찌든 채 매트릭스(the Matrix)에서 살고 있지만 ;-)