Linux

Linux Process Story

naleejang 2024. 6. 14. 23:05

오랜만에 삽질을 좀 할 기회가 와서 삽질한 김에 알게 된 것들을 좀 정리해 놓으면 좋을 것 같아서 블로그에 글을 쓰기 시작한다. 하는 일이 리눅스를 모르면 할 수 없는 일들인데도, 어쩜 이렇게 모르는 명령어들이 많은지... 알면 알수록 신기하고 재미난 세계임은 틀림이 없는것 같다. 

리눅스에서 실행되는 모든 애플리케이션들은 전부 프로세스 기반으로 실행이 된다는 건 아마도 리눅스를 조금이라도 다루어 본 경험이 있는 사람이라면 누구나 알고 있는 사실일 것이다. 

그럼, 실행 중인 프로세스는 어떻게 확인할 수 있을까? 많이 사용하는 명령어가 아마도 ps 라는 명령어 일것이다. ps 에 여러 옵션을 주고 프로세스를 목록을 확인할 수 있는데, 난 주로 옛날에 대학 다닐때 배웠던 ps -ef 라는 명령어다. 요즘은 ps aux 와 같은 명령어도 많이 쓰는것 같다.

[nalee@rhel8 ~]$ ps -ef 
UID          PID    PPID  C STIME TTY          TIME CMD
root           1       0  0 Jun11 ?        00:00:45 /usr/lib/systemd/systemd --switched-root --system --deserialize 17
root           2       0  0 Jun11 ?        00:00:00 [kthreadd]
root           3       2  0 Jun11 ?        00:00:00 [rcu_gp]
root           4       2  0 Jun11 ?        00:00:00 [rcu_par_gp]
root           5       2  0 Jun11 ?        00:00:00 [slub_flushwq]
...

[nalee@rhel8 ~]$ ps aux
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root           1  0.0  0.0 241752 14580 ?        Ss   Jun11   0:45 /usr/lib/systemd/systemd --switched-root --system --deserialize 17
root           2  0.0  0.0      0     0 ?        S    Jun11   0:00 [kthreadd]
root           3  0.0  0.0      0     0 ?        I<   Jun11   0:00 [rcu_gp]
root           4  0.0  0.0      0     0 ?        I<   Jun11   0:00 [rcu_par_gp]
root           5  0.0  0.0      0     0 ?        I<   Jun11   0:00 [slub_flushwq]
...

프로세스를 확인할 수 있는 명령어는 이것뿐일까? 아니다. 가끔은 부모 프로세스가 뭐고, 자식 프로세스가 뭔지 알아야만 할때도 있다. 물론 알고 싶지 않을지라도 알아야만 할때 pstree 라는 명령어를 사용하여 프로세스 목록을 트리 형식으로 볼 수 있다. 

[root@comp01 ~]# pstree -p
systemd(1)─┬─NetworkManager(1034)─┬─{NetworkManager}(1045)
           │                      └─{NetworkManager}(1049)
           ├─agetty(1600)
           ├─agetty(1601)
           ├─auditd(903)───{auditd}(904)
           ├─certmonger(32126)
           ├─chronyd(29940)
           ├─conmon(41558)─┬─dumb-init(41571)───iscsid(41585)
           │               └─{conmon}(41560)
           ├─conmon(880650)─┬─dumb-init(880683)───dumb-init(880706)───sshd(880741)
           │                └─{conmon}(880652)
           ├─conmon(880816)─┬─dumb-init(880828)───virtlogd(880841)
           │                └─{conmon}(880818)
           ├─conmon(880883)─┬─dumb-init(880896)───libvirtd(880908)─┬─{libvirtd}(880951)
           │                │                                      ├─{libvirtd}(880952)
           │                │                                      ├─{libvirtd}(880953)
           │                │                                      ├─{libvirtd}(880954)
           │                │                                      ├─{libvirtd}(880955)
           │                │                                      ├─{libvirtd}(880956)
           │                │                                      ├─{libvirtd}(880957)
           │                │                                      ├─{libvirtd}(880958)
           │                │                                      ├─{libvirtd}(880959)
           │                │                                      ├─{libvirtd}(880960)
           │                │                                      ├─{libvirtd}(1020161)
           │                │                                      └─{libvirtd}(1020545)
           │                ├─qemu-kvm(1019818)─┬─{qemu-kvm}(1019857)
           │                │                   ├─{qemu-kvm}(1019883)
           │                │                   ├─{qemu-kvm}(1019884)
           │                │                   └─{qemu-kvm}(1019899)
           │                ├─qemu-kvm(1020537)─┬─{qemu-kvm}(1020548)
           │                │                   ├─{qemu-kvm}(1020557)
           │                │                   ├─{qemu-kvm}(1020559)
           │                │                   └─{qemu-kvm}(1020582)
           │                └─{conmon}(880885)
           ├─crond(29278)
           └─tuned(1434)─┬─{tuned}(1467)
                         ├─{tuned}(21097)
                         ├─{tuned}(21100)
                         └─{tuned}(21101)
[root@comp01 ~]#

이렇게 프로세스 트리를 통해 우리는 프로세스의 관계를 알수 있다. 그럼 여기서, 가끔 프로세스를 종료해야 할 경우가 온다. 그러면 우리는 대체적으로 ps -ef | grep process_name 이런식으로 명령어를 실행해서 프로세스 ID를 찾은 뒤 kill -9 PID 명령어를 통해 프로세스를 종료한다. 과연 이 방법만이 프로세스 ID를 찾을 수 있을까? 아니다. pgrep 이라는 명령어가 있다. pgrep를 사용하면 쉽게 프로세스 ID를 찾을 수 있다.

[root@comp01 ~]# pgrep qemu-kvm
1019818
1020537
[root@comp01 ~]# pgrep libvirtd
880908
[root@comp01 ~]#

그리고, 이렇게 찾은 프로세스는 pkill이라는 명령어로 프로세스를 종료할 수 있다. 그럼, 여기서 libvirtd를 pkill로 종료한다고 해서 qemu-kvm이라는 프로세스도 같이 죽을까? 그건 아니다. libvirtd는 dump-init 이라는 프로세스의 하위 프로세스이고, qemu-kvm은 conmon 프로세스의 하위 프로세스 아래 있으므로, libvirtd 가 죽었다고 해서 qemu-kvm이 죽지는 않는다.  

[root@comp01 ~]# pgrep libvirtd
302094
[root@comp01 ~]# pkill libvirtd
[root@comp01 ~]# pgrep libvirtd
[root@comp01 ~]# pgrep qemu-kvm
1019818
1020537

그래서, 나는 좀더 재밌는 실험을 해 보기로 했다. 아래 동영상은 내 노트북 환경을 녹화한 건데, pkill 명령어로 libvirtd 라는 프로세스를 죽였다. 그리고, 실행중인 vm이 죽는지 확인해 봤다. 물론, vm은 죽지 않는다. 이때, pidof 라는 명령어를 이용해 libvirtd의 프로세스 ID를 찾는데, 사실 pgrep이랑 결과가 동일하다. 

이렇게 해서 이번에 알게된 프로세스 이야기를 블로그에 정리해 봤다. 물론 아는 사람들도 있겠지만, 나처럼 모르는 사람들이 더 많을꺼라 생각한다. 그래서 이렇게 적어두면 언젠가 나에게 그리고, 또 다른 누군가에게 도움이 되겠지~!!

오늘은 이만 자야겠다.