Home Linux System Operations
Post
Cancel

Linux System Operations

# Linux System Operations

Q&A: 프로세스, 데몬, systemctl, tmux, 리버스 프록시

질문

  1. 프로세스는 현재 돌아가는 프로그램(함수 콜백 등), daemon은 보통 백그라운드에서 도는 주요 배치 프로그램인가?
  2. systemctl은 무엇인가?
  3. tmux는 무엇인가?
  4. 리버스 프록시는 사용자 요청과 웹서버 사이에 인터페이스를 하나 더 둔 것인가? nginx처럼 보안이나 로드 밸런싱 같은 것을 담당하도록?

답변

1. 프로세스와 데몬

프로세스(process) 는 실행 중인 프로그램이다.

예를 들어 디스크에 있는 /bin/ls는 실행 파일이고, 사용자가 ls를 실행하면 메모리 위에 실행 중인 ls 프로세스가 생긴다.

1
ls

정리하면 다음과 같다.

1
2
프로그램 = 디스크에 저장된 실행 가능한 파일
프로세스 = 실행 중인 프로그램의 인스턴스

여기서 “함수 콜백”은 프로세스 자체라기보다는, 어떤 프로세스 안에서 실행되는 코드 흐름에 가깝다. 예를 들어 Node.js 서버 프로세스 안에서 콜백 함수들이 실행될 수는 있지만, 콜백 하나하나를 보통 OS 프로세스라고 부르지는 않는다.

데몬(daemon) 은 보통 백그라운드에서 오래 실행되며 특정 서비스를 제공하는 프로세스다.

1
2
3
4
sshd    SSH 접속을 받아주는 데몬
nginx   HTTP 요청을 받아주는 웹 서버 데몬
cron    정해진 시간에 작업을 실행하는 데몬
mysqld  MySQL 서버 데몬

데몬은 백그라운드에서 돈다는 점이 중요하지만, 모든 백그라운드 프로세스가 데몬인 것은 아니다.

1
sleep 100 &

위 명령은 백그라운드 프로세스지만, 보통 데몬이라고 부르지는 않는다. 그냥 사용자가 뒤에서 실행시킨 임시 프로세스에 가깝다.

또 데몬을 “주요 배치 프로그램”이라고 이해하면 조금 좁다. 배치 작업을 담당하는 데몬도 있지만, 데몬은 배치보다 넓은 개념이다. 웹 서버, SSH 서버, DB 서버처럼 계속 대기하면서 요청을 처리하는 서비스도 데몬이다.

1
2
3
4
프로세스   실행 중인 프로그램
백그라운드 터미널 앞을 차지하지 않고 뒤에서 실행되는 방식
데몬       백그라운드에서 오래 실행되며 서비스를 제공하는 프로세스
배치       정해진 작업을 한 번 또는 주기적으로 처리하는 작업 방식

2. systemctl

systemctl은 리눅스에서 systemd가 관리하는 서비스들을 제어하는 명령어다.

요즘 많은 리눅스 배포판은 부팅, 서비스 실행, 데몬 관리, 로그 연동 등을 systemd라는 시스템 매니저가 담당한다. systemctl은 그 systemd에게 명령을 내리는 도구다.

예를 들어 nginx 서비스를 시작하려면 다음처럼 쓴다.

1
sudo systemctl start nginx

서비스를 멈추려면 다음처럼 쓴다.

1
sudo systemctl stop nginx

상태를 확인하려면 다음처럼 쓴다.

1
systemctl status nginx

서버가 부팅될 때 자동으로 nginx가 켜지게 하려면 enable을 사용한다.

1
sudo systemctl enable nginx

자동 시작을 끄려면 disable을 사용한다.

1
sudo systemctl disable nginx

정리하면 다음과 같다.

1
2
3
systemd    리눅스 시스템과 서비스를 관리하는 시스템 매니저
systemctl  systemd에게 명령을 내리는 CLI 도구
service    systemd가 관리하는 데몬 또는 백그라운드 작업 단위

자주 쓰는 명령은 다음과 같다.

