1. 프로세스
명령어들의 실체는 디스크에 있는 실행 파일이다. 셸에서 명령어를 입력하면 커널이 해당하는 명령어 파일을 읽어 메모리에 올려 CPU가 프로그램을 실행시킨다. 이 때 메모리 위에 올린 프로그램을 프로세스라 한다.
같
은 프로그램을 실행하더라도 각 프로세스는 별도의 메모리 영역을 가지며, 파일의 소유자에따라 권한이 제한되는것 처럼 프로세스를 실행한 사용자에게 권한이 주어진다. 리눅스 커널은 각각의 프로세스에게 프로세스 ID 라는 고유한 번호를 할당해서 관리한다.
리눅스에서 새로운 프로세스는 기존에 존재하는 별도의 프로세스를 기반으로 만들어진다. 여기서 새로운 프로세스를 만드는 프로세스를 부모 프로세스라고 하며, 새롭게 만들어지는 프로세스를 자식 프로세스라고 한다. 예를들어 셸에서 ls 명령어를 실행하면 부모 프로세스는 셸이며 자식 프로세스는 ls 명령어이다.
1.1. 프로세스 목록 표시 명령어 : ps
■ 프로세스 목록 표시하기
$ ps
인자 없이 ps 명령어 입력만으로 현재 접속한 터미널에서 실행한 프로세스만 출력한다.
- PID : 프로세스 ID
- TTY : 터미널
- CMD : 실행한 명령어
즉 프로세스 ID (PID) 가 54114 인 bash 명령어와 프로세스 ID가 79431인 ps 명령어가 실행 중이라는 의미이다.
프로세스 ID (PID) 는 프로세스가 종료되기 전까지 바뀌지 않는다. 따라서 특정 프로세스를 지정할 때 PID 를 사용할 수 있다.
1.1.1. 현재 접속한 터미널 외의 프로세스 출력
다른 터미널에서 실행 중인 프로세스나 터미널과 무관하게 돌아가는 프로세스인 데몬(demon)을 출력하려면 x 옵션을 사용하면 되는데, 이 x 옵션으로 사용자가 현재 실행 중인 모든 프로세스를 확인할 수 있다. f 옵션은 프로세스 간 부모 자식 관계를 표시할 수 있다.
bash 아래에 ps 가 있는것을 볼 수 있다.
TTY 는 터미널을 의미하는데 ? 으로 표시되는것은 SSH 접속을 담당하는 프로세스 이다. 해당 프로세스가 터미널에 접속되어 있지 않은 데몬(demon)을 의미한다.
1.1.2. ps 명령어의 옵션 형식
위에서 보면 ps 명령어에 -를 붙이지 않고 xf 옵션을 지정했다. 리눅스의 ps 명령어는 두 종류의 옵션 형식을 제공한다.
- UNIX 방식 옵션 : 대시(-)를 사용하여 옵션 지정. (예) ps -ef
- BSD 방식 옵션 : - 없이 옵션 지정. (예) ps aux
대시(-) 에따라 다른 옵션체계가 적용된다.
가장 많이 사용되는 옵션을 살펴보자.
(1) UNIX 옵션
옵션 | 내용 |
-e | every 커널 프로세스 제외한 모든 프로세스 출력 |
-f | full 풀 포맷으로 출력(UID, PID, PPID 등 출력) |
-l | long 긴 포맷(우선순위 관련된 PRI, NI 값등 확인가능) |
사용예 | |
-ef | 모든 프로세스를 풀 포맷으로 출력 |
-ef | grep '프로세스명' | '프로세스명'의 구동 확인 |
(2) BSD 옵션
옵션 | 내용 |
x | ps 명령어 실행한 사용자의 프로세스 출력 |
f | 트리구조로 프로세스 출력 |
ux | ps 명령어 실행한 사용자의 프로세스를 상세히 출력 |
ax | 모든 사용자 프로세스 출력 |
aux | 모든 사용자의 프로세스 상세히 출력 |
auxww | aux 옵션의 출력결과가 화면에 잘리지 않도록 출력 |
사용예 | |
aux | grep '프로세스명' | '프로세스명'의 프로세스 상세히 확인 |
1.2. 프로세스 종료 명령어 : kill
■ 프로세스 종료하기
$ kill <프로세스 ID>
주의해야할 점은 다른 사용자가 실행 중인 프로세스는 함부로 종료할 수 없다. 예외적으로 슈퍼 사용자(루트 유저)는 모든 사용자의 프로세스를 강제 종료할 수 있다.
2. 잡 (job)
셸에서의 처리 단위를 잡(job)이라고 한다. 셸에서 커맨드 라인에 입력한 것이 잡에 해당한다. 커맨드 라인에서 명령어 하나만 입력했다면 프로세스와 잡은 같다. 다음 그림과 같이 복수의 명령어를 파이프로 연결하면 잡은 1개이지만 프로세스는 명령어마다 생성되어 3개가 생성된다.
프로세스는 시스템 전체에 걸쳐 프로세스 ID 라는 유일한 값이 할당된다. 하지만, 잡은 셸별로 관리된다. 그래서 터미널 여러개를 사용해서 셸 여러개를 사용하면 중복된 잡 번호가 할당될 수 있다. 잡은 일시 정지하거나 백그라운드에서 실행할 수 있다.
2.1. 명령어의 일시정지
■ 명령어의 일시 정지
Ctrl + Z
man bash 를 실행하여 bash 의 매뉴얼을 확인하던 중 다른 작업을 해야할 경우, q를 눌러 종료를 하지않고 Ctrl + Z 를 누르면 다음과 같이 프롬프트에 출력되고 커맨드가 입력할 수 있게 된다. man bash 가 종료되고 명령어를 입력할 수 있는것 처럼 보이지만, man bash 라는 잡이 정지 상태로 된 것 뿐이다. 이렇게 일시정지된 잡은 다시 정지한 상태에서부터 실행할 수 있다.
2.2. 잡 목록 확인
■ 잡(jobs) 목록 확인
$ jobs
임의의 명령어들을 실행하고 일시정지상태로 만들어 잡을 생성한 후, jobs 명령어로 출력해 보았다.
[1], [2], [3] 과같은 숫자는 잡의 번호를 의미한다. 여기서 프로세스 ID (PID) 도 함께 출력해서 보고 싶다면 -l 옵션을 사용한다.
■ 잡(jobs) 목록을 프로세스 ID와 함께 확인
$ jobs -l
잡 번호 뒤에 프로세스 ID가 함께 출력되어 확인할 수 있다.
2.3. 일시정지된 잡을 포그라운드(foreground)로 전환하는 명령어 : fg
포그라운드(foreground)란 사용자의 입력을 받아들일 수 있는 잡의 상태를 말한다. 정지상태에 있는 잡을 다시 확인하기 위해서는 포그라운드로 되돌려야 한다.
■ 일시정지 상태의 잡(jobs) 을 포그라운드로 전환하는 명령어
$ fg %<잡번호>
bash 매뉴얼을 읽는 도중이었던 [1] 잡을 실행해 다시 확인하던 부분부터 보려면 다음과 같이 입력하면 된다.
여기서 %<잡번호>를 생략하면, jobs 명령어를 실행했을 때 +로 표시되는 현재 잡이 실행된다.
예를들어 다음의 캡쳐와 같이 [1]의 잡에 +가 표기되어 있으므로, 잡번호를 생략하고 fg만 입력하면 [1] 의 잡이 실행된다.
2.4. 잡을 백그라운드(background)로 전환하는 명령어 : bg
백그라운드(background)란 포그라운드와 반대로 사용자가 조작할 수 없는 잡의 상태를 말한다. 작업을 하다보면 잡을 멈추지 않은 채 셸로 돌아가는 경우가 생긴다. 예를들어, 긴 시간이 걸리는 작업을 실행시켜 놓고 하염없이 터미널창을 쳐다보고 있는 것보다 백그라운드에서 해당 작업이 돌아가는 도중에 셸로 다른 작업을 수행하는 것이 효율적일 수 있다.
■ 잡(jobs) 을 백그라운드로 전환하는 명령어
$ bg %<잡번호>
fg 명령어와 마찬가지로 잡 번호를 생략하면 + 로 표시된 현재 잡이 백그라운드에서 실행된다.
■ 잡(jobs) 을 백그라운드에서 실행하는 명령어
커맨드 라인의 마지막에 & 을 추가하면 해당 명령어가 백그라운드에서 실행된다.
$ 명령어 &
$ cp file1 file2 & # cp명령어를 백그라운드에서 실행한다.
2.5. 잡의 상태 전이
■ 잡(jobs) 의 상태
상태 | 내용 |
포그라운드(foreground) | 사용자가 조작하면서 실행 중의 상태 |
백그라운드(background) | 사용자가 조작할 수 없지만 실행 중인 상태 |
정지(stopped) | 처리를 일시 중단한 상태 |
2.6. 잡의 종료 명령어 : kill
포그라운드(foreground)로 실행 중인 잡을 종료하기 위해서는 Ctrl + C 를 입력하면 된다.
백그라운드(background)로 실행 중인 잡을 종료하기 위해서는 kill 명령어를 실행한다.
■ 잡 종료 명령어
$ kill %<잡 번호>
다음과 같이 잡 번호 [2] 를 종료하기위해 kill %2 명령어를 실행했다.
종료후, 다시 잡 목록을 확인하면 [2] 잡이 종료되었음을 확인할 수 있다.
3. kill 명령어
kill 명령어는 프로세스나 잡을 종료하는 명령어가 아니다. 단지 시그널을 전송하는 명령어이다.
시그널은 말 그대로 프로세스에 전송되는 신호이다. 프로세스는 전달받은 시그널의 종류에 따라 종료, 정지, 재기동 등의 처리를 수행한다.
전송할 시그널의 종류는 아래와 같이 지정할 수 있다.
$ kill -<시그널 이름>
시그널을 지정하지않으면 기본값으로 TERM 이 된다. TERM 은 terminate 라는 의미로 종료 시그널이다. 그래서 시그널 이름을 지정하지않으면 자동으로 프로세스나 잡이 종료되는 것이다. 또, 시그널 이름에는 각각 고유의 번호가 존재하여 이를 지정하는 방식도 가능하다. TERM 의 고유 번호는 15이다. 따라서 다음의 명령어들은 동일하다.
- kill 81080
- kill -TERM 81080
- kill -15 81080
포그라운드(foreground)에서 동작하는 잡에게 입력한 Ctrl + Z , Ctrl + C 도 내부적으로 시그널을 전송하는 것이다.
- Ctrl + Z 의 시그널 이름 : TSTP
- Ctrl + C 의 시그널 이름 : INT
시그널 목록은 kill 명령어에 -l 옵션을 지정하여 확인할 수 있다.
■ 시그널 목록 확인
$ kill -l
SIG라는 문자열이 붙어 표시된다.
시그널 목록중에 9) SIGKILL 은 예외적이다. 이 시그널은 프로세스에 전달되지 않고 리눅스 커널이 처리한다. 리눅스 커널은 이 시그널을 받으면 지정한 프로세스를 강제로 종료한다. 즉, 일반적인 15)TERM 시그널을 보내도 종료되지 않는 상태에 빠졌을 때, 강제종료 하기위한 시그널이다.
KILL 시그널은 강제 종료하므로 신중하게 이용해야한다. 해당 프로세스가 적절한 작업을 수행하지 못한 상태에서 강제로 종료되면 예상치 못한 문제가 야기될 수 있기 때문이다.
따라서, TERM 으로 종료되지 않았을때 KILL 시그널을 사용하여 종료하는 것이 바람직하다.