프로세스
Process
개요
- 실행 중인 프로그램
- 리눅스는 다중 프로세스 시스템
- 프로세스는 부모-자식 관계를 가지고 생성
- 프로세스 구분 방법 중 하나로 시스템 프로세스(운영체제가 생성)와 사용자 프로세스로 나누기도 함
- 리눅스가 부팅이 될 때 systemd 프로세스와 kthreadd 프로세스 생성, 이 프로세스 제외한 모든 프로세스는 부모 프로세스 존재
- 자식 프로세스는 부모 프로세스에 의해 만들어지고 자식 프로세스는 자신의 작업이 종료되면 부모 프로세스에게 결과를 돌려주고 종료됨
- 결과는 정상 수행이나 에러로 인한 종료를 구분하기 위한 값
- 로그인을 해서 bash shell을 실행하고 그 안에서 vi편집기를 실행하면 이 경우는 vi 프로세스가 자식 프로세스가 되고 bash shell이 부모 프로세스가 됨
- vi편집기 종료하면 결과를 bash shell에게 전달하고 종료됨
프로세스 번호
- 프로세스는 만들어질 때 관리의 편리성을 위해 고유번호 부여 PID(Process Identification Number)
- 이름 사용하지 않고 번호 사용하는 이유는 하나의 프로그램을 동시에 여러번 실행할 수 있기 때문에 일반적으로 네이밍 방법으로는 구분하기 어려움
- PID는 1번부터 일련번호 형태로 부여됨
- 부팅될 때 실행되는 systemd가 1번이고 kthreadd가 2번으로 생성, 나머지 프로세스는 이들의 자식
- 유닉스에서는 init 프로세스가 1번이었지만 우분투는 init의 이름을 systemd로 변경
프로세스 종류
리눅스의 프로세스 중 사용자가 실행한 경우에는 잠깐 실행되었다가 종료
Daemon Process
- 특정 서비스를 계속 제공하기 위해 존재
- 커널에 의해서 실행
- 평소에는 대기 상태로 있다가 요청이 오면 서비스를 제공
- 서버에서 구동되는 프로세스들이 여기에 해당되는 경우가 많음
Orphan Process
- 자식 프로세스는 부모 프로세스가 종료되면 같이 종료가 되어야 하는데 부모 프로세스는 종료되었는데 종료되지 않고 남아있는 프로세스
- 1번 프로세스가 새로운 프로세스가 됨
Zombie Process
- 자식 프로세스가 종료될 때 자신이 종료되었다는 사실을 부모 프로세스에게 알려주고 종료되는데 프로세스는 종료가 되었는데 부모 프로세스의 자식 프로세스 테이블에는 남아있는 형태
- 자식 프로세스의 종료를 부모 프로세스가 제대로 처리를 하지 못해서 발생하게 되는데 프로세스 목록에서는 defunct라고 표시
- 부모 프로세스는 자식 프로세스를 테이블 형태로 관리하는데 테이블의 용량이 유한 테이블의 용량이 다 차면 더 이상 프로세스 생성 불가
- 좀비는 실체가 없어서 kill 명령으로 종료 안됨, 부모 프로세스를 종료하거나 SIGCHLD 시그널을 부모 프로세스에게 보내서 좀비 프로세스를 찾아서 정리하도록 해야함
- SIGCHLD 시그널을 보내면 이 프로세스를 고아 프로세스로 만들고 1번 프로세스가 부모 프로세스가 되고 일정 시간 단위로 1번 프로세스가 조회를 해서 제거
프로세스 목록 확인
- ps
- ps [옵션] e: 모든 프로세스 정보 출력 f: 프로세스에 대한 자세한 정보 출력 u uid: 유저가 실행한 프로세스 p pid: 프로세스 id에 해당하는 프로세스의 정보를 출력 a: 터미널에서 실행한 모든 프로세스 정보를 출력 u: 자세히 출력 x: 시스템에서 실행한 모든 프로세스 출력
- 프로세스 검색
ps -ef | grep bash
프로세스 관리
특정 프로세스 검색
- 기본형식:
pgrep [옵션] [패턴]
- 옵션 x: 패턴과 일치하는 프로세스의 정보를 출력 n: 패턴을 포함하고 있는 가장 최근 프로세스의 정보를 출력 u: 사용자이름: 특정 사용자가 수행 중인 모든 프로세스를 출력 l: PID와 프로세스 이름 출력 t: 터미널 특정 단말기와 관련된 프로세스의 정보를 출력
- 특정 프로세스를 조회할 때 ps와 grep를 조합해서 수행, pgrep는 이 두개를 합쳐논 명령어
프로세스 종료
시그널
- 프로세스에 무언가 발생했음을 알려주는 간단한 메시지
- 현재 버전의 리눅스에서 사용가능한 시그널을 확인
kill -l
- SIGHUP(1): 터미널과 연결이 끊겼을 때 발생하는 시그널로 종료를 시켜줌
- SIGINIT(2): 인터럽트(CTRL + c) 발생
- (Interrupt - 정상 수행 중에 강제로 중지), 현재 수행 중인 작업보다 우선순위가 높은 경우에만 중지
- SIGQUIT(3): 종료 신호인데 사용자가 CTRL + \ 를 입력하면 발생
- SIGKILL(9): 프로세스를 강제로 종료시키는 시그널로 이 시그널을 받은 프로세스는 이 시그널을 무시할 수 없음
- SIGALRM(14): 알람에 의해서 발생
- SIGTERM(15): kill 명령이 보내는 기본 시그널
kill
- 프로세스 종료 명령
- 형식:
kill [시그널] PID
pkill
- 프로세스 이름으로 종료
killall
- 프로세스 이름을 종료
top
- 프로세스 정보를 주기적으로 출력
작업제어
- 포그라운드 작업
- 터미널에서 작업할 때 일반적으로 사용자가 명령을 입력하면 쉘이 그 명령을 해석해서 커널에 전달해 실행을 하고 커널이 실행한 결과를 쉘이 받아서 화면에 출력하고 사용자는 화면에 출력된 결과를 보면서 대화식으로 작업을 수행
- 사용자가 입력한 명령이 실행되서 출력될 때 기다리는 방식으로 처리되는 프로세스를 포그라운드 프로세스라고 함
- 포그라운드 작업은 명령이 수행되는 동안에는 프롬프트가 출력되지 않기 때문에 다른 명령을 입력할 수가 없음
- 백그라운드 작업
- 다른 프로세스를 실행되는 동안 뒤에서 실행되도록 하는 작업
- 프롬프트에서 백그라운드로 프로세스를 실행시키면 작업은 뒤에서 실행되고 프롬프트는 바로 출력
- 우분투에서 백그라운드로 작업을 시키는 방법은 작업 뒤에 &를 추가
- 백그라운드로 수행시켜야 하는 작업은 웹 서버나 데이터베이스 서버 처럼 계속해서 구동되어 있어야 하는 프로그램이나 오랜 시간이 걸리는 작업
- 백그라운드로 작업을 수행시킬 때는 바로 결과가 나오지 않기 때문에 작업이 수행 중인지 확인하는 것이 좋음 100초 동안 현재 스레드를 중지시키는 프로세스를 백그라운드로 실행하고 확인, ps pgrep 사용
jobs
- 모든 백그라운드 작업을 조회하는 명령
- 형식:
jobs [%작업번호]
dh@dh:~$ jobs
[1]+ Running sleep 100 &
맨 앞의 1은 작업 번호로 작업이 늘어날 때마다 1씩 증가 + 기호는 가장 최근에 수행된 백그라운드 작업 Running은 작업 상태 sleep 100은 작업 내용
작업 전환
- ctrl + z: 포그라운드 작업을 중지
- bg %작업번호: 작업 번호가 지시하는 작업을 백그라운드로 전환
- fg %작업번호: 백그라운드 작업을 포그라운드로 전환
계속 실행
- 일반적인 작업은 로그아웃을 하면 종료
- 로그아웃 후에도 백그라운드에서 계속 작업이 수행되도록 하고자 할 때는 nohup 명령 & 로 실행시키면 됨
cronjob(작업예약)
- 운영체제 제공 기능 이용
- 프로그래밍 언어로 프로그램을 만들어서 이용
- 응용 프로그램이 제공하는 기능 이용 쿠버네티스 크론잡, 에어플로우
- 정해진 시간에 한번만 실행 at 명령으로 실행
- 형식
at [옵션] [시각]
작업내용
- 옵션:
l: 현재 실행 대기 중인 명령 목록을 출력
r 작업번호: 작업번호에 해당하는 작업을 삭제
m: 출력 결과가 없더라도 작업이 완료되면 사용자에게 메일로 알려줌
f 파일경로: 작업을 직접 입력하지 않고 파일의 내용을 수행하고자 하는 경우
- 시간 설정 방법: at 시간: 시간에 동작
at 04:00 pm: 오후4시
at 1 am tomorrow: 내일 오전 1시
at 1 am jul 31: 7/31 1시
at 4 pm + 3days: 3일 후 오후 4시
- 작업 확인 명령
ls -l /var/spool/cron/atjobs
- 실습:
- 오전 10시 50분에 ls -l 명령의 결과를 a.out에 출력
at 10:50 am
at>/usr/bin/ls -l > a.out
- 작업확인
sudo ls -l /var/spool/cron/atjobs
crontab - 주기를 가지고 작업을 계속 수행
- 형식:
crontab [-u 사용자계정] [옵션] [파일 경로]
- 옵션
e: 사용자의 크론탭 파일 편집
l: 크론탭 파일의 목록을 출력
r: 크롭탭 파일 삭제
- crontab 명령으로 관리하는 파일은 사용자 별로 생성되는데 이 파일에 반복 실행할 작업을 저장
- 작성할 때 여러 개의 명령을 하나의 파일에 기록할 수 있는데 이 경우 각 명령은 별도의 행에 작성해야 함
- 작성 방법
분(00-59) 시간(00-23) 일(1-31) 월(1-12) 요일(0-6) 작업내용
- 요일은 0이 일요일
- 앞에 5개 항목에서 *이 있으면 해당 항목의 모든 값을 의미
30 23 1 * * 작업 -> 매월 1일 23:30 분에 작업을 수행
30 * 1 * * 작업 -> 매월 1일 매시간 30분에 작업을 수행
- 하이픈 연산자 사용하면 범위 설정 가능
- 요일 설정할 때 1-5로 설정하면 월요일부터 금요일까지
- ,를 이용해 여러개의 값 지정가능
1,3,5
- /를 이용해서 단계값을 설정가능
1-10/2 -> 1,3,5,7,9
*/20
crontab -e # crontab 파일 생성
sudo -l /var/spool/cron/crontabs # crontab 목록확인
crontab -l # crontab 파일 내용 확인
crontab -r # crontab 삭제
systemd service
- 리눅스 시스템과 서비스 관리로 유닉스의 init을 대체
- 다양한 서비스 데몬을 시작하고 프로세스들의 상태를 유지하고 시스템 상태를 관리하는 역할을 수행
- init에 비해 개선된점:
- 쉘과 독립적으로 부팅 가능
- 시스템 상태에 대한 스냅샷을 유지
- 셧다운전에 사용자 세션의 안전한 종료가 가능
unit
- 서비스의 종류를 구분하기 위해 사용하는 개념
- systemd는 관리 대상의 이름을 서비스명:유닛종류 형태로 관리
- 종류:
- service: 시스템 서비스 유닛으로 데몬을 시작, 재시작, 종료 및 로드
- target: 유닛을 그룹화
- automount: 디렉터리 계층 구조에서 자동 마운트 포인트를 관리
- device: 리눅스 장치 트리에 있는 장치를 관리
- path: 파일 시스템의 파일이나 디렉터리 경로를 관리
- scope: 외부에서 생성된 프로세스를 관리
- slice: 시스템의 프로세스를 계층적으로 관리
- socket: 소켓을 관리하는 유닛
- swap: 스왑 관리
- timer: 타이머
명령
- systemd를 위한 명령은 systemctl
- systemctl 명령을 이용해 서비스를 시작하거나 중지
systemctl [옵션] [명령] [유닛이름]
- 유닛 이름은 이름.service 이지만 .service는 생략 가능
- 옵션
-a: 유닛 전체를 출력
-t 유닛종류: 유닛 종류만 출력
- 명령
start: 서비스시작
stop: 서비스중지
reload: 설정파일다시읽기
restart: 재시작
status: 유닛 상태를 출력
enable: 부팅할 때 자동 시작하도록
disable: 부팅할 때 자동 시작 않도록
is-active: 동작 중인지 확인
is-enabled: 부팅할 때 자동 시작 여부
isolate: 지정한 유닛 및 이와 관련된 유닛만 시작하고 나머지는 중지
kill: 유닛에 시그널
cgroup
- 자원 사용을 프로세스 그룹 단위로 제어할 수 있는 리눅스 커널 기능
- CPU, Memory, Network, IO 등을 포함
- 컨테이너의 핵심 기술
- 사용방법
- cgroup이라는 가상 파일 시스템을 수동으로 마운트해서 사용
- libcgroup과 같은 툴을 사용해서 생성하고 관리
- cgroup을 사용하는 소프트웨어(docker, LXC가상화 등) 활용