1
2
3
4
5
6
systemctl status nginx
sudo systemctl start nginx
sudo systemctl stop nginx
sudo systemctl restart nginx
sudo systemctl enable nginx
sudo systemctl disable nginx

여기서 start와 enable은 다르다.

1
2
start   지금 즉시 실행
enable  다음 부팅부터 자동 실행되도록 등록

3. tmux

tmux는 터미널 멀티플렉서(terminal multiplexer)다. 쉽게 말하면 하나의 SSH 터미널 안에서 여러 터미널 세션을 만들고, 접속이 끊겨도 작업을 계속 유지하게 해주는 도구다.

SSH로 원격 서버에 접속해서 긴 작업을 실행한다고 해보자.

1
ssh ubuntu@server

그 상태에서 오래 걸리는 작업을 실행했다.

1
./deploy.sh

그런데 네트워크가 끊기면 일반적으로 SSH 세션이 종료되고, 그 안에서 실행 중이던 작업도 같이 영향을 받을 수 있다. tmux를 쓰면 작업을 tmux 세션 안에 띄워두고, SSH 연결이 끊겨도 나중에 다시 붙을 수 있다.

기본 사용 예시는 다음과 같다.

1
tmux new -s work

work라는 이름의 tmux 세션을 만든다. 그 안에서 작업을 실행한다.

1
./long-running-task.sh

세션에서 빠져나오려면 보통 다음 키를 누른다.

1
Ctrl-b 를 누른 뒤 d

이것을 detach라고 한다. 작업은 계속 실행된다.

나중에 다시 붙으려면 다음처럼 한다.

1
tmux attach -t work

세션 목록은 다음처럼 본다.

1
tmux ls

정리하면 다음과 같다.

1
2
3
tmux session   유지되는 터미널 작업 공간
detach         세션은 살려두고 빠져나오기
attach         살아 있는 세션에 다시 접속하기

tmux는 서버 관리, 배포, 로그 모니터링, 긴 작업 실행에서 유용하다. 다만 운영 배포를 tmux에만 의존하는 것은 좋은 자동화 방식은 아니다. 실무에서는 systemd, CI/CD, Docker, Kubernetes 같은 방식과 함께 이해하는 것이 좋다.

4. 리버스 프록시와 nginx

리버스 프록시(reverse proxy)는 사용자의 요청을 실제 애플리케이션 서버 앞에서 먼저 받아서, 적절한 내부 서버로 전달하는 서버다.

1
사용자 -> 리버스 프록시 -> 애플리케이션 서버

예를 들어 사용자는 https://example.com으로 요청을 보낸다. 이 요청을 nginx가 먼저 받고, 내부의 Spring Boot나 Node.js 서버로 넘길 수 있다.

1
2
3
브라우저
-> nginx
-> localhost:8080의 Spring Boot 앱

nginx 설정은 대략 이런 형태가 될 수 있다.

1
2
3
4
5
6
7
8
server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://127.0.0.1:8080;
    }
}

이 경우 사용자는 127.0.0.1:8080에 직접 접속하지 않는다. 사용자는 nginx에 요청하고, nginx가 내부 앱 서버로 요청을 전달한다.

리버스 프록시가 하는 대표적인 역할은 다음과 같다.

1
2
3
4
5
6
7
8
9
TLS/HTTPS 처리
로드 밸런싱
요청 라우팅
정적 파일 서빙
압축
캐싱
보안 헤더 추가
Rate limiting
내부 서버 주소 숨기기

그러나 리버스 프록시를 단순히 “보안을 담당하는 것”으로만 이해하면 부족하다. 리버스 프록시는 보안 기능도 할 수 있지만, 핵심은 클라이언트 요청을 받아 내부 서버로 대신 전달하는 중간 서버라는 점이다.

프록시와 리버스 프록시의 차이도 알아두면 좋다.

1
2
포워드 프록시  클라이언트 앞에 서서 클라이언트를 대신해 외부로 나간다
리버스 프록시  서버 앞에 서서 서버를 대신해 요청을 받는다

예를 들어 회사 내부에서 인터넷 접속을 통제하는 프록시는 포워드 프록시에 가깝다.

