스탑 (1)

안녕하세요 케이치입니다.


오늘은 윈도우에서 특정 포트를 사용중인 프로세스를 죽이는 법을 가지고 왔습니다. 


최근에 Node.js 앱을 테스트해볼 일이 있었는데 고정적으로 특정 포트를 사용하는 앱이었습니다. 윈도우에서 cmd 창을 띄워서 실행시켰다가 Ctrl + C로  프로그램을 중지시켰는데 다시 기동시켰더니 포트가 이미 사용중이라면서 에러가 나더라구요. 그래서 이놈을 어떻게 죽여야 하나 찾아봤습니다.


우선 제 환경은 Windows 10이구요 CMD창을 띄우면 아래처럼 나옵니다.


제가 봤던 에러 메시지는 아래와 같구요


Error: listen EADDRINUSE :::2002


2002번 포트가 이미 사용중이라는 메시지입니다.


그럼 누가 이 포트를 사용중인지 찾아보죠.


cmd 창에 아래 명령어를 입력합니다.


C:\Users\dev>netstat -ano|find "2002"

  TCP    0.0.0.0:2002         0.0.0.0:0           LISTENING       5096

  TCP    [::]:2002              [::]:0                 LISTENING       5096


출력된 내용은 TCP 프로토콜에서 2002번 포트로 리스닝하고있는 프로세스의 ID가 5096번이라는 걸 말해줍니다. 우리는 5096 프로세스를 죽이면 되는거겠죠. 죽이기 전에 위 명령어에 대해서 설명을 좀 드리겠습니다.


netstat -ano는 netstat 명령어를 a, n, o 옵션으로 실행시키라는 의미죠. 여기서 a, n, o에 대한 설명은 netstat /? 를 입력하면 확인할 수 있습니다.


C:\Users\dev>netstat /?


프로토콜 통계와 현재 TCP/IP 네트워크 연결을 표시합니다.


NETSTAT [-a] [-b] [-e] [-f] [-n] [-o] [-p proto] [-r] [-s] [-x] [-t] [interval]


  -a            모든 연결과 수신 대기 포트를 표시합니다.

  -b            각 연결 또는 수신 대기 포트 생성과 관련된 실행 파일을

                표시합니다. 잘 알려진 실행 파일이 여러 독립 구성 요소를

                호스팅할 경우 연결 또는 수신 대기 포트 생성과 관련된

                구성 요소의 시퀀스가 표시됩니다.

                이러한 경우에는 실행 파일 이름이 대괄호로 아래에

                표시되고 위에는 TCP/IP에 도달할 때까지

                호출된 구성 요소가 표시됩니다. 이 옵션은 시간이 오래

                걸릴 수 있으며 사용 권한이 없으면 실패합니다.

  -e            이더넷 통계를 표시합니다. 이 옵션은 -s 옵션과 함께

                사용할 수 있습니다.

  -f            외부 주소의 FQDN(정규화된 도메인 이름)을

                표시합니다.

  -n            주소와 포트 번호를 숫자 형식으로 표시합니다.

  -o            각 연결의 소유자 프로세스 ID를 표시합니다.

  -p proto      proto로 지정한 프로토콜의 연결을 표시합니다. proto는

                TCP, UDP, TCPv6 또는 UDPv6 중 하나입니다. -s 옵션과 함께

                사용하여 프로토콜별 통계를 표시할 경우 proto는 IP, IPv6, ICMP,

                ICMPv6, TCP, TCPv6, UDP 또는 UDPv6 중 하나입니다.

  -q            모든 연결, 수신 대기 포트 및 바인딩된 비수신 대기 TCP

                포트를 표시합니다. 바인딩된 비수신 대기 포트는 활성 연결과 연결되거나

                연결되지 않을 수도 있습니다.

  -r            라우팅 테이블을 표시합니다.

  -s            프로토콜별 통계를 표시합니다. 기본적으로 IP, IPv6, ICMP,

                ICMPv6, TCP, TCPv6, UDP 및 UDPv6에 대한 통계를 표시합니다.

                -p 옵션을 사용하여 기본값의 일부 집합에 대한 통계만

                지정할 수 있습니다.

  -t            현재 연결 오프로드 상태를 표시합니다.

  -x            NetworkDirect 연결, 수신기 및 공유 끝점을

                표시합니다.

  -y            모든 연결에 대한 TCP 연결 템플릿을 표시합니다.

                다른 옵션과 함께 사용할 수 없습니다.

  interval      다음 화면으로 이동하기 전에 지정한 시간(초) 동안 선택한 통계를 다시 표시합니다.

                통계 다시 표시를 중지하려면 <Ctrl+C>를 누르십시오.

                이 값을 생략하면 현재 구성 정보가

                한 번만 출력됩니다.


이렇게 실행된 결과를 파이프( | )를 통해 find 명령어로 전달하여 "2002"를 찾으라고 하고있죠. find 명령어는 리눅스의 grep과 비슷한 기능을 합니다.


find "2002"를 제외한 앞 부분만 실행시키면 2002포트 말고도  다른 여러 포트들에 대한 목록이 함께 출력됩니다. 


자, 그럼 5096번 프로세스를 죽여볼까요?


