스프링 부트 어플리케이션이 실행 중인 intellij를 종료하면서 terminate을 안하고 dismiss로 꺼버렸더니, 포트를 점유한 채로 꺼져버렸다.
이후 다시 어플리케이션을 돌리려고 하니 8080 포트를 사용하고 있다는 에러 메세지가 떴다.
💡 8080을 점유하고 있는 프로그램을 찾아서 끈다.
lsof -i :포트번호
kill -9 {PID번호}
lsof
명령어lsof
는 list open files의 약자로 시스템에서 열린 파일 목록을 알려주고 사용하는 프로세스, 디바이스 정보, 파일의 종류 등 상세한 정보를 출력해준다.
Linux, Unix는 추상화된 파일 시스템 (VFS - Virtual File System)을 사용하므로 일반 파일, 디렉터리, 네트워크 소켓, 라이브러리, 심볼릭 링크 등도 모두 파일로 처리되며 lsof
에서 상세한 정보를 확인할 수 있다.
lsof
는 리눅스, AIX, Solaris, FreeBSD, Mac OS X 등 종류에 상관없이 일관된 옵션과 출력 형식을 갖는다는 장점이 있다.
옵션 없이 lsof를 실행하면 모든 열린 파일 정보를 출력한다.
lsof
컬럼별 의미의 다음과 같다.
$ lsof /var/log/httpd/access_log
$ lsof +D /tmp
:여기서 사용한 명령어이다. -i 옵션 뒤에 프로토콜과 포트를 명시해 주면된다.
$ lsof -i TCP:22
$ lsof -i TCP:22-80 #범위 지정
예로 java 로 서비스하고 있는 모든 listen 하는 포트를 표시하려면 아래 명령을 실행한다.
$ lsof -i TCP -P |grep java|grep LISTEN
$ 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