1
내 PC -> 포워드 프록시 -> 인터넷

반면 nginx가 여러 웹 서버 앞에서 요청을 받는 구조는 리버스 프록시다.

1
사용자 -> nginx -> app1/app2/app3

로드 밸런싱을 하면 다음처럼 여러 서버 중 하나로 요청을 보낼 수 있다.

1
2
3
사용자 -> nginx -> app1
              -> app2
              -> app3

정리하면 다음과 같다.

1
2
3
4
5
6
7
프로세스        실행 중인 프로그램
데몬            백그라운드에서 오래 실행되며 서비스를 제공하는 프로세스
systemd         리눅스 서비스 관리자
systemctl       systemd를 제어하는 명령어
tmux            터미널 세션을 유지하고 나눠 쓰는 도구
리버스 프록시   사용자 요청을 앞에서 받아 내부 서버로 전달하는 서버
nginx           웹 서버이자 리버스 프록시로 자주 쓰이는 프로그램(웹서버, reverse proxy, load balancer 다 수행 가능)

사용자의 이해를 고쳐 말하면 다음과 같다.

1
2
3
4
5
프로세스는 실행 중인 프로그램이다. 함수 콜백 자체는 보통 프로세스가 아니다.
데몬은 단순 배치 프로그램이 아니라, 백그라운드에서 지속적으로 서비스를 제공하는 프로세스다.
systemctl은 그런 데몬/서비스를 시작, 중지, 재시작, 자동 실행 설정하는 도구다.
tmux는 SSH 세션 안에서 작업 공간을 유지하고 여러 터미널을 다루게 해주는 도구다.
리버스 프록시는 사용자와 앱 서버 사이에서 요청을 받아 전달하고, nginx가 그 역할을 자주 맡는다.

전체 연결해서 보면

1
2
3
4
5
6
7
8
9
10
11
사용자 요청
↓
Nginx(reverse proxy daemon)
↓
Application process
↓
systemd가 관리
↓
SSH로 원격 운영
↓
tmux로 세션 유지

Q&A: systemd는 무엇인가?

질문

systemctl 설명과 관련해서, systemd가 무엇인지 핵심만 보충해 달라. 리눅스의 네이티브 기능인가?

답변

systemd는 리눅스 시스템에서 부팅 과정과 서비스 관리를 담당하는 시스템 매니저다.

컴퓨터가 켜지면 리눅스 커널이 먼저 실행되고, 그 다음 사용자 공간의 첫 번째 주요 프로세스로 systemd가 실행된다. systemd는 이후 여러 서비스와 데몬을 시작하고 관리한다.

1
2
3
4
5
전원 켜짐
-> 부트로더
-> 리눅스 커널
-> systemd
-> sshd, nginx, cron 같은 서비스 실행

systemd가 관리하는 대표적인 일은 다음과 같다.

1
2
3
4
5
6
서비스 시작/중지/재시작
부팅 시 자동 실행 관리
서비스 의존성 관리
로그 시스템 연동
타이머 기반 작업 실행
마운트, 네트워크 등 시스템 자원 관리

systemctl은 이 systemd에게 명령을 내리는 CLI 도구다.

1
2
3
sudo systemctl start nginx
systemctl status ssh
sudo systemctl enable docker

중요한 점은 systemd가 리눅스 커널 자체의 기능은 아니라는 것이다. 커널 내부 기능이 아니라, 커널 위에서 실행되는 사용자 공간 프로그램이다.

다만 현대의 많은 리눅스 배포판, 예를 들어 Ubuntu, Debian, Fedora, CentOS 계열은 systemd를 기본 시스템 매니저로 사용한다. 그래서 실무에서는 리눅스의 표준적인 서비스 관리 방식처럼 자주 접하게 된다.

정리하면 다음과 같다.

1
2
3
Linux kernel  운영체제의 핵심 커널
systemd       커널 위에서 실행되는 시스템/서비스 관리자
systemctl     systemd를 조작하는 명령어

따라서 systemd는 리눅스 커널의 네이티브 기능은 아니지만, 현대 리눅스 배포판에서 사실상 표준처럼 널리 쓰이는 기본 시스템 관리 도구라고 이해하면 된다.

