프로그램을 사용할 때는 거의 그런 일들이 없지만, 개발을 하다 보면 특정 포트가 겹쳐서 실행이 되지 않는 경우가 있습니다. 이럴 때에는 해당 프로세스를 찾아서 kill 하고, 내가 원하는 프로그램을 다시 실행시키면 됩니다.

그런데, 이 포트라는 것이, 한번 사용할 때에 OS 에서 할당받는 개념으로 되어 있고, 그래서 프로그램이 정상 종료되면 반환하게 되지만, 그렇지 않고 강제 종료되는 등의 일이 발생하면 포트가 사용중인 것 처럼 더 이상 사용할 수 없게 됩니다. 물론 이 경우 재부팅을 하고 나면 자연스럽게 사라지는 현상이지만, 개발을 하다가 재부팅을 빈번하게 할 수도 없는 상황이므로 아래 내용을 참고하면 좋습니다.

특정 포트를 사용하는 프로세스 찾기

아마도 서버단 개발을 많이 진행한 분들이라면 netstat 이라는 명령어를 아주 잘 알고 계실겁니다. 최근에는 container 형태의 배포 형태가 많아졌기 때문에 그 중요성이 작아졌지만, 과거 하나의 머신(machine, VM)에 여러 개의 프로세스를 띄우는 경우 어떤 포트를 어느 프로세스가 사용하고 있는지 찾는 것은 매우 흔하고 중요한 일이었습니다.

netstat 사용해보기

netstat 명령어는 리눅스 명령어로, 그야말로 네트워크(network)의 상태(status) 를 체크하는 명령어입니다. 맥에서는 터미널이나 iterm같은 프로그램을 실행하고, 아래와 같이 입력합니다.

$ netstat -anv | grep LISTEN 
tcp4       0      0  127.0.0.1.631          *.*                    LISTEN      131072 131072  26008      0 0x0080 0x00000006
tcp6       0      0  ::1.631                *.*                    LISTEN      131072 131072  26008      0 0x0080 0x00000006
tcp4       0      0  127.0.0.1.49315        *.*                    LISTEN      131072 131072    724      0 0x0100 0x00000002
tcp4       0      0  127.0.0.1.16107        *.*                    LISTEN      131072 131072    669      0 0x0100 0x00000006
tcp4       0      0  *.15018                *.*                    LISTEN      131072 131072    692      0 0x0000 0x00000006
tcp46      0      0  *.3283                 *.*                    LISTEN      131072 131072    528      0 0x0000 0x00000202
tcp6       0      0  *.49177                *.*                    LISTEN      131072 131072    397      0 0x0100 0x00000006
tcp4       0      0  *.49177                *.*                    LISTEN      131072 131072    397      0 0x0100 0x00000006
tcp4       0      0  127.0.0.1.2015         *.*                    LISTEN      131072 131072     70      0 0x0180 0x00000026
tcp4       0      0  *.88                   *.*                    LISTEN      131072 131072    116      0 0x0180 0x00000006
tcp6       0      0  *.88                   *.*                    LISTEN      131072 131072    116      0 0x0180 0x00000006
tcp6       0      0  fe80::aede:48ff:.49159 *.*                    LISTEN      131072 131072     77      0 0x0180 0x00000006
tcp6       0      0  fe80::aede:48ff:.49158 *.*                    LISTEN      131072 131072     77      0 0x0180 0x00000006
tcp6       0      0  fe80::aede:48ff:.49157 *.*                    LISTEN      131072 131072     77      0 0x0180 0x00000006
tcp6       0      0  fe80::aede:48ff:.49156 *.*                    LISTEN      131072 131072     77      0 0x0180 0x00000006
tcp6       0      0  fe80::aede:48ff:.49155 *.*                    LISTEN      131072 131072     77      0 0x0180 0x00000006
tcp6       0      0  fe80::aede:48ff:.49154 *.*                    LISTEN      131072 131072     77      0 0x0180 0x00000006
tcp4       0      0  *.5900                 *.*                    LISTEN      131072 131072      1      0 0x0180 0x00000006
tcp6       0      0  *.5900                 *.*                    LISTEN      131072 131072      1      0 0x0180 0x00000006
tcp4       0      0  *.22                   *.*                    LISTEN      131072 131072      1      0 0x0180 0x00000006
tcp6       0      0  *.22                   *.*                    LISTEN      131072 131072      1      0 0x0180 0x00000006

여기서 -anv 부분은 옵션으로서, 필요에 따라서 다양한 옵션을 이용해서 표현할 수 있고, grep 부분은 그 결과 중에서 어떤 문구가 포함된 부분만을 발췌하겠다는 의미입니다.

만약 5900 포트에 대해서 확인을 해 보고 싶다면, grep 명령어를 이용해서 다음과 같이 응용할 수 있습니다.

$ netstat -anv | grep LISTEN | grep 5900
tcp4       0      0  *.5900                 *.*                    LISTEN      131072 131072      1      0 0x0180 0x00000006
tcp6       0      0  *.5900                 *.*                    LISTEN      131072 131072      1      0 0x0180 0x00000006

여기서 pid 는 두 개의 131072 뒤에 나오는 1 입니다. (뒤쪽에서 활용합니다)

