서비스 · 프로세스 관리 09 / 50 · Part 1. 프로세스 기초
실습 환경: Rocky Linux 9.8 · Ubuntu 24.04.5 (systemd로 부팅한 Docker 격리 컨테이너, 테스트 계정 analyst)

1. 들어가며

백업이나 로그 압축처럼 CPU를 많이 쓰지만 급하지 않은 작업이 웹 서비스와 같은 서버에서 돌면 서비스 응답이 느려진다. 이럴 때 쓰는 가장 간단한 도구가 nice 값 이다. nice는 "이 프로세스는 CPU를 다른 프로세스에게 양보해도 된다"는 표시다.

이번 글에서는 nice 값의 범위와 권한 규칙을 확인하고, 같은 CPU 코어에서 nice 0과 nice 19를 경쟁시켜 실제 배분이 어떻게 달라지는지 측정한다.


2. 핵심 개념

2-1. nice 값

항목내용
범위-20 (가장 우선) ~ +19 (가장 양보), 기본값 0
이름의 의미값이 클수록 다른 프로세스에게 "친절(nice)"하다 = 덜 받는다
적용 대상일반 스케줄링 정책(SCHED_OTHER, ps에서 TS) 프로세스
상속fork한 자식은 부모의 nice 값을 물려받는다

2-2. 권한 규칙

작업일반 사용자root (CAP_SYS_NICE)
자기 프로세스 nice를 올리기 (0 → 10)가능가능
자기 프로세스 nice를 내리기 (10 → 5)불가가능
음수 nice 설정불가가능
다른 사용자의 프로세스 변경불가가능

일반 사용자가 한 번 양보한 CPU를 되찾지 못하게 한 이유는, 모든 사용자가 자기 작업을 최우선으로 올리는 경쟁을 막기 위해서다. 예외적으로 /etc/security/limits.conf의 priority/nice 항목으로 허용 범위를 줄 수 있다.

2-3. 명령어

명령어용도
nice현재 nice 값 출력
nice -n 10 CMDnice 10으로 새로 실행
renice -n 15 -p PID실행 중인 프로세스 변경 (-u USER, -g PGID도 가능)
ps -o ni,pri / top의 NI, PR확인

3. 동작 원리

nice 값과 CPU 배분 — CFS 가중치 방식

Linux의 일반 스케줄러(CFS, 6.6 이후 커널은 EEVDF)는 nice 값을 가중치(weight) 로 바꾼다. nice 한 단계마다 약 1.25배 차이가 나며, nice 0은 1024, nice 19는 15다. 같은 코어에서 경쟁하면 가중치 비율대로 CPU 시간을 나눈다.

nice 0  : 가중치 1024 ─┐
                       ├─ 1024 / (1024 + 15) ≈ 98.6 %
nice 19 : 가중치   15 ─┘      15 / (1024 + 15) ≈  1.4 %

중요한 점은 nice가 CPU를 두고 경쟁할 때만 의미가 있다는 것이다. 코어가 남아 있으면 nice 19 프로세스도 CPU를 100% 쓸 수 있다. 실습에서 taskset -c 0으로 두 프로세스를 같은 코어에 고정 한 이유다.

ps의 PRI와 top의 PR은 계산 방식이 다르다. top의 PR은 20 + nice(nice 0 → 20), ps의 pri 열은 반대 방향 숫자(nice 10 → 9)를 보여 준다. 비교할 때는 NI 열 을 기준으로 한다.


4. 명령어 실습

# 1) 일반 사용자 (analyst)
nice                                    # 현재 값
nice -n 10 sleep 100 &                  # nice 10으로 실행
ps -o pid,ni,pri,stat,cmd -p $!
nice -n -5 sleep 1                      # 음수 → 실패
renice -n 15 -p $(jobs -p %1)           # 10 → 15 (올리기) 성공
renice -n 5  -p $(jobs -p %1)           # 15 → 5 (내리기) 실패

# 2) root: 같은 코어(CPU 0)에서 경쟁
taskset -c 0 timeout 12 sh -c 'while :; do :; done' &
taskset -c 0 nice -n 19 timeout 12 sh -c 'while :; do :; done' &
sleep 8; ps -o pid,ni,psr,%cpu,time,cmd -C sh --sort=ni
renice -n -5 -p $(pgrep -f 'while' | head -1)