Q&A: systemd, systemctl, shell, kernel의 관계

질문

그러니까 systemd는 systemctl으로 조작되는 프로그램이고, curl 등을 명령어로 입력하면 shell이 그걸 커널로 전달하는 메커니즘과 비슷한 것인가?

답변

거의 맞지만, 조금만 정확히 다듬자.

systemd와 systemctl 관계는 이렇게 봐야 한다.

1
2
systemd    실제로 시스템/서비스를 관리하는 데몬
systemctl  systemd에게 명령을 보내는 CLI 도구

예를 들어 다음 명령을 보자.

1
sudo systemctl restart nginx

이건 systemctl이라는 명령어가 실행되고, 그 명령어가 systemd에게 “nginx 서비스를 재시작해줘”라고 요청하는 구조다. 실제로 nginx 프로세스를 관리하고 상태를 추적하는 주체는 systemd다.

다만 curl 실행과는 조금 다르다.

1
curl https://example.com

이 경우 셸이 curl을 “커널로 전달한다”기보다는 다음 흐름에 가깝다.

1
2
3
4
5
사용자 입력
-> shell이 curl 실행 파일을 찾음
-> shell이 커널에게 새 프로세스 실행을 요청
-> 커널이 curl 프로세스를 만듦
-> curl 프로세스가 실행됨

즉 셸은 커널에게 “이 프로그램 실행해줘”라고 시스템 콜을 통해 요청한다.

반면 다음 명령은 이렇게 볼 수 있다.

1
systemctl restart nginx
1
2
3
4
5
사용자 입력
-> shell이 systemctl 실행
-> systemctl 프로세스가 systemd와 통신
-> systemd가 nginx 서비스 상태를 변경
-> 필요하면 커널에게 프로세스 생성/종료 등을 요청

그래서 비슷한 점은 있다.

1
2
3
둘 다 사용자는 명령어를 입력한다.
둘 다 shell이 실행 파일을 찾아 프로세스로 실행한다.
둘 다 결국 커널의 도움을 받아 프로세스가 실행된다.

하지만 차이는 다음과 같다.

1
2
3
curl      = curl 자신이 일을 하는 일반 명령어
systemctl = systemd에게 일을 시키는 조작 명령어
systemd   = 백그라운드에서 서비스들을 관리하는 관리자 프로세스

한 줄로 말하면 다음과 같다.

1
systemctl은 systemd를 조작하는 리모컨이고, curl은 직접 일을 하는 도구다.

Q&A: systemd unit file은 무엇인가?

질문

systemd unit file은 무엇인가?

답변

systemd unit file은 systemd가 어떤 대상을 어떻게 관리할지 적어 둔 설정 파일이다. 서비스 실행 방법, 자동 재시작 여부, 의존성 같은 정보를 선언한다.

unit은 서비스만 뜻하지 않는다.

1
2
3
4
.service  데몬이나 서비스 프로세스
.socket   소켓 기반 활성화 대상
.timer    시간 기반 실행
.mount    마운트 대상

가장 자주 보는 것은 .service unit이다.

1
2
3
4
5
6
7
8
9
10
[Unit]
Description=My App
After=network.target

[Service]
ExecStart=/usr/local/bin/my-app
Restart=on-failure

[Install]
WantedBy=multi-user.target

이 파일은 대략 다음 뜻이다.

1
2
3
4
network.target 이후 실행
my-app 실행 파일로 서비스 시작
실패하면 재시작
부팅 시 일반 서버 모드에서 함께 켤 수 있음

systemctl은 이런 unit을 기준으로 동작한다.

1
2
3
sudo systemctl start my-app
sudo systemctl enable my-app
systemctl status my-app

정리하면 다음과 같다.

1
2
3
systemd unit       systemd가 관리하는 대상
unit file          그 대상의 실행/관리 규칙을 적은 설정 파일
systemctl          unit을 시작, 중지, 조회하는 명령어

Q&A: signal은 무엇인가?

질문

signal은 무엇인가?

답변

