اگر هنگام اجرای یک برنامه، وبسرور، API، دیتابیس یا کانتینر با خطایی مثل Address already in use، EADDRINUSE، bind: address already in use یا در Docker با پیام port is already allocated روبهرو شدهاید، معنی آن معمولاً این است که یک Process دیگر قبلاً همان IP و Port را گرفته است و برنامه جدید نمیتواند روی همان Socket گوش کند.
راهحل کوتاه: ابتدا با ss -ltnp یا ss -lunp مشخص کنید چه Processای روی پورت موردنظر Listen میکند. اگر به PID نیاز دارید از lsof -i :PORT یا fuser PORT/tcp کمک بگیرید. بعد بررسی کنید Process متعلق به کدام سرویس systemd، برنامه یا کانتینر Docker است. فقط اگر مطمئن شدید آن سرویس نباید فعال باشد، آن را بهصورت اصولی Stop کنید؛ kill -9 باید آخرین انتخاب باشد، نه اولین راهحل.
خطای Address Already in Use یعنی چه؟
برنامههایی مثل Nginx، Apache، Node.js، Python، PHP، Redis، PostgreSQL و سرویسهای Docker برای دریافت اتصال شبکه باید یک Socket را به یک IP و Port مشخص Bind کنند.
برای مثال ممکن است برنامه Node.js بخواهد روی پورت 3000 اجرا شود:
0.0.0.0:3000
اگر Process دیگری قبلاً همین آدرس را گرفته باشد، برنامه دوم نمیتواند همان ترکیب IP و Port را Bind کند و سیستمعامل خطای EADDRINUSE برمیگرداند.
نمونه خطا در Node.js:
Error: listen EADDRINUSE: address already in use :::3000
نمونه در Python:
OSError: [Errno 98] Address already in use
نمونه در یک سرویس لینوکسی:
bind() to 0.0.0.0:8080 failed (98: Address already in use)
قبل از Kill کردن Process، سرویس اشغالکننده پورت را پیدا کنید
اشتباه رایج این است که بهمحض دیدن خطا، Process را با kill -9 متوقف کنیم. این کار ممکن است وبسرور، دیتابیس، SSH Tunnel، Proxy یا سرویس مهم دیگری را از کار بیندازد.
روند درست این است:
- پورت مشکلدار را مشخص کنید.
- Process یا سرویس Listenکننده را پیدا کنید.
- بررسی کنید Process چرا فعال است.
- تصمیم بگیرید سرویس فعلی Stop شود یا پورت برنامه جدید تغییر کند.
- بعد از تغییر، دوباره وضعیت پورت را تست کنید.
روش اول و پیشنهادی: پیدا کردن سرویس اشغالکننده Port با ss
در بیشتر توزیعهای جدید Linux، ابزار ss انتخاب مناسبی برای بررسی Socketها است.
برای مشاهده TCP Portهای در حال Listen:
sudo ss -ltnp
معنی گزینهها:
-l: فقط Socketهای Listening را نمایش میدهد.-t: فقط TCP را نمایش میدهد.-n: Port و IP را عددی نشان میدهد.-p: Process مرتبط را در صورت داشتن Permission نمایش میدهد.
نمونه خروجی:
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 511 0.0.0.0:80 0.0.0.0:* users:(("nginx",pid=2140,fd=6))
LISTEN 0 4096 127.0.0.1:3000 0.0.0.0:* users:(("node",pid=4251,fd=19))
در این مثال:
- پورت
80توسط Nginx با PID برابر2140استفاده میشود. - پورت
3000توسط Node.js با PID برابر4251استفاده میشود.
فقط یک Port مشخص را با ss بررسی کنیم
مثلاً برای پورت 3000:
sudo ss -ltnp 'sport = :3000'
یا با grep:
sudo ss -ltnp | grep ':3000 '
روش اول دقیقتر است، چون از قابلیت فیلتر خود ss استفاده میکند.
اگر Port مربوط به UDP است
دستور TCP چیزی برای UDP نشان نمیدهد. برای UDP اجرا کنید:
sudo ss -lunp
برای یک UDP Port مشخص، مثلاً 53:
sudo ss -lunp 'sport = :53'
این مورد برای سرویسهایی مثل DNS اهمیت دارد؛ چون ممکن است پورت UDP اشغال باشد ولی شما فقط TCP را بررسی کرده باشید.
روش دوم: پیدا کردن PID با lsof
lsof ابزار مشاهده فایلهای باز توسط Processها است و Socketهای شبکه نیز در Linux بهعنوان File Descriptor مدیریت میشوند.
برای پورت 8080:
sudo lsof -i :8080
نمونه:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
java 7421 app 64u IPv6 91944 0t0 TCP *:8080 (LISTEN)
در این خروجی Process با نام java و PID برابر 7421 پورت را در اختیار دارد.
برای نمایش فقط TCP Listener روی همان Port:
sudo lsof -nP -iTCP:8080 -sTCP:LISTEN
اگر lsof نصب نیست
در Ubuntu و Debian:
sudo apt update
sudo apt install lsof
در Rocky Linux، AlmaLinux یا RHEL:
sudo dnf install lsof
روش سوم: پیدا کردن PID با fuser
برای TCP Port 3000:
sudo fuser 3000/tcp
نمونه خروجی:
3000/tcp: 4251
برای نمایش اطلاعات بیشتر:
sudo fuser -v 3000/tcp
برای UDP:
sudo fuser -v 53/udp
هشدار: fuser امکان Kill کردن Process را هم دارد، اما قبل از استفاده از گزینههای Kill ابتدا سرویس و نقش PID را مشخص کنید. آزاد کردن پورت با متوقف کردن اشتباهی سرویس حیاتی میتواند باعث Downtime شود.
PID پیدا شد؛ حالا بفهمیم Process چیست
فرض کنیم PID برابر 4251 است.
اطلاعات Process:
ps -fp 4251
Command Line کامل:
tr '\0' ' ' < /proc/4251/cmdline
echo
مسیر فایل اجرایی:
readlink -f /proc/4251/exe
دایرکتوری کاری Process:
readlink -f /proc/4251/cwd
این اطلاعات کمک میکند بفهمید Process مربوط به کدام برنامه یا پروژه است.
چطور بفهمیم PID مربوط به کدام سرویس systemd است؟
یکی از روشهای ساده:
systemctl status 4251
اگر Process عضو یک Unit شناختهشده systemd باشد، معمولاً اطلاعات Service نمایش داده میشود.
همچنین میتوانید ساختار Cgroup را ببینید:
cat /proc/4251/cgroup
اگر مثلاً مشخص شد Process متعلق به nginx.service است، بهجای Kill کردن مستقیم PID بهتر است Service را مدیریت کنید:
sudo systemctl status nginx
sudo systemctl stop nginx
روش اصولی آزاد کردن Port
اگر پس از بررسی مطمئن شدید Process قبلی نباید اجرا شود، ابتدا روش Graceful را امتحان کنید.
اگر systemd Service است:
sudo systemctl stop SERVICE_NAME
مثلاً:
sudo systemctl stop nginx
بعد Port را بررسی کنید:
sudo ss -ltnp 'sport = :80'
اگر Process مستقل است
برای Process مستقل ابتدا SIGTERM بفرستید:
kill 4251
این فرمان بهطور پیشفرض SIGTERM میفرستد و به برنامه فرصت میدهد Shutdown تمیز انجام دهد.
چند ثانیه بعد:
ps -p 4251
sudo ss -ltnp 'sport = :3000'
فقط اگر Process به SIGTERM پاسخ نداد و مطمئن هستید توقف اجباری بیخطر است، SIGKILL را در نظر بگیرید:
kill -9 4251
چرا kill -9 انتخاب اول نیست؟ SIGKILL به Process فرصت Cleanup، Flush کردن داده، بستن Connectionها یا حذف Lock File را نمیدهد. برای دیتابیس و برنامههای دارای داده حساس این تفاوت مهم است.
اگر سرویس را Stop میکنیم ولی دوباره برمیگردد
اگر Process بلافاصله با PID جدید ظاهر میشود، احتمالاً تحت کنترل systemd، Supervisor، Docker، Kubernetes یا یک Process Manager مانند PM2 است.
مثلاً بعد از Kill:
sudo ss -ltnp 'sport = :3000'
اگر PID جدیدی ظاهر شد، Root Cause را پیدا کنید؛ Kill کردن مکرر راهحل نیست.
اگر برنامه با PM2 اجرا شده است
برنامههای Node.js ممکن است توسط PM2 مدیریت شوند:
pm2 list
برای توقف یک برنامه:
pm2 stop APP_NAME
اگر برنامه نباید دیگر اجرا شود:
pm2 delete APP_NAME
رفع Address Already in Use در Docker
در Docker دو Port مهم داریم:
- Container Port: پورتی که برنامه داخل Container استفاده میکند.
- Published Host Port: پورتی که روی Host منتشر شده است.
مثلاً:
docker run -p 8080:80 nginx
یعنی Port 8080 روی Host به Port 80 داخل Container متصل میشود.
اگر Host Port 8080 قبلاً استفاده شده باشد، Container جدید نمیتواند همان Port را Publish کند.
ببینید کدام Container پورت را گرفته است
docker ps --format 'table {{.ID}}\t{{.Names}}\t{{.Ports}}'
نمونه:
CONTAINER ID NAMES PORTS
a91c44f21c12 old-api 0.0.0.0:8080->80/tcp
bc319cd92011 postgres 0.0.0.0:5432->5432/tcp
در این مثال Container با نام old-api پورت 8080 Host را گرفته است.
جستوجوی سریع Docker بر اساس Port
docker ps --filter publish=8080
اگر Container موردنظر دیگر لازم نیست:
docker stop old-api
و اگر باید حذف شود:
docker rm old-api
اگر مشکل در Docker Compose است
فرض کنید Compose این تنظیم را دارد:
services:
app:
image: myapp
ports:
- "8080:80"
اگر پورت 8080 روی Host اشغال باشد، یکی از راهها انتخاب Port دیگری است:
services:
app:
image: myapp
ports:
- "8081:80"
سپس:
docker compose up -d
در این حالت برنامه داخل کانتینر همچنان Port 80 دارد، اما از بیرون با Port 8081 Host در دسترس است.
اگر ss فقط docker-proxy نشان میدهد
در بعضی تنظیمات Docker ممکن است Process مربوط به Port بهشکل docker-proxy دیده شود:
sudo ss -ltnp 'sport = :8080'
در این حالت ابتدا Containerهای دارای Published Port را بررسی کنید:
docker ps --filter publish=8080
بهجای Kill کردن مستقیم docker-proxy، Container مسئول آن Port را مدیریت کنید.
مقاله مرتبط
اگر Port آزاد است اما سایت یا سرویس VPS همچنان از بیرون باز نمیشود، مشکل میتواند از Firewall، Listen Address، Reverse Proxy یا شبکه باشد. در این حالت مقاله عیبیابی باز نشدن سایت روی VPS میتواند مرحله بعدی بررسی باشد.
تداخل IPv4 و IPv6 را هم بررسی کنید
گاهی خطا کمی گیجکننده است؛ چون برنامه روی IPv4 چیزی نشان نمیدهد اما Bind روی IPv6 انجام شده است.
هم TCP IPv4 و هم IPv6 را ببینید:
sudo ss -ltnp
ممکن است خروجی شامل یکی از اینها باشد:
0.0.0.0:8080
127.0.0.1:8080
[::]:8080
[::1]:8080
0.0.0.0 یعنی برنامه روی همه IPv4 Addressهای سیستم Listen میکند. [::] نیز معمولاً به همه IPv6 Addressها اشاره دارد و بسته به تنظیمات Socket و سیستم ممکن است روی Bind برنامه دوم اثر بگذارد.
یک Port میتواند روی IPهای مختلف استفاده شود؟
بله، در بعضی شرایط دو سرویس میتوانند یک شماره Port یکسان داشته باشند اگر روی IPهای محلی متفاوت Bind شوند.
مثلاً:
127.0.0.1:8080
192.0.2.10:8080
اما اگر یکی از برنامهها روی:
0.0.0.0:8080
Listen کند، معمولاً تمام IPv4 Addressهای محلی را برای آن Port پوشش میدهد و برنامه دیگری نمیتواند بهسادگی Port 8080 را روی یکی از همان IPها بگیرد.
127.0.0.1 با 0.0.0.0 چه تفاوتی دارد؟
اگر سرویس فقط باید توسط Reverse Proxy محلی مصرف شود، معمولاً Bind روی Loopback امنتر است:
127.0.0.1:3000
اما:
0.0.0.0:3000
به معنی Listen روی همه IPv4 Interfaceهای محلی است.
گاهی دو نسخه از یک برنامه با تنظیم متفاوت Bind شدهاند و همین موضوع باعث Conflict میشود.
تداخل Nginx و Apache روی Port 80 یا 443
یکی از سناریوهای بسیار رایج این است که هم Nginx و هم Apache تلاش میکنند روی Port 80 اجرا شوند.
بررسی:
sudo ss -ltnp 'sport = :80'
sudo ss -ltnp 'sport = :443'
سپس:
sudo systemctl status nginx
sudo systemctl status apache2
اگر Nginx قرار است Reverse Proxy باشد، معمولاً Backend باید روی Port دیگری مثل 8080 یا Loopback اجرا شود؛ نه اینکه هر دو روی 0.0.0.0:80 Bind شوند.
Node.js دو بار اجرا شده است
در پروژه Node.js ممکن است برنامه را دستی اجرا کرده باشید:
node server.js
در حالی که همان برنامه قبلاً با PM2 یا systemd فعال بوده است.
پورت را بررسی کنید:
sudo ss -ltnp 'sport = :3000'
و Processهای Node:
ps aux | grep '[n]ode'
اگر PM2 دارید:
pm2 list
Flask یا Python: Port قبلاً گرفته شده است
مثلاً Flask روی Port 5000:
sudo ss -ltnp 'sport = :5000'
یا:
sudo lsof -nP -iTCP:5000 -sTCP:LISTEN
اگر نسخه قبلی برنامه هنوز فعال است، همان Process را بهصورت اصولی Stop کنید یا Port نسخه جدید را تغییر دهید.
Redis و PostgreSQL را بدون بررسی متوقف نکنید
پورتهای رایج:
Redis: 6379
PostgreSQL: 5432
MySQL: 3306
اگر برنامه شما میخواهد روی یکی از این Portها اجرا شود و PID متعلق به دیتابیس است، احتمالاً مشکل از انتخاب Port برنامه شماست، نه دیتابیس.
هشدار: صرفاً برای آزاد کردن Port، دیتابیس Production را Stop یا Kill نکنید. ابتدا مشخص کنید کدام سرویس باید واقعاً از آن Port استفاده کند.
گاهی systemd Socket خودش Port را گرفته است
در بعضی سرویسها systemd قبل از اجرای Service، Socket را باز میکند. در این حالت فقط بررسی Service کافی نیست.
Socket Unitهای فعال:
systemctl list-sockets
اگر Socket Unit خاصی Port را مدیریت میکند، وضعیت آن را بررسی کنید:
systemctl status NAME.socket
در چنین سناریویی Kill کردن Process فرزند ممکن است باعث آزاد ماندن دائمی Port نشود، چون خود Socket Unit همچنان فعال است.
آیا TIME_WAIT باعث Address Already in Use میشود؟
گاهی بعد از Restart سریع برنامه تعداد زیادی Connection در حالت TIME-WAIT دیده میشود:
ss -tan state time-wait
اما وجود TIME_WAIT بهتنهایی به این معنی نیست که یک Listener فعال همان Port را اشغال کرده است. برای خطای Bind ابتدا Listenerها را بررسی کنید:
sudo ss -ltnp
رفتار دقیق Bind مجدد به تنظیمات Socket مانند SO_REUSEADDR و نوع Connection بستگی دارد؛ بنابراین پیشنهاد نمیشود صرفاً به خاطر مشاهده TIME_WAIT تنظیمات Kernel را تغییر دهید.
اگر برنامه میگوید Port اشغال است ولی ss چیزی نشان نمیدهد
چند مورد را بررسی کنید:
- پروتکل را اشتباه بررسی نکرده باشید؛ TCP در برابر UDP.
- IPv6 Listener را نادیده نگرفته باشید.
- فرمان را بدون Permission کافی اجرا نکرده باشید.
- برنامه با Unix Socket کار نکند.
- خطا مربوط به Port موقتی یا Race Condition نباشد.
- Process بین دو بار بررسی سریع Start و Stop نشود.
بررسی گسترده:
sudo ss -lntup
Address Already in Use برای Unix Socket
این خطا فقط مخصوص TCP/UDP Port نیست. برنامهها میتوانند روی Unix Domain Socket نیز Bind کنند.
مثلاً:
/run/myapp/app.sock
برای مشاهده Unix Socketها:
sudo ss -lxnp
اگر Socket File باقی مانده ولی Process مربوطه دیگر وجود ندارد، باید اول مطمئن شوید Socket واقعاً Stale است. حذف کورکورانه Socket فایل یک سرویس فعال میتواند مشکل ایجاد کند.
گاهی بهتر است Port برنامه جدید را تغییر دهید
اگر Port فعلی به سرویس مهم دیگری تعلق دارد، بهترین راه آزاد کردن آن نیست؛ Port برنامه جدید را عوض کنید.
مثلاً برنامه Node.js:
PORT=3001 node server.js
یا در فایل Environment:
PORT=3001
بعد از تغییر پورت، Reverse Proxy، Firewall، Health Check و تنظیمات سرویسهایی که به برنامه وصل میشوند را نیز بررسی کنید.
تست نهایی بعد از رفع تداخل Port
فرض کنیم سرویس باید روی پورت 3000 باشد.
اول Listener را ببینید:
sudo ss -ltnp 'sport = :3000'
بعد از داخل خود سرور Connection را تست کنید:
curl -v http://127.0.0.1:3000/
اگر HTTP نیست، صرفاً بازبودن TCP را میتوانید با ابزارهایی مانند netcat بررسی کنید:
nc -vz 127.0.0.1 3000
اگر nc نصب نیست، نصب بسته بسته به توزیع Linux متفاوت است.
بعد از Start مجدد، لاگ سرویس را بررسی کنید
برای systemd:
sudo systemctl restart SERVICE_NAME
sudo systemctl status SERVICE_NAME
sudo journalctl -u SERVICE_NAME -n 100 --no-pager
برای Docker Compose:
docker compose up -d
docker compose ps
docker compose logs --tail=100
روال امن رفع Address Already in Use
- Port و Protocol موردنظر را مشخص کنید.
- با
ssListener فعال را پیدا کنید. - با
lsofیاfuserPID را تأیید کنید. - با
psو اطلاعات/procبرنامه را شناسایی کنید. - بررسی کنید Process متعلق به systemd، Docker، PM2 یا سرویس دیگری است.
- مشخص کنید سرویس قبلی باید Stop شود یا Port سرویس جدید تغییر کند.
- برای Stop ابتدا روش Graceful را استفاده کنید.
- بعد از تغییر، با
ssوضعیت Port را دوباره بررسی کنید. - سرویس را Start کنید و لاگ آن را بخوانید.
- با
curlیا ابزار مناسب عملکرد واقعی سرویس را تست کنید.
اجرای سرویسهای لینوکسی روی VPS
اگر برای Docker، Node.js، Python، وبسرور، دیتابیس یا سرویسهای Self-hosted به زیرساخت لینوکسی نیاز دارید، میتوانید پلنهای خرید سرور مجازی ایران ایرانیکاسرور را بررسی کنید. در سرورهای چندسرویسی بهتر است برای هر برنامه Port، Reverse Proxy و Service Manager مشخصی در نظر بگیرید تا تداخلها قابلردیابی باشند.
تماس با پشتیبانی ایرانیکاسرور: 021-91302467
Rollback؛ اگر سرویس اشتباهی را متوقف کردیم
اگر یک systemd Service را اشتباهی Stop کردهاید:
sudo systemctl start SERVICE_NAME
sudo systemctl status SERVICE_NAME
اگر Container را Stop کردهاید:
docker start CONTAINER_NAME
اگر Docker Compose است:
docker compose up -d
اگر فقط Port برنامه جدید را تغییر دادهاید و نتیجه مناسب نبود، Configuration قبلی را برگردانید و سرویس را Restart کنید.
اگر نمیدانید کدام Process را میتوان متوقف کرد
روی سرور Production قبل از Kill کردن PID یا Stop کردن سرویس ناشناس، نقش Process را مشخص کنید. اگر برای تشخیص سرویس، systemd، Docker یا Reverse Proxy به کمک نیاز دارید، میتوانید از خدمات کانفیگ و عیبیابی سرور ایرانیکاسرور استفاده کنید.
تماس با پشتیبانی ایرانیکاسرور: 021-91302467
اشتباههای رایج هنگام رفع Port Conflict
- اجرای مستقیم
kill -9بدون شناسایی Process؛ - بررسی فقط TCP در حالی که برنامه UDP است؛
- نادیده گرفتن IPv6؛
- Kill کردن
docker-proxyبهجای مدیریت Container؛ - Stop کردن دیتابیس فقط برای آزاد کردن Port؛
- Kill کردن Processای که systemd یا PM2 فوراً دوباره اجرا میکند؛
- اشتباه گرفتن Connectionهای
TIME_WAITبا Listener فعال؛ - تغییر Port برنامه بدون اصلاح Reverse Proxy یا Firewall؛
- استفاده همزمان Nginx و Apache روی یک IP و Port بدون معماری مشخص؛
- تغییر تصادفی تنظیمات Kernel برای حل یک Port Conflict ساده.
سؤالات متداول
خطای Address already in use دقیقاً یعنی چه؟
یعنی برنامه هنگام Bind کردن Socket نتوانسته آدرس موردنظر را بگیرد؛ یکی از علتهای اصلی این است که آدرس و Port قبلاً در اختیار Socket دیگری قرار دارد. در Linux این وضعیت معمولاً با خطای EADDRINUSE گزارش میشود.
چطور بفهمیم چه برنامهای Port را اشغال کرده است؟
برای TCP میتوانید از sudo ss -ltnp استفاده کنید. برای یک Port مشخص نیز lsof -i :PORT یا fuser PORT/tcp کمک میکند PID و Process مسئول را پیدا کنید.
آیا برای آزاد کردن Port باید kill -9 بزنیم؟
خیر. ابتدا باید مشخص کنید Process چیست. اگر systemd Service یا Container است، همان Service Manager را برای Stop کردن استفاده کنید. برای Process مستقل نیز ابتدا SIGTERM معمولی مناسبتر است و SIGKILL باید آخرین راه باشد.
چرا بعد از Kill کردن Process دوباره همان Port اشغال میشود؟
احتمالاً Process تحت مدیریت systemd، Docker Restart Policy، PM2، Supervisor یا سیستم مشابهی است و بهصورت خودکار دوباره اجرا میشود. باید Manager اصلی را پیدا کنید.
خطای port is already allocated در Docker را چطور رفع کنیم؟
ابتدا با docker ps --filter publish=PORT بررسی کنید کدام Container همان Host Port را Publish کرده است. سپس Container قبلی را در صورت عدم نیاز Stop کنید یا Host Port سرویس جدید را تغییر دهید.
آیا دو برنامه میتوانند از یک Port استفاده کنند؟
دو برنامه عادی نمیتوانند همزمان همان ترکیب IP، Protocol و Port را بدون تنظیمات Socket خاص در اختیار بگیرند. اگر روی IPهای متفاوت Bind شوند، در بعضی سناریوها استفاده از شماره Port یکسان ممکن است.
چرا ss روی Port چیزی نشان نمیدهد اما برنامه EADDRINUSE میدهد؟
ممکن است Protocol اشتباه را بررسی کرده باشید، Listener روی IPv6 باشد، Unix Socket درگیر باشد، Permission کافی برای مشاهده Process نداشته باشید یا شرایط Race بین Start و Stop برنامه وجود داشته باشد.
آیا TIME_WAIT همان Port اشغالشده است؟
نه لزوماً. TIME_WAIT یک وضعیت Connection TCP است و با یک Listener فعال فرق دارد. برای پیدا کردن Process اشغالکننده Port ابتدا Socketهای Listening را با ss -ltnp بررسی کنید.
جمعبندی: برای رفع Address Already in Use ابتدا Port را کورکورانه آزاد نکنید؛ Process صاحب آن را شناسایی کنید. ss ابزار اصلی برای دیدن Listenerهاست و lsof و fuser میتوانند PID را تأیید کنند. بعد مشخص کنید Process متعلق به systemd، Docker، PM2 یا برنامه مستقل است. اگر سرویس فعلی لازم است، Port برنامه جدید را تغییر دهید؛ اگر سرویس قدیمی اضافی است، آن را از Manager اصلی بهصورت Graceful متوقف کنید.






دیدگاهها (۰)