본문 바로가기
리눅스 이야기

Address already in use (Bind failed) 문제 해결방법

by reallinux1 2023. 11. 27.

Address already in use (Bind failed) 문제 해결방법

 

 

"Address already in use" Bind 에러란 ? 
서버 역할을 하는 프로그램(nginx, tomcat, java(spring), python(django), nodejs 등)이 리눅스 서버내에서 특정 IP 주소와 Port 번호를 사용하려고 할때 bind 시스템콜을 사용하게됩니다. 그런데 이미 다른 프로세스가 해당 Port 번호를 이미 사용하고 있을때 포트 충돌로 인한 Bind Failed 에러가 발생 할 수 있습니다.

아래와 같이 다양한 상황에서 Bind Failed 에러가 발생할 수 있습니다.

 - Nginx 에러 메시지 예시

Nov 27 03:23:53 ubuntu nginx[13081]: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
Nov 27 03:23:54 ubuntu nginx[13081]: nginx: [emerg] still could not bind()
Nov 27 03:23:54 ubuntu systemd[1]: nginx.service: Control process exited, code=exited status=1
Nov 27 03:23:54 ubuntu systemd[1]: nginx.service: Failed with result 'exit-code'.
Nov 27 03:23:54 ubuntu systemd[1]: Failed to start A high performance web server and a reverse proxy server.




 - Java 에러 메시지 예시

java.net.BindException: Address already in use (Bind failed)


 - Python 에러 메시지 예시

OSError: [Errno 98] Address already in use


 - Docker 에러 메시지 예시

Error starting userland proxy: listen tcp 0.0.0.0:2224: bind: address already in use


 - Nodejs 에러 메시지 예시

events.js:183
      throw er; // Unhandled 'error' event
      ^

Error: listen EADDRINUSE 0.0.0.0:80
    at Object._errnoException (util.js:1022:11)
    at _exceptionWithHostPort (util.js:1044:20)
    at Server.setupListenHandle [as _listen2] (net.js:1367:14)
    at listenInCluster (net.js:1408:12)
    at doListen (net.js:1517:7)
    at _combinedTickCallback (internal/process/next_tick.js:141:11)
    at process._tickCallback (internal/process/next_tick.js:180:9)
    at Function.Module.runMain (module.js:695:11)
    at startup (bootstrap_node.js:188:16)
    at bootstrap_node.js:609:3



문제 해결 방법:

많은 블로그와 게시글들에서 위 "Address already in use" Bind 문제 해결방식으로 충돌되는 포트번호를 쓰고 있는 프로세스를 찾아내서 kill 명령어 등을 통해서 종료시키는 방법을 이야기하고 있습니다.
(주의: 무턱대고 kill -9 를 사용하는것이 올바른 해결책은 아닙니다.)

우선 아래와같은 명령어(netstat, fuser, ss, lsof)들을 통해서 특정 포트번호(예: 80) 을 사용하고 있는 프로세스를 찾아 낼 수 있습니다.


$ sudo netstat -tnlp | grep 80
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      13029/node



$ sudo fuser -v 80/tcp
                     USER        PID ACCESS COMMAND
80/tcp:              root      13029 F.... node



$ sudo ss -lptn 'sport = :80'
State             Recv-Q             Send-Q                          Local Address:Port                         Peer Address:Port             
LISTEN            0                  511                                   0.0.0.0:80                                0.0.0.0:*                 users:(("node",pid=13029,fd=12))

 

$ sudo lsof -i :80
COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
node    13029 root   12u  IPv4 128546      0t0  TCP *:http (LISTEN)



위와 같이 찾아낸 프로세스 정보를 토대로 먼저 어떤 프로세스인지를 확인해야합니다.
꼭 80 포트가 아니더라도 다른포트번호로 동일한 이슈가 발생했을때에도 왜 그 포트를 사용중이고 누가 사용중인지 꼭 확인하고 종료 시켜야합니다.

또한 kill 은 단순히 프로세스를 종료시키는 명령어가 아닙니다. 특정 프로세스에게 kill -l 을 통해서 확인해보면 보낼 수 있는 시그널을 확인할 수 있고 9번(SIGKILL) 은 강제종료이고 15번(SIGTERM) 이 일반적인 종료의 시그널입니다. 9번(SIGKILL)으로 강제종료를 시키게 되면 시스템 자원해지를 정상적으로 하지 못하고 종료가 될 수 있고 이는 다른 부작용(side effect) 가 발생할 여지가 있습니다. 따라서 기본적으로는 15번(SIGTERM) 을 추천하고 만약에 다른방법으로 정상종료 시킬수가 있다면 (예: service nginx stop) 정상적으로 해지절차를 밟을 수있는 방법으로 종료시키는것을 추천드립니다 !

$ whatis kill
kill (1)             - send a signal to a process
kill (2)             - send signal to a process



$ kill -l
 1) SIGHUP  2) SIGINT  3) SIGQUIT  4) SIGILL  5) SIGTRAP
 6) SIGABRT  7) SIGBUS  8) SIGFPE  9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR
31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3
38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7
58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
63) SIGRTMAX-1 64) SIGRTMAX


kill -9 를 무턱대고 사용하면 안되는 이유 (예시 실습)

$ htop





# 다른 터미널 통해서 htop pid 얻어내서 강제종료 vs 정상종료 비교

$ pkill -9 htop

$ pkill htop



* 참고: 아래 이미지는 강제종료(비정상 종료)되었을때 예시 이미지 입니다.

 

리얼리눅스 홈페이지 바로가기 https://reallinux.co.kr/