signal은 프로세스에게 보내는 짧은 알림 또는 제어 요청이다. 운영체제나 다른 프로세스가 실행 중인 프로세스에 “종료해”, “중단됐어”, “계속해” 같은 사건을 전달할 때 쓴다.

자주 만나는 signal은 다음과 같다.

1
2
3
SIGINT   인터럽트 요청. 터미널에서 Ctrl-C와 자주 연결됨
SIGTERM  정상 종료를 요청
SIGKILL  즉시 강제 종료. 프로세스가 무시하거나 처리할 수 없음

예를 들어 프로세스에 종료 요청을 보낼 수 있다.

1
kill 1234

기본 kill은 보통 SIGTERM을 보낸다. 즉 “정리하고 종료해 달라”는 요청에 가깝다.

강제 종료는 다음처럼 쓴다.

1
kill -KILL 1234

이것은 프로세스가 정리 코드를 실행할 기회도 거의 주지 않으므로 마지막 수단으로 보는 편이 좋다.

프로그램은 일부 signal을 받아서 정리 작업을 수행할 수 있다. 예를 들어 서버가 SIGTERM을 받으면 새 요청을 그만 받고 진행 중인 작업을 정리한 뒤 종료하도록 만들 수 있다.

정리하면 다음과 같다.

1
2
3
4
signal    실행 중인 프로세스에 전달되는 제어/알림 메커니즘
SIGTERM   종료 요청
SIGKILL   강제 종료
Ctrl-C    포그라운드 프로세스에 SIGINT를 보내는 흔한 입력

Q&A: fork와 exec는 무엇인가?

질문

fork와 exec는 무엇인가?

답변

fork와 exec는 유닉스/리눅스에서 새 프로그램을 실행할 때 핵심이 되는 프로세스 생성 방식이다.

1
2
fork  현재 프로세스를 복제해 자식 프로세스를 만든다
exec  현재 프로세스의 내용을 다른 프로그램으로 교체한다

셸에서 다음 명령을 입력했다고 하자.

1
ls

흐름은 대략 다음과 같다.

1
2
3
4
shell 프로세스
-> fork로 자식 프로세스 생성
-> 자식 프로세스가 exec로 ls 프로그램 실행
-> 부모 shell은 기다리거나 다음 명령을 받음

중요한 점은 exec가 새 프로세스를 추가로 만드는 것이 아니라, 현재 프로세스의 프로그램 이미지를 바꾸는 것이라는 점이다. 그래서 보통 fork로 자식을 만든 뒤, 그 자식이 exec로 원하는 프로그램이 된다.

백그라운드 실행도 이 구조와 이어진다.

1
sleep 100 &

셸은 자식 프로세스를 만들고 sleep을 실행시키지만, 포그라운드처럼 끝날 때까지 기다리지 않고 바로 다음 명령을 받는다.

정리하면 다음과 같다.

1
2
3
fork        프로세스 복제
exec        실행할 프로그램으로 교체
shell 실행  fork 후 자식에서 exec

Q&A: process tree는 무엇인가?

질문

process tree는 무엇인가?

답변

process tree는 프로세스들이 부모-자식 관계로 연결된 구조다. 리눅스에서 프로세스는 보통 다른 프로세스가 fork해서 만든다. 그래서 각 프로세스에는 부모 프로세스가 있다.

1
2
3
4
5
6
7
8
systemd
├── sshd
│   └── ssh session shell
│       └── vim
├── nginx
│   ├── nginx worker
│   └── nginx worker
└── cron

이런 구조를 process tree라고 부른다.

확인할 때는 다음 명령을 쓸 수 있다.

1
2
ps -ef
pstree

현대 리눅스에서는 보통 systemd가 사용자 공간의 가장 위쪽에서 많은 서비스의 조상 역할을 한다.

1
PID 1  systemd

부모 프로세스가 종료되면 자식 프로세스의 처리 방식도 중요해진다. 고아 프로세스는 보통 systemd 같은 상위 프로세스가 거둬 관리하고, 종료된 자식의 상태를 부모가 회수하지 않으면 zombie 프로세스가 잠시 남을 수 있다.

정리하면 다음과 같다.