# 3) (Ubuntu) 서비스의 nice 값
ps -eo pid,ni,pri,cls,comm --sort=ni | head -6
systemctl show systemd-journald -p Nice

5. 실행 결과

실제 실행 결과 — Rocky Linux 9.8 · analyst@rocky9-lab — 일반 사용자의 nice / renice 범위

실제 실행 결과 — Rocky Linux 9.8 · root@rocky9-lab — 같은 CPU에서 nice 0 vs nice 19 경쟁

실제 실행 결과 — Ubuntu 24.04.5 · root@ubuntu-lab — 서비스의 nice 값 확인

텍스트 원본(실제 출력):

[analyst@rocky9-lab ~]$ nice
0
[analyst@rocky9-lab ~]$ nice -n 10 sleep 100 & sleep 0.2; ps -o pid,ni,pri,stat,cmd -p $!
    PID  NI PRI STAT CMD
    527  10   9 SN+  sleep 100
[analyst@rocky9-lab ~]$ nice -n -5 sleep 1
nice: cannot set niceness: Permission denied
[analyst@rocky9-lab ~]$ renice -n 15 -p $(jobs -p %1)
527 (process ID) old priority 10, new priority 15
[analyst@rocky9-lab ~]$ renice -n 5 -p $(jobs -p %1)
renice: failed to set priority for 527 (process ID): Permission denied
[analyst@rocky9-lab ~]$ kill %1
[root@rocky9-lab ~]# taskset -c 0 timeout 12 sh -c 'while :; do :; done' &
[root@rocky9-lab ~]# taskset -c 0 nice -n 19 timeout 12 sh -c 'while :; do :; done' &
[root@rocky9-lab ~]# sleep 8; ps -o pid,ni,psr,%cpu,time,cmd -C sh --sort=ni
    PID  NI PSR %CPU     TIME CMD
    583   0   0 97.6 00:00:07 sh -c while :; do :; done
    584  19   0  1.3 00:00:00 sh -c while :; do :; done
[root@rocky9-lab ~]# renice -n -5 -p $(pgrep -f 'while' | head -1) >/dev/null; ps -o pid,ni,pri,cmd -p $(pgrep -f 'while' | head -1)
    PID  NI PRI CMD
    580  -5  24 timeout 12 sh -c while :; do :; done
[root@rocky9-lab ~]# wait 2>/dev/null; true
root@ubuntu-lab:~# ps -eo pid,ni,pri,cls,comm --sort=ni | head -6
    PID  NI PRI CLS COMMAND
     25  -1  20  TS systemd-journal
      1   0  19  TS systemd
     67   0  19  TS systemd-resolve
     80   0  19  TS cron
     81   0  19  TS dbus-daemon
root@ubuntu-lab:~# systemctl show systemd-journald -p Nice
Nice=-1

6. 결과 해석

관찰의미
nice → 0로그인 셸의 기본값
NI 10, STAT SN+nice 10으로 실행되었고, 04편의 N(낮은 우선순위) 플래그가 붙었다
nice -n -5 → Permission denied일반 사용자는 음수를 설정할 수 없다
old priority 10, new priority 15양보를 늘리는 방향은 허용된다
15 → 5 Permission denied한 번 올린 값을 되돌리는 것은 root만 가능하다
PSR 0 두 프로세스, %CPU 97.6 vs 1.3같은 코어에서 nice 0이 거의 모든 시간을 가져갔다. 이론값(98.6 : 1.4)과 거의 같다
TIME 00:00:07 vs 00:00:008초 동안의 누적 CPU 시간 차이. nice 19 쪽은 1초도 받지 못했다
renice 결과가 timeout 12 sh -c ... (PID 580)pgrep -f 'while'이 timeout 래퍼 프로세스까지 매칭해 엉뚱한 PID를 바꿨다. 실제 루프(sh)는 그대로다
Ubuntu journald NI -1, Nice=-1서비스 우선순위는 unit 파일의 Nice=로 설정된다. 로그 수집이 밀리지 않도록 한 기본 설정이다
CLS TS스케줄링 클래스 SCHED_OTHER(Time Sharing). nice가 적용되는 일반 정책

renice 결과의 교훈은 12편에서 다시 다룬다. pgrep -f는 명령 인자 전체를 검색하므로, 대상 인자를 포함한 다른 프로세스까지 매칭 될 수 있다. 조치 전에는 항상 pgrep -a로 먼저 확인한다.


