Process 관리
process는 흔히 실행중인 프로그램을 뜻한다. file과는 다른 의미이다. file은 디스크 상에 존재하며 수동적이다.
process는 메모리에 있거나 cpu가 실행하는 상태를 의미한다
예를 들면
디스크의 특정 파티션의 특정 디렉토리에 있는 ls 명령을 실행하면 ls 명령이 메모리에 올라가고 cpu 자원을 할당 받아
실행된다. 이것을 process 라고 하며 실행이 끝나면 메모리에서 완전히 제거된다.
프로세스 관리는 중요하다. 프로세스를 잘못관리하면 시스템 성능이 떨어질 수 있으며 보안상 시스템이 취약해질 수도 있다.
프로세스 상태보기
ps
PS(1) Linux User's Manual PS(1)
NAME ps - report process statusSYNOPSIS
ps [options]
[lee@river ex]$ ps
PID TTY TIME CMD
3397 pts/1 00:00:00 bash
3578 pts/1 00:00:00 ps
[lee@river ex]$
두개의 프로세스가 실행중이다.
ps 명령을 아무런 옵션 없이 사용하면 출력되는 내용은 현재 터미널에서(여기서는 pts/1) 현재 사용자 권한
(여기서는 lee)으로 실행(메모리에 있거나 cpu 자원을 할당받은)중인 프로세스만 출력된다. 아무런 옵션 없이
사용하면 가장 단순한 형태로 출력해준다.
위의 ps 명령의 각 항목의 의미는 아래와 같다.
PID : 커널이 식별하는 프로세스 식별자
프로세스가 생성되는 순서대로 번호가 할당되며 1번은 init 이다.
TTY : 프로세스가 어떤 터미널에서 실행되었는가 하는 정보
TIME : 프로세스가 cpu를 점유한 누적 시간
CMD : 프로세스 이름
모든 프로세스 목록을 다 보고 싶다면 -e 옵션을 사용하면 된다.
[lee@river ex]$ ps -e
PID TTY STAT TIME COMMAND 1 ? S 0:04 init [3]
2 ? SW 0:00 [keventd]
3 ? SW 0:00 [kapmd]
4 ? SWN 0:00 [ksoftirqd_CPU0]
5 ? SW 0:00 [kswapd]
6 ? SW 0:00 [kscand/DMA]
7 ? SW 0:00 [kscand/Normal]
8 ? SW 0:00 [kscand/HighMem]
10 ? SW 0:00 [kupdated]
11 ? SW 0:00 [mdrecoveryd]
15 ? SW 0:00 [kjournald]
73 ? SW 0:00 [khubd]
285 ? SW 0:00 [kjournald]
286 ? SW 0:00 [kjournald]
위에 출력결과중 TTY는 프로세스가 실행된 터미널을 나타내는데 ? 로 표시된 것은 터미널과 관계없는
프로세스를 뜻한다. 예를 들면 부팅할 때 자동으로 실행된 프로세스를 의미한다.
그리고 STAT 는 프로세스 상태를 나타내는 부분으로 여기에서 몇 가지가 있다.
S (sleep) : 프로세스가 cpu 자원을 기다리고 있는 상태
SW : 프로세스가 swap 영역에 내려와 있는 상태(스왑파티션에 있다)
(한정된 메모리 자원을 효율적으로 사용하기 위해 일부 프로세스가 swap 영역으로 내갈 수 있다)
SWN : swap 영역에 있는 프로세스중 cpu 자원을 할당받을 우선순위가 낮은 상태
T : 중단된 상태
R : Runable 또는 Running 상태
Z : Zombie 상태
주요옵션
-e : 모든 프로세스 출력
-f : 프로세스 소유자 및 부모 프로세스 정보까지 출력
-ef : -e와 -f 는 주로 같이 붙여서 많이 사용된다.
프로세스도 file system 처럼 계층구조로 되어 있다.
부모프로세스가 있고 그 아래에 자식 프로세스가 있는 구조이다.
ex)
[lee@river book]$ pstree
pstree -u 사용자 => 특정 사용자 권한의 프로세스만 tree 구조로 출력할 수 있다.
ex)
[lee@river book]$ pstree -u lee
bash---bash---pstree
[lee@river book]$
부모 프로세스의 pid 를 출력하고자 하는 경우에는 -f 옵션을 사용하면 된다.
ex)[lee@river book]$ ps -f
UID PID PPID C STIME TTY TIME CMD
lee 3122 3119 0 10:17 pts/0 00:00:00 -bash
lee 3522 3122 0 11:11 pts/0 00:00:00 bash
lee 3613 3522 0 11:37 pts/0 00:00:00 ps -f
[lee@river book]$
몇개의 자식 프로세스를 만들고 테스트 해보자
[lee@river book]$ sleep 300 &
[1] 3614
[lee@river book]$ sleep 600 &
[2] 3615
[lee@river book]$ sleep 900 &
[3] 3616
[lee@river book]$ pstree -u lee
bash---bash-+-pstree
`-3*[sleep]
위에서 실행한 3개의 sleep 프로세스의 부모 프로세스는 바로 위에 있는 bash 라는것을 알 수 있다.
그렇다면 자식 프로세스가 죽기 전에 부모프로세스가 죽는다면 자식 프로세스는 어떻게 될까? 확인해보자
[lee@river book]$ ps -f
UID PID PPID C STIME TTY TIME CMD
lee 3122 3119 0 10:17 pts/0 00:00:00 -bash
lee 3522 3122 0 11:11 pts/0 00:00:00 bash
lee 3614 3522 0 11:38 pts/0 00:00:00 sleep 300
lee 3615 3522 0 11:38 pts/0 00:00:00 sleep 600
lee 3616 3522 0 11:38 pts/0 00:00:00 sleep 900
lee 3620 3522 0 11:40 pts/0 00:00:00 ps -f
여기서 PPID 가 Parent PID 즉, 부모프로세스id 이다.
[lee@river book]$ kill -9 3522 <= 프로세스를 죽이는 명령어
[lee@river newbook]$ ps -f
UID PID PPID C STIME TTY TIME CMD
lee 3122 3119 0 10:17 pts/0 00:00:00 -bash
lee 3614 1 0 11:38 pts/0 00:00:00 sleep 300
lee 3615 1 0 11:38 pts/0 00:00:00 sleep 600
lee 3616 1 0 11:38 pts/0 00:00:00 sleep 900
lee 3621 3122 0 11:40 pts/0 00:00:00 ps -f
부모 프로세스가 메모리에서 제거되었으나 자식 프로세스는 여전히 살아있다.
부모 프로세스가 1로 변경되었다. 그래서 sleep 프로세스는 여전히 부모 프로세스를 갖고
메모리에 남아있다. 부모 프로세스가 죽어도 자식 프로세스는 죽지 않는다는 것을 알 수 있다.
이번에는 pstree 로 확인해보자
[lee@river newbook]$ pstree -u lee
sleep
sleep
sleep
bash---pstreebash---man---sh---sh-+-less
`-nroff---groff---grotty
[lee@river newbook]$
sleep 프로세스의 소유자는 여전히 lee 이지만 더이상 bash의 자식은 아니라는것을 알 수 있다
프로세서 제어 명령어 kill
불필요한 프로세스가 메모리에 남아 있다면 메모리 리소스를 줄이기 위해 제거해야 한다.
프로세스를 제거하는 명령은 kill 이다.
[lee@river newbook]$ help kill
kill: kill [-s sigspec | -n signum | -sigspec] [pid | job]... or kill -l [sigspec]
Send the processes named by PID (or JOB) the signal SIGSPEC. If SIGSPEC is not present,
then SIGTERM is assumed. An argument of `-l' lists the signal names; if arguments follow `-l'
they are assumed to be signal numbers for which names should be listed. Kill is a shell
builtin for two reasons: it allows job IDs to be used instead of process IDs, and, if you have reached
the limit on processes that you can create, you don't have to start a process to kill another one.
[lee@river newbook]$man kill
KILL(1) Linux Programmer's Manual KILL(1)
NAME kill -
SYNOPSIS kill [ -s signal | -p ] [ -a ] pid ... kill -l [ signal ]
kill 은 shell 내장 명령어인 동시에 외부명령어로도 존재한다. kill 명령을 경로 없이 사용한다면
shell 내장 명령어 kill 이 사용된다. 둘 다 비슷하지만 완전히 같진 않다.
kill 명령은 프로세스에게 특정 signal 을 전달하는 명령어인데 아래에 전달 할 수 있는 모든 signal의 종류를 확인할 수
있다. 그러나 일반적으로 자주 사용되는 것들은 몇 안 된다.
[lee@river newbook]$ kill -l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE
9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR213) SIGPIPE 14) SIGALRM 15) SIGTERM
17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN22) SIGTTOU 23) SIGURG
24) SIGXCPU 25) SIGXFSZ26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR
31) SIGSYS 33) SIGRTMIN
... 이하생략.
주요 signal
1) SIGHUP : 프로세스 재실행이다. 죽였다가 다시 실행하는것과 같다.
2) SIGINT : 현재 프로세스 강제종료. ctrl+c 를 사용한다.
9) SIGKILL : 가장 많이 사용되는 시그널로 프로세스 강제 종료이다. 프로세스가 어떤일을 하든 무조건 죽인다.
물론 죽일 수 없는 예외적인 프로세스도 존재한다. 예를 들면 init 프로세스
15) SIGTERM : 프로세스 종료.
이 시그널을 사용하면 프로세스가 종료되지 않을 수도 있다.강제종료가 아니기 때문이다.
20) SIGTSTP : 현재 프로세스 강제 중단. ctrl+z 사용
위에서 언급한 signal 외에 다른 signal 들은 잘 사용되지 않는다.
ex)[lee@river newbook]$ sleep 900 &
[1] 3658 <= sleep 의 pid
[lee@river newbook]$ ps
PID TTY TIME CMD
3122 pts/0 00:00:00 bash
3658 pts/0 00:00:00 sleep
3659 pts/0 00:00:00 ps
sleep 프로세스는 실행할 때의 인자에 해당하는 시간(초)만큼 메모리를 점유한다.
필요없다고 가정하고 제거해보자.
[lee@river newbook]$ kill -SIGKILL 3658
[lee@river newbook]$[1]+ Killed sleep 900
[lee@river newbook]$
-SIGKILL 대신에 -KILL 또는 -9 라고 해도 같다. kill -l 로 출력해보면 signal을 의미하는 SIG 문자가
각 signal 앞에 다 포함되어 있는 것을 알 수 있다. 그래서 SIG 는 생략해도 되며 -9 는 -SIGKILL 의 번호를 뜻한다.
그 번호를 사용해도 된다. 다른 시그널도 다 마찬가지.
[lee@river newbook]$ sleep 600 &
[1] 3662
[lee@river newbook]$ kill 3662
[lee@river newbook]$[1]+ Terminated sleep 600
[lee@river newbook]$
종료 메세지가 다르다. 아무런 signal을 사용하지 않으면 기본적으로 -SIGTERM 시그널이 사용된다.
kill PID = kill -SIGTERM PID = kill -TERM PID = kill -15 PID => 이 세 개는 다 같은 의미이다.
-SIGTERM 은 -SIGKILL 과 달리 프로세스를 안전하게 정상적으로 종료시킨다.
다른 signal 도 확인해보자.
[root@river root]# ps -e | grep sendmail
1132 ? S 0:00 [sendmail]
1141 ? S 0:00 [sendmail]
3707 pts/0 R 0:00 grep sendmail
[root@river root]# kill -SIGHUP 1132
[root@river root]# ps -e | grep sendmail
1141 ? S 0:00 [sendmail]
3709 ? S 0:00 [sendmail]
3712 pts/0 S 0:00 grep sendmail[root@river root]#
SIGHUP signal을 전달하고 난 후 결과를 보면 1132 PID 의 sendmail PID 가 바뀐 것을 알 수 있다.
즉, sendmail 프로세스가 다시 실행되었다는 의미이다. 이렇게 프로세스를 재 실행 할 경우에는
-9로 죽이고 다시 실행하기 보다는 SIGHUP 를 사용하는 것이 편하다
[root@river root]# sleep 1000
sleep 프로세스를 실행할 때 & 붙이지 않으면 sleep 프로세스가 완전히 끝날 때까지는 shell prompt 가
보이지 않는다. 즉 command 를 사용할 수 없다. 시간이 많이 걸리는 프로세스를 실행할 때 & 붙여주지 않고 실행하면
이렇게 멀티태스킹을 사용하지 못하는 문제가 발생한다. 1000초라는 시간을 기다릴 수 없다면 죽여야 한다.
아무런 명령을 사용할 수 없지만 ctrl+c 를 입력하는 것은 가능하다.
vi 편집기 사용도중 ctrl+z 를 입력했다. 그러면
[1]+ Stopped vim a.txt
[root@river root]#vi 편집기가 강제 중단된다. ctrl+z 를 입력하면 현재 프로세스를 강제 중단하는 시그널을
전달하기 때문이다.
[root@river root]# ps -u
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 3665 0.0 0.1 4088 888 pts/0 S 12:10 0:00 [su]
root 3666 0.0 0.2 5448 1448 pts/0 S 12:10 0:00 -bash
root 3719 0.0 0.5 9160 2780 pts/0 T 12:17 0:00 vim a.txt
root 3726 0.0 0.1 2608 660 pts/0 R 12:19 0:00 ps -u
[root@river root]#%CPU 와 %MEM 은 각각 cpu 점유율과 메모리 점유율을 나타낸다.
vi 프로세스의 상태가 T 이다. 중단된 프로세스를 다시 재실행해야 할 경우에는
fg (foreground) 명령을 사용하면 된다.
foreground/background 프로세스
foreground 프로세스에게 터미널 제어권이 있다. foreground 프로세스가 실행중인동안에서터미널에서
명령을 바로 전달하지 못한다.
ex)[root@river root]# sleep 1000
=> sleep 프로세스가 foreground 상태로 실행중이다.
그 아래의 세 개의 명령은 sleep 프로세스가 끝나야 차례대로 실행된다. 그래서 시간이 많이 걸리는 프로세스를
foreground로 실행해서는 곤란하다. 그럴 때는 background 로 실행하면된다.
단지 실행할 때 & 기호만 붙여주면 된다.
ex)
[root@river root]# sleep 1000 &
[2] 3733
[root@river root]# ls
a.txt anaconda-ks.cfg b.txt contest.txt hello unix install.log install.log.syslog
[root@river root]# pwd
/root[root@river root]#
=> 이제 터미널 제어권이 sleep 에게 있지 않으므로 명령을 계속 입력하는 것이 가능하다.
*.background 프로세스는 jobs 명령어로 따로 관리할 수 있다.
[root@river root]# sleep 300 &
[4] 3737
[root@river root]# sleep 900 &
[5] 3739
[root@river root]# sleep 600 &
[6] 3740
[root@river root]# jobs => 중단 또는 background 상태로 실행중인 프로세스만 출력
[1]- Stopped vim a.txt
[2] Running sleep 1000 &
[3]+ Stopped vim b.txt
[4] Running sleep 300 &
[5] Running sleep 900 &
[6] Running sleep 600 &
[root@river root]#
출력결과중 숫자는 프로세스 제어에 사용되는 job 번호 이며 +,- 기호는 가장 나중에 실행된 것,
그리고 두 번째로 나중에 실행된 프로세스를 뜻한다.
[root@river root]# kill -9 %3 %5
[root@river root]#[3]+ 죽었음 vim b.txt
[5] 죽었음 sleep 900
[root@river root]# jobs
[1]+ Stopped vim a.txt
[2] Running sleep 1000 &
[4] Running sleep 300 &
[6]- Running sleep 600 &[root@river root]#
프로세스 id 대신 job 번호로도 프로세스를 제어할 수 있다는 것을 알 수 있다.
중단 또는 백그라운드로 실행중인 프로세스를 foreground 로 전환하고자 하는 경우에는
fg %job번호를 사용하면 된다.
ex)[root@river root]# fg %6
sleep 600[6]+ Stopped sleep 600
[root@river root]# jobs
[1]- Stopped vim a.txt
[2] Running sleep 1000 &
[4] Running sleep 300 &
[6]+ Stopped sleep 600
[root@river root]# bg %6
[6]+ sleep 600 &
[root@river root]# jobs
[1]+ Stopped vim a.txt
[2] Running sleep 1000 &
[4] Running sleep 300 &
[6]- Running sleep 600 &
[root@river root]#
그리고 foreground 상태의 프로세스를 background 로 전환하고자 할 경우에는 먼저 프로세스를 ctrl+z 로
강제 중단한 후 bg 명령을 사용하면 된다.