1
2
3
4
process tree  프로세스의 부모-자식 관계
PID           프로세스 ID
PPID          부모 프로세스 ID
PID 1         시스템의 최상위 사용자 공간 프로세스

Q&A: 시스템 모니터링 (System Monitoring)

질문

시스템의 CPU, 메모리 사용량 등을 어떻게 확인할까?

답변

top - 실시간 시스템 모니터링

1
top
1
2
3
4
5
6
7
8
9
10
top - 10:30:45 up 5 days, 3:21, 1 user, load average: 0.50, 0.45, 0.40
Tasks: 123 total,  2 running, 121 sleeping,  0 stopped,  0 zombie
%Cpu(s):  5.2 us,  2.1 sy,  0.0 ni, 92.7 id,  0.0 wa,  0.0 hi,  0.0 si
MiB Mem :   7956.1 total,  3456.8 free,  2048.5 used,  2450.8 buff/cache
MiB Swap:   2048.0 total,  2048.0 free,     0.0 used.  5200.0 avail Mem

   PID USER   PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
  1234 ubuntu 20   0  456789 128456  45678 S   8.2  1.6   0:15.23 python3
  5678 www-data 20  0  789456 234567  78901 S   5.1  2.9   1:23.45 nginx
  ...

각 항목의 의미:

1
2
3
4
5
6
7
load average   현재, 5분, 15분 평균 로드
%Cpu(s)        CPU 사용률 (us: user, sy: system, id: idle)
Mem            메모리 사용 현황
PID            프로세스 ID
%CPU           CPU 사용률
%MEM           메모리 사용률
COMMAND        명령어

top 명령어 단축키

1
2
3
4
5
6
q           종료
h           도움말
P           CPU로 정렬
M           메모리로 정렬
k           프로세스 종료 (kill)
r           프로세스 우선순위 변경

ps - 현재 프로세스 목록

1
2
3
4
5
6
7
8
# 현재 사용자의 프로세스만 보기
ps

# 모든 프로세스 상세 정보
ps aux

# 특정 프로세스 검색
ps aux | grep nginx

free - 메모리 사용량

1
2
3
4
5
6
7
8
# 기본 보기 (KB 단위)
free

# 사람이 읽기 쉬운 단위 (MB, GB)
free -h

# 1초마다 갱신
free -h -s 1
1
2
3
              total       used       free     shared   buffers    cached
Mem:           7956       2048       3456        512        256        768
Swap:          2048          0       2048

htop - top보다 친화적인 모니터링

1
2
3
4
5
# 설치 (필요한 경우)
sudo apt install htop

# 실행
htop

시스템 부하 확인

1
2
3
4
5
6
7
# 로드 평균 확인
uptime
# 10:30:45 up 5 days, 3:21, 1 user, load average: 0.50, 0.45, 0.40

# /proc/loadavg에서도 확인 가능
cat /proc/loadavg
# 0.50 0.45 0.40 1/123 5678

로드 평균 해석:

  • 1.0 = 1개 CPU를 완전히 사용 (CPU 개수에 따라 다름)
  • 4.0 (4 CPU 서버) = CPU를 완전히 사용 (정상)
  • 8.0 (4 CPU 서버) = CPU 부하 높음 (문제 가능)

Q&A: Job Control & Background Processes

질문

긴 작업을 실행 중인데 중단했다가 다시 실행하고 싶으면 어떻게 할까?

답변

백그라운드에서 프로세스 실행

1
2
3
4
5
6
7
8
# 포그라운드에서 실행 (기본, Ctrl+C로 종료까지)
./long-running-script.sh

# 백그라운드에서 실행 (& 사용)
./long-running-script.sh &

# 출력을 리다이렉션하면서 백그라운드 실행
./long-running-script.sh > output.log 2>&1 &

jobs - 백그라운드 작업 목록

1
2
3
4
5
6
7
# 현재 셸의 백그라운드 작업
jobs

# 출력 예
[1]   Running    ./deploy.sh &
[2]   Stopped    ./backup.sh
[3]   Done       ./cleanup.sh

[숫자]는 job number, 상태는 Running/Stopped/Done 등.