조금 다른 방향으로 찾아보자

또 다른 명령어로 lsof 라는 것이 있습니다. 저도 이번에 공부하면서 알게 된 명령어인데, 사용법은 아래와 같습니다.

$ sudo lsof -iTCP -sTCP:LISTEN -n -P 
COMMAND     PID        USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
launchd       1        root    8u  IPv6 0xd7741fb83718b26b      0t0  TCP *:22 (LISTEN)
launchd       1        root    9u  IPv4 0xd7741fb8371919f3      0t0  TCP *:22 (LISTEN)
launchd       1        root   11u  IPv6 0xd7741fb83718b26b      0t0  TCP *:22 (LISTEN)
launchd       1        root   12u  IPv4 0xd7741fb8371919f3      0t0  TCP *:22 (LISTEN)
launchd       1        root   16u  IPv6 0xd7741fb83718b8cb      0t0  TCP *:5900 (LISTEN)
launchd       1        root   17u  IPv4 0xd7741fb83719241b      0t0  TCP *:5900 (LISTEN)
launchd       1        root   19u  IPv6 0xd7741fb83718b8cb      0t0  TCP *:5900 (LISTEN)
launchd       1        root   20u  IPv4 0xd7741fb83719241b      0t0  TCP *:5900 (LISTEN)
expressvp    70        root    5u  IPv4 0xd7741fb8371956e3      0t0  TCP 127.0.0.1:2015 (LISTEN)
remoted      77        root    4u  IPv6 0xd7741fb83718c58b      0t0  TCP [fe80:5::aede:48ff:fe00:1122]:49154 (LISTEN)
remoted      77        root    5u  IPv6 0xd7741fb83718ac0b      0t0  TCP [fe80:5::aede:48ff:fe00:1122]:49155 (LISTEN)
remoted      77        root    6u  IPv6 0xd7741fb8396c826b      0t0  TCP [fe80:5::aede:48ff:fe00:1122]:49156 (LISTEN)
remoted      77        root    7u  IPv6 0xd7741fb8396c88cb      0t0  TCP [fe80:5::aede:48ff:fe00:1122]:49157 (LISTEN)
remoted      77        root    8u  IPv6 0xd7741fb8396c8f2b      0t0  TCP [fe80:5::aede:48ff:fe00:1122]:49158 (LISTEN)
remoted      77        root    9u  IPv6 0xd7741fb8396c958b      0t0  TCP [fe80:5::aede:48ff:fe00:1122]:49159 (LISTEN)
kdc         116        root    5u  IPv6 0xd7741fb83975ac0b      0t0  TCP *:88 (LISTEN)
kdc         116        root    7u  IPv4 0xd7741fb837194293      0t0  TCP *:88 (LISTEN)
rapportd    397 jonghunpark    5u  IPv4 0xd7741fb837190fcb      0t0  TCP *:49177 (LISTEN)
rapportd    397 jonghunpark    6u  IPv6 0xd7741fb83975bf2b      0t0  TCP *:49177 (LISTEN)
ARDAgent    528 jonghunpark    9u  IPv6 0xd7741fb83ae4c58b      0t0  TCP *:3283 (LISTEN)
delfino     669 jonghunpark    9u  IPv4 0xd7741fb843fa986b      0t0  TCP 127.0.0.1:16107 (LISTEN)
UniCRSLoc   692 jonghunpark    3u  IPv4 0xd7741fb8421a6e43      0t0  TCP *:15018 (LISTEN)
Google      724 jonghunpark  103u  IPv4 0xd7741fb843fa79f3      0t0  TCP 127.0.0.1:49315 (LISTEN)
cupsd     26008        root    5u  IPv6 0xd7741fb8562e158b      0t0  TCP [::1]:631 (LISTEN)
cupsd     26008        root    6u  IPv4 0xd7741fb843fab6e3      0t0  TCP 127.0.0.1:631 (LISTEN)

sudo 명령어이기 때문에 관리자여야만 실행할 수 있습니다. 특정 포트에 대해서만 찾아보려면,

$ sudo lsof -i :5900 -n -P
COMMAND PID USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
launchd   1 root   16u  IPv6 0xd7741fb83718b8cb      0t0  TCP *:5900 (LISTEN)
launchd   1 root   17u  IPv4 0xd7741fb83719241b      0t0  TCP *:5900 (LISTEN)
launchd   1 root   19u  IPv6 0xd7741fb83718b8cb      0t0  TCP *:5900 (LISTEN)
launchd   1 root   20u  IPv4 0xd7741fb83719241b      0t0  TCP *:5900 (LISTEN)

프로세스 종료시키기

특정 프로세스를 종료시키는 명령어는 kill 입니다. 이 명령어는 프로그램의 terminate 동작에 해당하는 부분을 실행하지 않고, 즉시 종료시켜 버리기 때문에 특정 프로그램에는 문제를 일으킬 수 있습니다. 또한 UI 가 있는 프로그램의 경우에는 마지막 layout 등을 저장하고 종료되는데 그러한 과정 없이 종료되어 버리므로 다시 실행하면 처음 실행했던 모습으로 남아 있을 수도 있습니다.

$ kill -9 {pid}

출처 및 참고자료


Leave a comment