Two recurring deployment failures are stale listeners on app ports and unsafe manual config edits. This is the production workflow I use to solve both.
Incident pattern
Error: listen EADDRINUSE: address already in use :::3000
Diagnose the listener first
ss -lntp | grep ':3000'
lsof -i :3000
ps -fp <PID>
Controlled fix
kill -15 <PID>
sleep 2
kill -9 <PID> 2>/dev/null || true
fuser -k 3000/tcp
ss -lntp | grep ':3000' || echo 'port free'
Prevent recurrence
Use pm2 or systemd instead of background shell starts.
pm2 start ecosystem.config.js --env production
pm2 save
pm2 startup
Safe config automation
Wrong quoting:
sed -i 's/$OLD/$NEW/g' wp-config.php
Correct quoting:
sed -i "s/$OLD/$NEW/g" wp-config.php
With dry-run:
OLD_VAL=$(grep DB_NAME wp-config.php | cut -d"'" -f4 | cut -d_ -f1)
NEW_VAL=$(pwd | cut -d/ -f3)
sed "s/$OLD_VAL/$NEW_VAL/g" wp-config.php | head -n 20
sed -i "s/$OLD_VAL/$NEW_VAL/g" wp-config.php
Safety checklist
cp wp-config.php wp-config.php.bak.$(date +%F-%H%M)
php -l wp-config.php
Rollback
cp wp-config.php.bak.YYYY-MM-DD-HHMM wp-config.php
systemctl restart php-fpm
Final takeaway
Stable deployment comes from repeatable operations: precise port diagnosis, controlled process cleanup, validated automation, and immediate rollback.
This post is licensed under CC BY-NC.
Comments
Join the discussion below.
Comments are not configured yet. Add Cusdis settings in /assets/json/config/blog-comments-config.json.