[Linux] 사용 중인 포트 찾아서 kill 하기

Coastby·2022년 11월 15일
1

문제 해결

목록 보기
4/17

🚫 문제상황

스프링 부트 어플리케이션이 실행 중인 intellij를 종료하면서 terminate을 안하고 dismiss로 꺼버렸더니, 포트를 점유한 채로 꺼져버렸다.
이후 다시 어플리케이션을 돌리려고 하니 8080 포트를 사용하고 있다는 에러 메세지가 떴다.

⭕️ 해결방법

💡 8080을 점유하고 있는 프로그램을 찾아서 끈다.

  1. 사용하는 process 확인
lsof -i :포트번호
  1. 프로세스 종료
kill -9 {PID번호}

lsof 명령어

lsof는 list open files의 약자로 시스템에서 열린 파일 목록을 알려주고 사용하는 프로세스, 디바이스 정보, 파일의 종류 등 상세한 정보를 출력해준다.
Linux, Unix는 추상화된 파일 시스템 (VFS - Virtual File System)을 사용하므로 일반 파일, 디렉터리, 네트워크 소켓, 라이브러리, 심볼릭 링크 등도 모두 파일로 처리되며 lsof에서 상세한 정보를 확인할 수 있다.

lsof는 리눅스, AIX, Solaris, FreeBSD, Mac OS X 등 종류에 상관없이 일관된 옵션과 출력 형식을 갖는다는 장점이 있다.

옵션 없이 lsof를 실행하면 모든 열린 파일 정보를 출력한다.

lsof

컬럼별 의미의 다음과 같다.

  1. COMMAND : 실행한 명령어
  2. PID : process id
  3. USER : 실행한 사용자
  4. FD: File Descriptor, 파일의 종류.
    a. cwd: current working directory
    b. rtd: root directory
    c. mem : memory-mapped file
    d. txt: program text (code and data);
  5. TYPE: 파일 종류
    a. DIR: 디렉터리
    b. CHR: character special file
    c. REG: regular file
    d. unix: 유닉스 도메인 소켓 (MySQL 등이 사용하는 소켓으로 로컬 프로세스에서만 사용 가능하며 TCP/UDP 보다 속도가 매우 빠름)
  6. DEVICE : 장치 번호
  7. SIZE/OFF: 파일의 크기나 오프셋
  8. NODE: 노드 번호
  9. NAME: 파일명

✅ 옵션

  • -u
    : 사용자 지정
  • 경로 지정
    : 특정 파일을 사용하고 있는 프로세스의 자세한 정보를 볼 수 있다. 옵션 없이 파일의 경로를 지정하면 된다.
    $ lsof /var/log/httpd/access_log
  • +D [디렉터리경로]
    : 특정 디렉터리 하위의 열린 파일을 표시하고 싶은 경우, +D 옵션 뒤에 디렉터리 경로를 명시하면 된다.
    $ lsof +D /tmp

✅ -i

:여기서 사용한 명령어이다. -i 옵션 뒤에 프로토콜과 포트를 명시해 주면된다.

$ lsof -i TCP:22
$ lsof -i TCP:22-80   #범위 지정
  • service name 대신 port 번호 표시
    IANA 에 등록한 well known 포트는 /etc/services 에 지정되어 있으므로 서비스를 파악하기 용이하다. 하지만 자체 개발한 서비스가 /etc/services 에 등록된 포트를 사용할 경우에는 서비스 이름보다 포트 번호로 표시하는 게 낫다. -P 옵션을 사용하면 서비스 이름대신 포트 번호로 표시해 준다.

예로 java 로 서비스하고 있는 모든 listen 하는 포트를 표시하려면 아래 명령을 실행한다.

$ lsof -i TCP -P |grep java|grep LISTEN
  • IPv4 또는 IPv6 포트만 표시
    -i 옵션 뒤에 4(IPv4), 또는 6(IPV6) 를 지정하여 특정 IP 의 버전만 확인할 수 있다.
    $ lsof -i 4

kill 명령어

signum 옵션은 생략할 수 있으며 생략시 TERM(Terminate) 시그널을 전송하게 되며 프로그램이 별도의 시그널 핸들러를 만들지 않았을 경우 기본 시그널 핸들러인 "프로세스 종료" 기능이 수행된다.

이제 왜 시그널 전송 명령어 이름이 kill 인지 이유를 짐작할 수 있을 것이다. 기본 시그널이 TERM 시그널이며 프로세스가 이 시그널을 수신시 기본 동작이 프로세스 종료라서 kill 이 되었다지만 다른 동작도 가능하므로 명령어 이름을 잘못 지은 셈이다.

kill -9 로 프로세스를 종료하면 시스템에 악영향을 줄 수 있습니다.
대신 kill -INT 나 kill -TERM 을 사용하세요.

인터넷보고 따라했는데, 위험하다고 한다..🤦‍♀️

이유?
리눅스를 포함하여 유닉스는 프로그램 작성시 시그널 핸들러를 등록할 수 있으므로 잘 만든 유닉스 프로그램이라면 INT, TERM 시그널을 받으면 사용하는 자원이나 객체를 반납하고 메모리를 정리하고 종료하도록 구현되어 있다.

시그널중에는 핸들러를 지정할 수 없는 시그널이 두 개 있으며 바로 KILL(9), STOP(19) 두 개의 시그널이다.

그러므로 프로세스가 이 시그널을 받으면 내부의 자원 반납과 정리 루틴을 호출하지 못하고 바로 종료되어 버릴 수 있으므로 TERM이나 INT 로는 종료되지 않는 프로세스외에는 일반적으로 사용하지 않는 게 좋다.

⭕️ 올바른 방법,

kill 명령어로 프로세스를 안전하게 종료 시키기 위해 권장하는 방법은 먼저 kill -TERM PID 나 kill -INT PID 같이 TERM(Termination) 나 INT(Interrupt) 시그널을 전송하는 것이다.

Java VM 도 TERM 시그널을 수신할 경우 깨끗하게 종료되니 tomcat 이나 기타 java VM 위에서 돌아가는 프로그램 종료시 KILL 시그널을 바로 보내지 말고 두 세 번 정도 TERM(15) 시그널을 보내고 그래도 종료가 되지 않을 경우 KILL 시그널을 전송하는게 좋다.

Linux에서 서비스 프로세스를 관리하는 service 명령어도 TERM 시그널을 보낸후에 일정 시간후에도 프로세스가 종료되지 않았으면 KILL 시그널을 보내게 구현되어 있다.

출처 :
https://www.lesstif.com/system-admin/lsof-20776078.html

profile
훈이야 화이팅

0개의 댓글