7. 보안 관점

주제내용
마이너의 위장일부 크립토마이너는 nice 19로 실행 해 서비스 영향(응답 지연)을 줄이고 발각을 늦춘다. top의 ni 항목이 계속 높다면 낮은 우선순위의 CPU 과다 사용을 의심한다
권한 상승 흔적일반 계정 프로세스의 nice가 음수 라면 root 권한으로 설정된 것이다. 누가 설정했는지 확인한다
보안 에이전트 보호EDR·로그 수집기는 부하 상황에서도 밀리지 않도록 음수 nice 또는 높은 CPUWeight=를 준다
DoS 완화사용자 작업 부하로 관리 접속(SSH)까지 느려지는 상황을 줄이려면 사용자 배치 작업에 nice·cgroup 제한을 건다 (18편)

8. 보안관제 관점

[Detection]  top: %Cpu 의 ni 항목 97% 지속 (us 는 낮음)
     ↓
[확인]       ps -eo pid,ni,user,%cpu,lstart,args --sort=-%cpu | awk '$2 > 0' | head
     ↓
[판단]       nice 19 로 실행 중인 알 수 없는 프로세스가 CPU 대부분 사용
             → 백업 등 정상 배치 작업인지, 채굴 등 악성인지 확인
     ↓
[Evidence]   /proc/PID/exe, cmdline(풀 주소·지갑 인자), 네트워크 연결
     ↓
[Response]   정상 작업이면 스케줄 조정 / 악성이면 수집 후 종료
확인 명령목적
ps -eo ni,comm \| sort -n \| uniq -cnice 값 분포
ps -eo pid,ni,user,args \| awk '$2 < 0'음수 nice 프로세스 (root가 설정)
systemctl show SERVICE -p Nice,CPUWeight서비스 설정 확인

9. 실무에서 자주 발생하는 실수

실수결과예방
nice 19면 CPU를 거의 안 쓴다고 생각코어가 남으면 100%도 쓴다nice는 경쟁 시 비율 이다. 절대 제한은 cgroup CPUQuota=
일반 계정으로 renice 되돌리기 시도Permission deniedroot 또는 처음부터 적절한 값으로 실행
pgrep -f로 찾은 PID에 바로 renice/kill래퍼·다른 프로세스까지 영향pgrep -a로 확인 후 적용
ps PRI와 top PR을 같은 값으로 비교해석 혼란NI 열 기준
I/O가 많은 작업에 nice만 적용디스크 경합은 그대로ionice -c3 병행

10. 실습 체크리스트

[ ] nice -n 10 으로 실행하고 NI, STAT N 을 확인했다
[ ] 일반 사용자가 음수 nice 와 값 되돌리기에 실패하는 것을 확인했다
[ ] taskset 으로 같은 코어에서 nice 0 과 19 를 경쟁시켰다
[ ] 측정 CPU 비율을 가중치 이론값과 비교했다
[ ] pgrep -f 가 래퍼 프로세스까지 매칭하는 문제를 확인했다
[ ] systemd 서비스의 Nice= 설정을 확인했다

11. 핵심 정리

  • nice는 -20(우선) ~ +19(양보), 기본 0이며, CPU를 경쟁할 때의 배분 비율 을 정한다.
  • 일반 사용자는 nice를 올리기만 할 수 있고, 음수 설정과 되돌리기는 root만 가능하다.
  • nice 0 : nice 19 = 가중치 1024 : 15 → 실측 97.6% : 1.3%.
  • 절대적인 CPU 제한이 필요하면 nice가 아니라 cgroup(CPUQuota=)을 쓴다.
  • 관제에서는 ni CPU 사용률과 음수 nice 프로세스를 이상 징후로 확인한다.

12. 다음 편 예고

다음 글 「10. 포그라운드·백그라운드와 Job Control」 에서는 &, jobs, bg, fg, Ctrl+Z의 동작을 프로세스 그룹과 함께 이해하고, 로그아웃 후에도 살아남는 작업(nohup, setsid, disown)의 차이를 실제 로그아웃으로 확인한다.


참고 자료


시리즈 이동

profile
코드에 숨겨진 위협을 읽고 AI로 보안의 미래를 설계합니다. 프론트엔드 개발 경험을 자산 삼아 더 견고하고 지능적인 보안 운영 시스템을 구축해 나가는 과정을 기록합니다

0개의 댓글