fg - 백그라운드 프로세스를 포그라운드로 가져오기

1
2
3
4
5
6
# 가장 최근 백그라운드 작업을 포그라운드로
fg

# 특정 job number로 가져오기
fg %1   # job 1을 포그라운드로
fg %2   # job 2를 포그라운드로

bg - 중지된 프로세스를 백그라운드에서 계속 실행

1
2
3
# 포그라운드 작업 중단 (Ctrl+Z)
# 프롬프트에서:
bg %1   # job 1을 백그라운드에서 계속 실행

실제 흐름

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 1. 시간이 오래 걸리는 작업 시작
./compile.sh

# 2. 중단 (Ctrl+Z)
# [1]+ Stopped    ./compile.sh

# 3. 다른 작업을 할 수 있음
ls -la
pwd

# 4. 백그라운드에서 계속 실행
bg %1
# [1]+ ./compile.sh &

# 5. 작업 목록 확인
jobs
# [1]+ Running    ./compile.sh &

# 6. 포그라운드로 가져오기
fg %1
# ./compile.sh (작업 진행 상황 보임)

# 7. 완료 또는 Ctrl+C로 종료

disown - 작업 관리에서 제거

1
2
3
4
5
6
7
8
# 백그라운드에서 실행 중인 작업
./long-process.sh &

# jobs에서 제거 (프로세스는 계속 실행)
disown %1

# 셸 종료해도 프로세스는 계속 실행됨
exit

nohup - 연결 끊겨도 실행 계속

1
2
3
4
5
# SSH 접속이 끊겨도 계속 실행
nohup ./deploy.sh > deploy.log 2>&1 &

# nohup.out에 출력 저장됨 (또는 지정한 파일)
tail -f deploy.log

Q&A: Signal & Process Management

질문

실행 중인 프로세스를 어떻게 종료할까? 강제 종료는 어떻게 할까?

답변

kill - 프로세스에 신호 전송

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 프로세스 ID 찾기
ps aux | grep python
# ubuntu  1234  0.5  2.1 456789 128456 ...

# SIGTERM 신호로 종료 (graceful shutdown)
kill 1234

# SIGKILL 신호로 강제 종료
kill -9 1234

# SIGSTOP 신호로 일시 중지
kill -STOP 1234

# SIGCONT 신호로 재시작
kill -CONT 1234

주요 신호들

1
2
3
4
5
SIGHUP (1)      터미널 종료 (설정 파일 재로드)
SIGTERM (15)    정상 종료 (graceful shutdown)
SIGKILL (9)     강제 종료 (차단 불가능)
SIGSTOP (19)    일시 중지
SIGCONT (18)    재시작

pkill - 프로세스 이름으로 종료

1
2
3
4
# 프로세스 이름으로 신호 전송
pkill python      # python 프로세스 종료
pkill -9 nginx    # nginx 강제 종료
pkill -f "node app.js"  # 정확한 명령어로 매칭

killall - 같은 이름의 모든 프로세스 종료

1
2
3
# 같은 이름의 모든 프로세스 종료
killall python
killall -9 java

프로세스 상태 확인 후 종료

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/bin/bash

# 프로세스가 실행 중인지 확인
if pgrep -x "myapp" > /dev/null; then
    echo "myapp이 실행 중입니다"
    kill $(pgrep -x "myapp")
    sleep 2
    
    # 여전히 실행 중이면 강제 종료
    if pgrep -x "myapp" > /dev/null; then
        echo "강제 종료 중..."
        kill -9 $(pgrep -x "myapp")
    fi
else
    echo "myapp이 실행 중이 아닙니다"
fi

실제 사용 예

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 1. Nginx 재시작
sudo systemctl stop nginx    # graceful
sudo systemctl start nginx

# 2. 응답 없는 프로세스 강제 종료
kill -9 12345

# 3. 개발 중 이전 서버 종료 후 재실행
pkill -f "node server.js"
node server.js &

# 4. 배포 전 이전 버전 종료
pkill -f "python app.py"
wait    # 모든 백그라운드 작업 대기
This post is licensed under CC BY 4.0 by the author.