# Linux htop/top 화면에 보이는 값들 해설 (2019)

> Clean Markdown view of GeekNews topic #31136. Use the original source for factual precision when an external source URL is present.

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=31136](https://news.hada.io/topic?id=31136)
- GeekNews Markdown: [https://news.hada.io/topic/31136.md](https://news.hada.io/topic/31136.md)
- Type: GN+
- Author: [neo](https://news.hada.io/@neo)
- Published: 2026-07-05T09:49:42+09:00
- Updated: 2026-07-05T09:49:42+09:00
- Original source: [peteris.rocks](https://peteris.rocks/blog/htop/)
- Points: 1
- Comments: 1

## Topic Body

- Ubuntu Server 16.04 x64의 **htop 화면**을 출발점으로 uptime, load average, Tasks, PID, 프로세스 트리, 상태, CPU 시간, 우선순위, 메모리 지표가 실제로 무엇을 뜻하는지 `/proc`와 명령어 출력으로 추적함
- 화면의 많은 값은 **procfs**와 `/etc/passwd`, `/etc/group`, `/etc/shadow`, `/etc/nsswitch.conf` 같은 시스템 파일에서 오며, `strace`로 프로그램이 어떤 파일을 읽는지 확인할 수 있음
- **Load average**는 CPU 사용률과 같은 값이 아니며, 실행 중·실행 대기 중인 프로세스와 uninterruptible 상태 프로세스를 포함한 지수 감쇠 이동평균임
- `R`, `S`, `D`, `Z`, `T`, `t` 같은 상태 코드는 signal, `kill`, `fork`/`exec`/`wait` 동작과 연결되어 있어 프로세스가 왜 멈추거나 남아 있는지 판단하는 단서가 됨
- `VIRT`, `RES`, `SHR`, `MEM%`는 **가상 메모리**, 물리 메모리, 공유 가능 메모리를 서로 다른 관점에서 보여주므로 한 숫자만 보고 실제 메모리 사용량을 단정하기 어려움

---

### htop 값은 어디서 오는가
- `uptime`은 시스템이 얼마나 오래 실행됐는지 보여주며, 같은 정보는 `uptime` 명령으로도 확인할 수 있음
- `uptime` 프로그램은 `/proc/uptime`을 읽음
  - 첫 번째 숫자는 시스템이 켜져 있던 전체 초 단위 시간
  - 두 번째 숫자는 시스템이 idle 상태였던 초 단위 시간
  - 멀티코어 시스템에서는 idle 시간이 코어별로 합산되어 전체 uptime보다 클 수 있음
- `strace uptime 2>&1 | grep open` 또는 `strace -e open uptime`으로 `uptime`이 여는 파일을 볼 수 있음
  - 예시 출력에는 `/proc/uptime`, `/var/run/utmp`, `/proc/loadavg`가 포함됨
- `/proc/uptime`의 숫자는 프로그램이나 스크립트에서 쓰기 좋고, `uptime` 출력은 사람이 읽기 좋게 포맷됨

### Load average와 CPU 사용률
- `/proc/loadavg`의 첫 세 값은 최근 **1분, 5분, 15분**의 시스템 load average를 나타냄
- 네 번째 값은 현재 실행 중인 프로세스 수와 전체 프로세스 수를 `1/120`처럼 보여주고, 마지막 값은 마지막으로 사용된 PID임
- 새 프로세스를 실행하면 PID가 할당되며, PID는 보통 증가하다가 고갈되면 재사용됨
  - PID 1은 부팅 시 시작되는 `/sbin/init`에 속함
- `htop`에서 실행 중인 프로세스가 하나만 보이면 그 하나가 `htop` 자체일 수 있음
- `sleep 30`은 실행 중이 아니라 sleep 상태라 running process 수를 늘리지 않음
- `cat /dev/urandom > /dev/null`처럼 계속 CPU를 쓰는 작업은 running process 수와 load average를 올림
- **Load number**는 실행 중이거나 실행 대기 중인 프로세스와 uninterruptible 상태 프로세스를 세는 값임
- load average는 단순 평균이 아니라 **지수 감쇠 이동평균**임
  - 1분 load average도 마지막 60초만 반영하지 않고, 최근 1분에 더 큰 비중을 두면서 이전 활동도 일부 포함함
- 단일 CPU 시스템에서 CPU-bound 프로세스 하나가 있으면 load average `1.00`은 CPU 100% 사용으로 단순화해 볼 수 있음
  - 2코어 시스템에서 같은 상황은 CPU 사용률 50%로 볼 수 있음
  - 2코어 시스템의 CPU 100% 사용에 해당하는 load average는 `2.00`으로 단순화할 수 있음
- 이 단순화는 uninterruptible 상태 프로세스가 load에 포함되기 때문에 항상 맞지는 않음
  - 높은 load average인데 CPU 사용률은 높지 않은 상황도 가능함
- 순간적인 CPU 사용률은 `mpstat`로 확인할 수 있음
  - `sudo apt install sysstat -y`
  - `mpstat 1`

### Tasks, PID, 프로세스 트리
- `htop` 오른쪽 위의 **Tasks**는 전체 프로세스 수와 실행 중인 프로세스 수를 보여줌
- Linux 커널은 내부적으로 프로세스를 task라고 부르며, `htop`은 화면 공간을 줄이기 위해 Processes 대신 Tasks를 사용함
- `Shift`+`H`로 thread 표시를 토글할 수 있음
  - `Tasks: 23, 10 thr`처럼 보이면 thread가 표시 중임
- `Shift`+`K`로 kernel thread 표시를 토글할 수 있음
  - `Tasks: 23, 40 kthr`처럼 보이면 kernel thread가 표시 중임
- 새 프로세스가 시작될 때마다 **PID**가 할당됨
  - `sleep 1000 &`처럼 백그라운드 실행하면 job 번호와 PID가 표시됨
  - `bash`의 `$!`는 마지막 백그라운드 프로세스 ID로 확장됨
- 프로세스 관련 정보는 `/proc/&lt;pid&gt;/` 아래에 있음
  - `/proc/&lt;pid&gt;/cmdline`은 실행 명령을 담고 있으며 인자는 `\0` 바이트로 구분됨
  - `tr '\0' '\n' < /proc/&lt;pid&gt;/cmdline` 또는 `strings /proc/&lt;pid&gt;/cmdline`로 읽기 쉽게 볼 수 있음
  - `/proc/&lt;pid&gt;/cwd`는 현재 작업 디렉터리 링크이고, `/proc/&lt;pid&gt;/exe`는 실행된 바이너리 링크임
- `htop`, `top`, `ps` 같은 진단 도구는 프로세스 세부 정보를 `/proc/&lt;pid&gt;/&lt;file&gt;`에서 읽음
- 새 프로세스를 만든 쪽은 parent process, 새로 만들어진 쪽은 child process이며 이 관계가 프로세스 트리를 이룸
- `htop`에서 `F5`를 누르면 프로세스 계층을 볼 수 있음
  - `ps f`와 `pstree -a`도 같은 관계를 보여줌
- `bash`에서 `date`를 실행하면 `bash`가 `fork`로 자기 복사본을 만들고, `exec`로 `/bin/date`를 메모리에 올린 뒤, parent인 `bash`가 child 종료를 기다림
- `/sbin/init`은 부팅 때 시작되고 `sshd`를 띄우며, SSH 접속 시 `sshd`가 세션 프로세스를 만들고 그 세션이 `bash` shell을 실행함

### 프로세스 사용자와 권한
- 각 프로세스는 사용자에게 소유되며, 사용자는 숫자 ID로 표현됨
- `/proc/&lt;pid&gt;/status`의 `Uid` 항목으로 프로세스의 사용자 ID를 확인할 수 있음
- `id 1000` 같은 명령은 숫자 ID에 해당하는 사용자 이름과 그룹을 보여줌
- `id`는 `/etc/nsswitch.conf` 설정에 따라 이름 해석 소스를 선택함
  - 예시 시스템에서는 `/etc/passwd`와 `/etc/group`을 읽음
  - `compat`은 Compatibility mode이며, `files`와 같지만 특수 항목을 허용함
  - 사용자 정보는 LDAP 같은 다른 데이터베이스나 서비스에도 저장될 수 있음
- `/etc/passwd`와 `/etc/group`은 숫자 ID를 사람이 읽을 수 있는 이름으로 매핑하는 평문 파일임
- 실제 비밀번호 정보는 `/etc/shadow`에 있음
  - `$6$`은 `sha512` 해싱 알고리듬을 뜻함
  - 그 뒤에는 rainbow table 공격을 막기 위한 랜덤 salt와 password+salt의 hash가 이어짐
- 프로그램은 기본적으로 실행한 사용자 권한으로 실행됨
  - 실행 파일 소유자가 다른 사용자여도 동일함
- 다른 사용자나 `root`로 실행하려면 `sudo`를 사용함
  - `sudo id`는 `root`의 UID 0으로 실행됨
  - `sudo -u daemon id`처럼 특정 사용자로 실행할 수 있음
- `/etc/sudoers`에 직접 redirect로 쓰려 하면 `echo`만 root로 실행되고 append는 현재 사용자로 수행되어 실패할 수 있음
  - `echo "$USER ALL=(ALL) NOPASSWD: ALL" | sudo tee -a /etc/sudoers`
  - `sudo bash -c "echo '$USER ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers"`
- `/etc/sudoers`는 `sudo visudo`로 편집해야 함
  - 저장 전 내용을 검증해 `sudo`를 사용할 수 없는 상태가 되는 실수를 막음
- `/usr/bin/passwd`는 일반 사용자가 실행해도 `/etc/shadow`에 쓸 수 있음
  - 파일 권한에 `s`가 있어 **setuid** 실행 파일로 동작함
  - 실행 파일 소유자인 `root` 권한으로 실행됨
  - root 소유 setuid 실행 파일은 `find /bin -user root -perm -u+s`로 찾을 수 있음

### 프로세스 상태 코드
- `htop`의 상태 열은 `S`라는 이름으로 표시되며, 주요 값은 다음과 같음
  - `R`: running 또는 runnable, 실행 중이거나 run queue에서 대기 중
  - `S`: interruptible sleep, 이벤트 완료를 기다림
  - `D`: uninterruptible sleep, 보통 I/O 대기
  - `Z`: defunct zombie, 종료됐지만 parent가 reap하지 않음
  - `T`: job control signal로 정지
  - `t`: tracing 중 debugger에 의해 정지
  - `X`: dead, 보여서는 안 되는 상태
- `ps`는 `Ss`, `R+`, `Ss+` 같은 substate도 보여줌
- ## R: 실행 중 또는 실행 가능
  - `R` 상태는 프로세스가 현재 실행 중이거나 실행 대기열에서 기다리는 상태임
  - 프로그램 소스 코드는 컴파일 후 CPU 명령어가 되고, 실행 시 메모리에 로드되어 CPU가 해당 명령을 실행함
  - 실행 중이라는 것은 CPU가 물리적으로 명령어를 실행한다는 뜻임
- ## S: 인터럽트 가능한 sleep
  - `S` 상태에서는 프로세스의 명령어가 CPU에서 실행되지 않고, 이벤트나 조건을 기다림
  - 이벤트가 발생하면 커널이 상태를 running으로 바꿈
  - `sleep 1000`은 지정한 시간 동안 대기하는 예시임
  - 이 상태는 signal로 interrupt할 수 있음
  - `htop`에서는 `F9`를 눌러 signal을 보낼 수 있음
  - `kill`은 signal을 보내는 시스템 호출이며, `/bin/kill`은 userland에서 이를 호출하는 프로그램임
  - 기본 signal은 `TERM`이며 프로세스 종료를 요청함
  - signal은 숫자이며 이름은 보통 대문자로 쓰고 `SIG` prefix가 붙을 수 있음
  - 예: `INT`, `KILL`, `STOP`, `CONT`, `HUP`
  - `kill -INT 10089`, `kill -2 10089`, `/bin/kill -2 10089`는 같은 동작을 함
  - `CTRL`+`C`를 누르면 `bash`가 foreground process에 `SIGINT`를 보냄
  - `SIGINT`나 `SIGTERM`을 보낸다고 프로세스가 반드시 종료되지는 않음
  - 프로그램은 signal handler를 설정해 정리 작업 후 종료하는 식으로 처리할 수 있음
  - `SIGKILL` 또는 `9`는 커널이 프로세스에 응답 기회를 주지 않고 강제 종료하게 함
- ## D: 인터럽트 불가능한 sleep
  - `D` 상태는 signal로 깨울 수 없으며, `SIGKILL`도 signal이기 때문에 이런 프로세스를 kill할 수 없음
  - 이 상태는 프로세스가 중단 없이 기다려야 하거나 이벤트가 빠르게 발생할 것으로 예상될 때 사용됨
  - 예: disk read/write
  - uninterruptible process는 보통 page fault 이후 I/O를 기다리는 상태일 수 있음
  - NFS 읽기·쓰기 지연에서 이런 상태가 생길 수 있음
  - 사용 가능한 메모리가 너무 적어 프로세스가 swap을 많이 하는 상황에서도 나타날 수 있음
  - 예시로 `sudo mount 8.8.8.8:/tmp /tmp &`를 실행하면 `/sbin/mount.nfs`가 `D` 상태가 됨
  - `strace`로 보면 `mount` 시스템 호출이 프로세스를 block함
  - `mount`에 `intr` 옵션을 주면 interruptible하게 실행할 수 있음
  - `sudo mount 8.8.8.8:/tmp /tmp -o intr`
- ## Z: 좀비 프로세스
  - `Z` 상태는 프로세스가 종료됐지만 parent가 아직 reap하지 않은 상태임
  - 좀비 프로세스는 짧게 존재하면 정상적일 수 있음
  - 오래 남아 있는 좀비 프로세스는 프로그램 버그를 나타낼 수 있음
  - 좀비 프로세스는 메모리를 소비하지 않고 PID만 차지함
  - 좀비 프로세스 자체는 `kill`할 수 없음
  - parent process에 `SIGCHLD`를 보내 좀비를 reap하라고 요청할 수 있음
  - parent process를 kill하면 parent와 그 좀비를 제거할 수 있음
  - `fork` 후 child가 `exit(0)`하고 parent가 `sleep(20)`하는 C 프로그램으로 좀비 상태를 재현할 수 있음
  - parent가 끝나면 좀비는 사라짐
  - 좀비가 유지되는 이유는 parent가 `wait` 시스템 호출로 child의 exit code를 확인할 수 있어야 하기 때문임
- ## T와 t: 정지된 프로세스
  - `T` 상태는 job control signal로 정지된 상태임
  - `cat /dev/urandom > /dev/null` 실행 중 `CTRL`+`Z`를 누르면 `T` 상태가 됨
  - `fg`로 다시 실행할 수 있음
  - `STOP` signal로 멈추고 `CONT` signal로 재개할 수도 있음
  - `t` 상태는 debugger가 tracing하는 동안 정지된 상태임
  - `nc -l 1234 &`로 실행한 프로세스에 `sudo gdb -p &lt;pid&gt;`로 attach하면 `t` 상태가 됨

### CPU 시간, niceness, priority
- Linux는 multitasking 운영체제라 단일 CPU에서도 여러 프로세스가 동시에 실행되는 것처럼 보임
- 실제로 단일 CPU는 한 번에 하나의 명령만 실행할 수 있으므로 **time sharing**을 사용함
  - 한 프로세스가 잠깐 실행되고 중단됨
  - 실행 대기 중인 다른 프로세스가 차례로 실행됨
  - 한 프로세스가 실행되는 짧은 구간을 time slice라고 함
- time slice는 보통 몇 밀리초라 시스템 load가 높지 않으면 잘 느껴지지 않음
- 단일 코어에서 load average가 `1.0`이면 CPU가 100% 사용됐다고 볼 수 있음
  - `1.0`보다 높으면 실행하려는 프로세스 수가 CPU가 처리할 수 있는 수보다 많아 slowdown이나 delay가 생길 수 있음
  - `1.0`보다 낮으면 CPU가 때때로 idle 상태임
- 프로세스 running time이 실제 경과 시간과 정확히 같지 않을 수 있는 이유도 time sharing으로 설명됨
- 사용 가능한 CPU core 수보다 실행할 task가 많으면 어떤 task를 먼저 실행할지 정해야 함
- Linux 커널의 scheduler는 run queue에서 다음 프로세스를 고르며, 커널의 scheduler 알고리듬에 의존함
- 일반적으로 scheduler를 직접 제어할 수는 없지만, 어떤 프로세스가 더 중요한지 알려줄 수 있음
- `NI`로 표시되는 **niceness**는 user-space priority임
  - 범위는 `-20`부터 `19`까지
  - `-20`이 가장 높은 우선순위이고 `19`가 가장 낮은 우선순위임
  - 더 nice한 프로세스는 덜 nice한 프로세스에 더 양보한다고 볼 수 있음
- `PRI`는 Linux 커널이 사용하는 kernel-space priority임
  - 범위는 `0`부터 `139`
  - `0~99`는 real time, `100~139`는 user용 범위임
- nice 값과 priority의 관계는 `PR = 20 + NI`로 설명됨
  - `NI`의 `-20~+19`가 `PR`의 `0~39`가 되고, 이는 `100~139`에 매핑됨
- 실행 전 niceness는 `nice -n niceness program`으로 설정함
- 실행 중인 프로세스 niceness는 `renice -n niceness -p PID`로 바꿈
- CPU 사용률 색상은 다음과 같음
  - Blue: 낮은 우선순위 thread, `nice > 0`
  - Green: 일반 우선순위 thread
  - Red: kernel thread

### 메모리 지표: VIRT, RES, SHR, MEM%
- 프로세스는 자신이 메모리에 단독으로 존재하는 것처럼 보이며, 이는 **가상 메모리**로 구현됨
- 프로세스는 물리 메모리에 직접 접근하지 않고 자체 virtual address space를 가짐
- 커널은 virtual memory address를 physical memory로 변환하거나 일부를 disk에 매핑할 수 있음
- 이 때문에 프로세스가 컴퓨터에 설치된 메모리보다 더 많은 메모리를 쓰는 것처럼 보일 수 있음
- 프로세스 메모리 사용량은 다음 항목을 포함하는지에 따라 달라짐
  - shared library
  - disk-mapped memory
  - swapped out memory
- 메모리 사용량 색상은 다음과 같음
  - Green: used memory
  - Blue: buffers
  - Orange: cache
- ## VIRT/VSZ
  - `VIRT`는 task가 사용하는 전체 **virtual memory** 양임
  - code, data, shared library, swapped out page, mapped됐지만 사용되지 않은 page를 포함함
  - 애플리케이션이 1GB를 요청하고 1MB만 사용해도 `VIRT`는 1GB로 나올 수 있음
  - 1GB 파일을 `mmap`하고 실제 사용하지 않아도 `VIRT`는 1GB로 표시될 수 있음
  - 대부분의 경우 `VIRT`는 유용한 숫자가 아님
- ## RES/RSS
  - `RES`는 swapped out되지 않은 physical memory, 즉 현재 물리 메모리에 있는 resident memory 사용량임
  - `RES`는 `VIRT`보다 실제 메모리 사용량을 더 잘 나타낼 수 있지만 한계가 있음
  - swapped out memory를 포함하지 않음
  - 일부 메모리는 다른 프로세스와 공유될 수 있음
  - 프로세스가 1GB 메모리를 사용한 뒤 `fork()`하면 두 프로세스의 `RES`가 각각 1GB로 보일 수 있지만, Linux의 copy-on-write 때문에 실제로는 1GB만 사용될 수 있음
- ## SHR
  - `SHR`은 task가 사용하는 shared memory 양임
  - 다른 프로세스와 잠재적으로 공유될 수 있는 메모리를 반영함
  - 예시 C 프로그램은 `malloc`, 일부 메모리 사용, `fork`, 추가 메모리 쓰기를 거치며 `VIRT`, `RES`, `SHR` 값이 어떻게 달라지는지 보여줌
  - 해당 메모리 예제 섹션은 TODO로 남아 있음
- ## MEM%
  - `MEM%`는 task가 현재 사용하는 available physical memory의 비율임
  - `RES`를 전체 RAM으로 나눈 값임
  - 예: `RES`가 `400M`이고 RAM이 8GB이면 `400/8192*100 = 4.88%`

### Ubuntu Server 16.04 기본 프로세스들
- fresh Digital Ocean droplet의 Ubuntu Server 16.04.1 LTS x64에서 시작되는 프로세스들을 조사함
- ## `/sbin/init`
  - `/sbin/init`은 boot process의 나머지를 조정하고 사용자 환경을 구성함
  - 자동으로 시작되는 프로세스들의 parent 또는 grandparent가 됨
  - `dpkg -S /sbin/init` 결과 `systemd-sysv: /sbin/init`으로, 해당 시스템에서는 systemd임
  - kill해도 아무 일도 일어나지 않음
- ## `/lib/systemd/systemd-journald`
  - `systemd-journald`는 logging data를 수집하고 저장하는 system service임
  - 여러 source에서 받은 로그 정보를 기반으로 structured, indexed journal을 만들고 유지함
  - 단순한 평문 로그 파일 대신 로그 메시지에 최적화된 특수 파일 형식을 사용함
  - `journalctl`로 조회함
  - `journalctl _COMM=sshd`
  - `journalctl _COMM=sshd -o json-pretty`
  - `journalctl --since yesterday`
  - `journalctl -b`
  - `journalctl -f`
  - `journalctl --disk-usage`
  - `journalctl --vacuum-size=1G`
  - 제거하거나 비활성화할 수는 없어 보이며, logging을 끌 수만 있음
- ## `/sbin/lvmetad -f`
  - `lvmetad`는 LVM metadata를 cache해서 LVM 명령이 disk scan 없이 metadata를 읽게 함
  - disk scan은 시간이 걸리고 시스템과 disk의 일반 작업을 방해할 수 있음
  - LVM은 Linux가 실행 중일 때 logical volume을 만들고, resize하고, 삭제할 수 있는 “dynamic partitions”로 볼 수 있음
  - LVM을 사용 중이라면 유지해야 할 것으로 정리됨
- ## `/lib/systemd/udevd`
  - `systemd-udevd`는 kernel uevent를 듣고, 각 event에 대해 udev rules의 matching instruction을 실행함
  - udev는 Linux kernel의 device manager이며 `/dev` directory의 device node를 주로 관리함
  - virtual server에서 필요한지는 확신하지 못함
- ## `/lib/systemd/timesyncd`
  - `systemd-timesyncd`는 remote NTP server와 local system clock을 동기화하는 system service임
  - `ntpd`를 대체함
  - 예시 시스템에서는 `timedatectl status`가 network time과 NTP synchronized를 `yes`로 보여줌
  - `netstat` 출력에서는 SSH port만 listening 상태로 보이며, Ubuntu 14.04의 `ntpd`처럼 여러 UDP 123 port를 열지 않음
- ## `/usr/sbin/atd -f`
  - `atd`는 나중에 실행하도록 queue에 넣은 job을 실행함
  - `at`과 `batch`는 stdin 또는 파일에서 명령을 읽어 나중에 실행함
  - 반복 실행을 예약하는 cron과 달리 `at`은 특정 시간에 한 번 실행함
  - 예시에서는 `echo "touch /tmp/yolo.txt" | at now + 1 minute`로 1분 뒤 파일을 생성함
  - 사용하지 않으면 `sudo apt remove at -y --purge`로 제거함
- ## `/usr/lib/snapd/snapd`
  - Snappy Ubuntu Core는 transactional update를 사용하는 Ubuntu rendition으로 소개됨
  - snap은 하나의 binary package가 Linux desktop, server, cloud, device에서 동작하도록 하는 universal Linux package format으로 설명됨
  - dependency를 single snap에 묶어 배포하는 simplified deb package처럼 이해됨
  - 서버에서 snappy로 애플리케이션을 deploy하거나 distribute해 본 적이 없어 `sudo apt remove snapd -y --purge`로 제거함
- ## `/usr/bin/dbus-daemon`
  - D-Bus는 같은 machine에서 동시에 실행되는 여러 process 사이의 IPC와 RPC mechanism임
  - desktop environment에는 필요하지만 web app을 실행하는 server에서는 필요한지 의문을 가짐
  - `dbus`를 제거하자 `timedatectl status`가 `Failed to create bus connection: No such file or directory`로 실패함
  - 그래서 keep하는 편이 좋다고 정리됨
- ## `/lib/systemd/systemd-logind`
  - `systemd-logind`는 user login을 관리하는 system service임
- ## `/usr/sbin/cron -f`
  - `cron`은 scheduled command를 실행하는 daemon임
  - `-f`는 foreground mode로 daemonize하지 않음을 뜻함
  - 주기적으로 실행할 작업은 cron으로 예약할 수 있음
  - `crontab -e`
  - Ubuntu에서는 `/etc/cron.hourly`, `/etc/cron.daily` 등을 사용하는 편이라고 정리됨
  - 로그는 다음 방식으로 볼 수 있음
  - `grep cron /var/log/syslog`
  - `journalctl _COMM=cron`
  - `journalctl _COMM=cron --since="date" --until="date"`
  - cron은 유지할 가능성이 높음
  - 제거하지 않을 경우 `sudo systemctl stop cron`, `sudo systemctl disable cron`으로 중지·비활성화할 수 있음
  - `apt remove cron`은 postfix 등을 설치하려고 할 수 있음
  - cron이 mail transport agent를 suggest하기 때문임
- ## `/usr/sbin/rsyslogd -n`
  - `rsyslogd`는 message logging을 지원하는 system utility임
  - `/var/log/auth.log` 같은 `/var/log/`의 로그 파일을 채우는 역할을 함
  - 설정 파일은 `/etc/rsyslog.d`에 있음
  - 원격 서버로 로그를 보내 centralized logging을 구성할 수 있음
  - `logger` 명령으로 background script에서 `/var/log/syslog`에 메시지를 남길 수 있음
  - `systemd-journald`가 이미 있어도 rsyslog와 journal은 서로 다른 특징이 있어 함께 쓰는 상황이 유용할 수 있음
  - 그래서 일단 유지함
- ## `/usr/sbin/acpid`
  - `acpid`는 ACPI event daemon임
  - user-space program에 ACPI event를 알려주도록 설계됨
  - ACPI는 hardware component discovery/configuration, power management, status monitoring 등에 쓰임
  - virtual server에서 suspend/resume을 의도하지 않아 제거해 봄
  - `reboot`은 성공했지만 `halt` 후 Digital Ocean이 여전히 켜진 것으로 인식해 web interface에서 Power Off해야 했음
  - 따라서 유지하는 편이 좋다고 정리됨
- ## `/usr/bin/lxcfs /var/lib/lxcfs/`
  - `lxcfs`는 LXC container를 위해 설계된 FUSE filesystem임
  - `/proc` 일부 파일의 virtualized view와 host cgroup filesystem에 대한 filtered access를 제공함
  - container 안에서 uptime, top 등이 더 “correct”한 결과를 갖게 함
  - LXC container를 쓰지 않으면 `sudo apt remove lxcfs -y --purge`로 제거할 수 있음
- ## `/usr/lib/accountservice/accounts-daemon`
  - AccountsService는 user account 정보를 query하고 조작하기 위한 D-Bus interface와 구현을 제공함
  - 구현은 `usermod(8)`, `useradd(8)`, `userdel(8)` 명령을 기반으로 함
  - 제거 후 무엇이 깨질지는 “Time will tell”로 남겨짐
- ## `/sbin/mdadm`
  - `mdadm`은 software RAID device를 관리하고 모니터링하는 Linux utility임
  - RAID는 여러 hard drive를 하나처럼 사용하는 방식임
  - RAID 0은 drive capacity를 확장함
  - RAID 1, RAID 5, RAID 6, RAID 10은 drive failure 시 data loss를 막는 목적이 있음
  - `sudo apt remove mdadm -y --purge`로 제거할 수 있음
- ## `/usr/lib/policykit-1/polkitd --no-debug`
  - `polkitd`는 PolicyKit daemon이며, polkit은 Authorization Framework임
  - fine-grained sudo처럼 이해됨
  - non-privileged user에게 root로 특정 action을 할 권한을 줄 수 있음
  - 예: desktop Linux에서 reboot 허용
  - server에서는 `sudo apt remove policykit-1 -y --purge`로 제거할 수 있다고 정리됨
  - 무엇이 깨지는지는 여전히 의문으로 남음
- ## `/usr/sbin/sshd -D`
  - `sshd`는 OpenSSH Daemon임
  - `-D` 옵션은 detach하지 않고 daemon이 되지 않게 하며, monitoring을 쉽게 함
- ## `/sbin/iscsid`
  - `iscsid`는 iSCSI configuration에 따라 동작하고 connection을 관리하는 background daemon임
  - iSCSI는 IP 기반 storage networking standard로, SCSI command를 IP network로 전달해 remote storage를 local disk처럼 사용할 수 있게 함
  - `sudo apt remove open-iscsi -y --purge`로 제거할 수 있음
- ## `/sbin/agetty --noclear tty1 linux`
  - `agetty`는 alternative Linux getty임
  - getty는 physical 또는 virtual terminal을 관리하고, 연결이 감지되면 username prompt를 띄운 뒤 `login` 프로그램을 실행함
  - Digital Ocean에서는 droplet details의 `Console`을 통해 이 terminal과 browser에서 상호작용할 수 있음
  - `getty@tty1.service` 관련 파일을 제거하고 reboot하면 SSH 접속은 가능했지만 Digital Ocean web console에서는 login할 수 없었음
- ## SSH 세션, bash, htop
  - `sshd: root@pts/0`은 `root` 사용자의 SSH session이 pseudoterminal `pts/0`에 설정됐다는 뜻임
  - pseudoterminal은 실제 text terminal을 emulate함
  - `bash`는 사용 중인 shell임
  - `-bash`처럼 앞에 dash가 붙으면 login shell로 시작된 것임
  - argument zero의 첫 문자가 `-`이거나 `--login` option으로 시작된 shell은 login shell임
  - 이 경우 다른 configuration file set을 읽음
  - `htop`은 screenshot에서 실행 중인 interactive process viewer임

### 서비스 제거 실험
- 일반 제거 목록은 다음과 같음
  - `sudo apt remove lvm2 -y --purge`
  - `sudo apt remove at -y --purge`
  - `sudo apt remove snapd -y --purge`
  - `sudo apt remove lxcfs -y --purge`
  - `sudo apt remove mdadm -y --purge`
  - `sudo apt remove open-iscsi -y --purge`
  - `sudo apt remove accountsservice -y --purge`
  - `sudo apt remove policykit-1 -y --purge`
- Extreme edition은 다음 작업을 포함함
  - `sudo apt remove dbus -y --purge`
  - `sudo apt remove rsyslog -y --purge`
  - `sudo apt remove acpid -y --purge`
  - `sudo systemctl stop cron && sudo systemctl disable cron`
  - `sudo rm /etc/systemd/system/getty.target.wants/getty@tty1.service`
  - `sudo rm /lib/systemd/system/getty@.service`
- [unattended installation of WordPress on Ubuntu Server](https://peteris.rocks/blog/unattended-installation-of-wordpress-on-ubuntu-server/) 지침을 따른 nginx, PHP7, MySQL 구성은 동작함

### 부록: 조사 도구와 shell 동작
- ## 소스 코드 찾기
  - `strace`만으로 충분하지 않을 때는 source code를 볼 수 있음
  - `which uptime`으로 binary 위치를 찾고, `dpkg -S /usr/bin/uptime`으로 Ubuntu package를 찾음
  - 예시에서는 `uptime`이 `procps` package에 속함
  - [packages.ubuntu.com](http://packages.ubuntu.com/)에서 package를 검색하고 source repository link를 찾을 수 있음
- ## file descriptor와 redirection
  - stderr를 stdout으로 redirect할 때는 `2>&1`을 사용함
  - `echo something > file`은 stdout을 file에 쓰는 것이며 `echo something 1> file`과 같음
  - `echo something 2> file`은 stderr를 file에 씀
  - `echo something 2>1`은 stderr를 `1`이라는 filename에 redirect하는 뜻임
  - `&`를 붙인 `2>&1`에서 `1`은 filename이 아니라 stream ID임
- ## PuTTY 색상 문제
  - PuTTY에서 `htop` 요소가 빠져 보이면 Window → Colours 설정에서 해결할 수 있음
  - title bar 우클릭
  - Change settings...
  - Window → Colours
  - Both radio button 선택
  - Apply
- ## C로 만든 간단한 shell
  - C로 작성한 간단한 shell은 `fork`, `exec`, `wait` 시스템 호출 사용을 보여줌
  - 입력이 `exit`이면 shell built-in으로 종료함
  - 그 외 명령은 `fork` 후 child에서 `execlp`로 실행하고, parent는 `waitpid`로 종료 상태를 기다림
  - `date`, `true`, `false` 실행 예시는 child exit code가 각각 출력됨
  - `sleep 1 &` 같은 background process의 종료 메시지가 Enter를 누른 뒤에야 보이는 이유는 shell이 input을 기다리다가 명령 입력 시 background process 상태를 확인하기 때문임

### 남은 조사 항목과 수정 이력
- 더 알아보고 싶은 항목은 process state substatus, kernel thread, `/dev/pts`, `CODE`·`DATA`·`SWAP` 메모리, time slice 길이, Linux scheduler 알고리듬, core pinning, manual page, CPU/memory bar 색상, process ID limit와 fork bomb, `lsof`, `ionice`, `schedtool` 등임
- 주요 수정·업데이트에는 다음이 포함됨
  - `/proc/uptime` idle time은 모든 core의 합산임
  - zombie C 예제의 parent/child `printf`가 수정됨
  - `apt remove cron`이 MTA dependency 때문에 `postfix`를 설치하려는 점이 추가됨
  - `id`는 `/etc/nsswitch.conf`를 통해 `/etc/passwd` 외 다른 source에서도 정보를 로드할 수 있음
  - `/etc/shadow` password hash format 설명이 추가됨
  - `/etc/sudoers`는 안전하게 `visudo`로 편집해야 함
  - `MEM%` 설명이 추가됨
  - load average 섹션이 다시 작성됨
  - `kill 1234`의 기본 signal은 `INT`가 아니라 `TERM`으로 수정됨
  - CPU와 memory color bar 설명이 추가됨

## Comments



### Comment 61276

- Author: neo
- Created: 2026-07-05T09:49:43+09:00
- Points: 1

###### [Hacker News 의견들](https://news.ycombinator.com/item?id=48784777) 
- 최근에는 **btop**으로 옮겨왔는데, 필요한 만큼 현대적이고 유용하며 정보량도 충분한 인터페이스였음  
  다른 사람들이 말한 것처럼 소비 전력(Watts)도 보여주는 듯하고, 네트워크, GPU, 디스크 정보도 함께 나옴  
  [https://github.com/aristocratos/btop](<https://github.com/aristocratos/btop>)
  - btop은 좋지만 단점도 있음: **zram/zswap 통계**가 없고(htop도 zram만 지원), ZFS 통계 세부 분해가 없으며, 아직 Arc GPU를 지원하지 않음  
    디스크 사용량 막대를 끌 수 없어 콘솔 창이 아주 크지 않으면 I/O 속도 그래프가 심하게 눌려 보임
  - btop을 오래 써왔는데, 빠진 건 다른 열 옆에 **포트 열** 하나 정도임  
    CPU/GPU 그래프는 너무 크게 잡혀 있고, 전반적으로 열린 파일 테이블이 더 많은 공간을 차지했으면 함
  - 아직도 가끔 컨테이너 기본 이미지로 **Alpine**을 쓰는데, btop이 musl을 지원하지 않는 것 같아서 제외됨
  - btop 신봉자라서, 새 MacBook에서는 **iStatMenu**까지 대체했음

- htop을 쓸 때마다 바꾸는 설정 2가지가 있는데 차이가 큼  
  첫째, **사용자 스레드**를 끔. 대체로 htop 화면만 어지럽히고 유용한 정보는 거의 주지 않음  
  둘째, **프로세스 트리 보기**를 켬. 프로세스가 어디서 시작됐는지가 다른 정보보다 더 중요할 때가 많고, 많은 파일을 처리하며 CPU를 먹는 컴파일러 프로세스 같은 것도 추적하기 쉬워짐  
  개인적으로는 둘 다 htop의 기본 동작이어야 한다고 봄
  - 프로세스 트리 보기는 좋지만, 켜면 프로세스 목록의 **동적 갱신과 재정렬**이 멈춰서 아쉬움

- 가상 메모리를 신뢰하기 어렵다는 설명이 반가움. Windows 작업 관리자가 기본으로 보여주는 방식이 이쪽이라 형편없음  
  **상주 집합 크기(RSS)** 가 가장 믿을 만한 지표이고, 그 외 값은 실제로 문제를 일으키지 않는 메모리 매핑 파일 같은 것 때문에 잘못 부풀려질 수 있음  
  예를 들어 2GB 로그 파일을 메모리 매핑해도 해당 부분을 읽을 때만 페이지로 올라오므로 실제 메모리를 쓰는 건 아닌데, 사용자는 프로세스를 보고 “왜 이 앱이 메모리를 이렇게 많이 쓰냐”고 함  
  Chrome도 한동안 이 문제를 겪어서 메모리 매핑 파일 사용을 줄였는데, 메모리 매핑 파일이 나빠서가 아니라 사용자가 실제 물리 메모리 사용량이 아닌 값을 보고 과민 반응했기 때문임  
  웹에는 가상 메모리 할당량으로 사용량을 판단하라는 가이드도 있는데, 이 글은 적어도 그 부분을 제대로 짚고 있음
  - 실제로는 **비례 집합 크기(PSS)** 가 RSS보다 더 정확함  
    참고: [https://en.wikipedia.org/wiki/Proportional_set_size](<https://en.wikipedia.org/wiki/Proportional_set_size>)
  - 메모리 매핑 파일을 쓰면 캐시된 페이지가 해당 프로세스의 **상주 집합 크기**에 포함됨  
    일반 파일 I/O를 쓰면 포함되지 않음. 각 작업의 메모리 사용량을 감시하다가 요청량을 넘으면 죽이는 HPC 클러스터에서는 꽤 재미있는 결과가 생김
  - 상주 집합 크기는 프로세스가 원하는 메모리 양이 아니라, **운영체제가 그 프로세스에 주기로 한 양**임  
    메모리 압박이 시작되면 더 이상 대표성이 없어짐. 이 오해 때문에 잘못된 결정을 몇 번 봤고, 팀원이 반대로 판단하는 걸 막으려고 차트에서 이 값을 빼버린 적도 있음
  - 정확히 말하면 Windows 작업 관리자는 프로세스 메모리 사용량 기본값으로 **Private Working Set**을 쓰며, 라이브러리나 메모리 매핑 파일처럼 다른 프로세스와 공유되는 페이지는 포함하지 않음  
    이름처럼 프로세스별로 사적으로 할당된 물리 메모리에 매핑된 부분만 보여주며, Unix의 Resident Set에 더 가까움  
    아마 성능 탭의 메모리 사용량을 말한 것 같지만, 모든 메모리 사용량 항목으로 오해할 수 있어 구분해둠

- top에서 `>` 문자를 쓰면 **메모리 사용량 기준 정렬**이 됨  
  호스트가 느려지는 이유를 찾을 때 가끔 쓰고, `swapd`가 CPU를 잡아먹는 것도 볼 수 있음
  - 메모리는 대문자 `M`, CPU는 대문자 `P`를 쓰는 쪽을 선호함

- 이런 글을 읽으면 Linux를 20년 넘게 매일 써왔는데도 아직 **잠재력의 일부만 활용**하고 있다는 걸 깨닫게 됨. 좋은 글임

- HN이 다시 회복되는 느낌이 듦  
  이게 HN의 걷는 유령 시기가 아니었으면 함
  - 첫 화면에 AI 관련 글이 3개 있지만, 하나는 저품질 생성물을 까는 글이라 희망을 가져봄
  - 7년 전 **슬롭 이전 글**로 돌아가며 회복되는 중인가 봄

- `nmon`을 모르는 사람은 이것도 한번 볼 만함  
  `h`를 누르면 사용 가능한 모니터 목록이 나오고, 다시 누르면 사라지며, `q`로 종료함  
  [https://nmon.sourceforge.io/pmwiki.php](<https://nmon.sourceforge.io/pmwiki.php>)  
  특히 `d`와 `D` 키로 보는 **디스크 처리량과 I/O**가 꽤 유용함
  - 직장에서 쓰는 AIX 장비들에서 알게 됐고, **topas**도 떠오름
  - 매우 유용한 도구라서 내가 제어할 수 있는 모든 머신에 설치함  
    **Wide CPU 사용량 그래프**가 큰 코어 수를 쉽게 처리해줘서 좋음

- `*top`류와는 다른 사용 방식으로, 차분한 `ps`식 차등 보고와 `vmstat` 같은 시스템 전체 보고를 더 좋아하게 됨  
  이렇게 하면 모든 내용이 터미널 스크롤백 버퍼에 남음: [https://github.com/c-blake/procs](<https://github.com/c-blake/procs>)  
  흔치 않게 효율적이고 표현력 있는 **Nim** 언어로 작성됨

- 이 글을 2016년부터 북마크해두고, 수년 동안 여러 번 다시 참고해왔음