윈도우에서 프로세스를 죽일 때는 "작업관리자"를 이용하는 방법도 있지만 개발을 하다보면 간혹 작업관리자에서 찾기 힘든 녀석들이 있죠. 그럴 경우 cmd창에서 작업을 하면 훨씬 수월하게 작업을 할 수 있습니다.


프로세스를 죽일 때는 taskkill 명령어를 사용합니다. 그럼 이녀석에 대한 설명을 한번 볼까요?


C:\Users\dev>taskkill /?


TASKKILL [/S 시스템 [/U 사용자 이름 [/P [암호]]]]

         { [/FI 필터] [/PID 프로세스 id | /IM 이미지 이름] } [/T] [/F]


설명:

    이 도구는 프로세스 ID(PID) 또는 이미지 이름으로 작업을 종료하는 데

    사용합니다.


매개 변수 목록:

    /S    시스템           연결할 원격 시스템을 지정합니다.


    /U    [도메인\]사용자  명령을 실행해야 하는 사용자 컨텍스트를

                           지정합니다.


    /P    [암호]           해당 사용자 컨텍스트의 암호를 지정합니다.

                           생략한 경우에는 물어봅니다.


    /FI   필터             작업 집합을 선택하는 필터를 적용합니다.

                           "*"를 사용할 수 있습니다. 예: imagename eq acme*


    /PID  프로세스_ID      종료할 프로세스의 PID를 지정합니다.

                           TaskList를 사용하여 PID를 얻을 수 있습니다.


    /IM   이미지 이름      종료할 프로세스의 이미지 이름을

                           지정합니다. 와일드카드 문자 '*'를 사용하여

                           모든 작업 또는 이미지 이름을 지정할 수 있습니다.


    /T                     지정된 프로세스와 그 프로세스로부터 시작된

                           모든 자식 프로세스를 종료합니다.


    /F                     프로세스를 강제로 종료하도록 지정합니다.


    /?                     이 도움말 메시지를 표시합니다.


필터:

    필터 이름     유효한 연산자             유효한 값

    -----------   ---------------           -------------------------

    STATUS        eq, ne                    RUNNING |

                                            NOT RESPONDING | UNKNOWN

    IMAGENAME     eq, ne                    이미지 이름

    PID           eq, ne, gt, lt, ge, le    PID 값

    SESSION       eq, ne, gt, lt, ge, le    세션 번호.

    CPUTIME       eq, ne, gt, lt, ge, le    CPU 시간 형식

                                            hh:mm:ss

                                            hh - 시간,

                                            mm - 분, ss - 초

    MEMUSAGE      eq, ne, gt, lt, ge, le    메모리 사용(KB)

    USERNAME      eq, ne                    사용자 이름([domain\]user

                                            형식)

    MODULES       eq, ne                    DLL 이름

    SERVICES      eq, ne                    서비스 이름

    WINDOWTITLE   eq, ne                    창 제목


    참고

    ----

    1) /IM 스위치에 대한 와일드카드 문자 '*'는 필터가 적용될 때만

    사용할 수 있습니다.

    2) 원격 프로세스는 항상 강제적으로(/F) 종료될 수 있습니다.

    3) 원격 컴퓨터가 지정되면 "WINDOWTITLE"  및 "STATUS" 필터는

       지원되지 않습니다.


예:

    TASKKILL /IM notepad.exe

    TASKKILL /PID 1230 /PID 1241 /PID 1253 /T

    TASKKILL /F /IM cmd.exe /T

    TASKKILL /F /FI "PID ge 1000" /FI "WINDOWTITLE ne untitle*"

    TASKKILL /F /FI "USERNAME eq NT AUTHORITY\SYSTEM" /IM notepad.exe

    TASKKILL /S 시스템 /U domain\username /FI "USERNAME ne NT*" /IM *

    TASKKILL /S 시스템 /U 사용자 이름 /P 암호 /FI "IMAGENAME eq note*"


설명을 읽어보니 우리에게 필요한 내용이 너무나도 잘 설명되어있네요.


그럼 이제 프로세스를 죽여보겠습니다.


C:\Users\dev>netstat -ano|find "2002"

  TCP    0.0.0.0:2002           0.0.0.0:0              LISTENING       5096

  TCP    [::]:2002              [::]:0                 LISTENING       5096


C:\Users\dev>taskkill /pid 5096

오류: 프로세스(PID 5096)를 종료할 수 없습니다.

원인: 이 프로세스는 /F 옵션을 사용하여 강제로 종료해야 합니다.


C:\Users\dev>taskkill /pid 5096 /f /t

성공: PID 5096인 프로세스(PID 11172인 자식 프로세스)가 종료되었습니다.


보시면 중간에 오류가 한번 나면서 /F옵션을 쓰라고 나오네요. 참고에 원격 프로세스는 /F 옵션을 줘야 종료된다고 나와있는데 그거 때문인것 같습니다. 그래서 F옵션을 추가하고 혹시나 해서 자식프로세스까지 죽이는 T옵션을 추가했습니다. 아!! 그리고  옵션은 대소문자 구문을 하지 않습니다. 윈도우는 영어 대소문자 구분을 하지 않죠. 


이상입니다. 오늘은 여기까지 쓸게요. 오늘도 즐코하세요~