端口占用排查脚本:lsof 与 ss 输出对比与自动清理
线上服务起不来,最常见的报错之一是 bind: Address already in use。这时运维第一反应是 lsof -i:8080,但你是否遇到过:ss 明明显示端口被占用,lsof 却空空如也;或者反过来,lsof 列出一堆进程,ss 只给一个 LISTEN。两个工具走的是完全不同的内核数据源,理解差异才能写出靠谱的排查与清理脚本。本文给出一套可直
线上服务起不来,最常见的报错之一是 bind: Address already in use。这时运维第一反应是 lsof -i:8080,但你是否遇到过:ss 明明显示端口被占用,lsof 却空空如也;或者反过来,lsof 列出一堆进程,ss 只给一个 LISTEN。两个工具走的是完全不同的内核数据源,理解差异才能写出靠谱的排查与清理脚本。本文给出一套可直
消息队列重投、用户连点两次提交、定时任务因为上一次超时被重新调度——这些场景都会让同一条业务数据被写入两次。如果写入逻辑是「先 SELECT 判断存在再 INSERT」,在并发下会稳定地漏判:两个事务同时 SELECT 都没查到,然后都去 INSERT,最后要么产生两条脏数据,要么撞唯一索引报 Duplicate entry。把判断和写入压进一条 SQL,交
面试里问到 Redis 缓存问题,最常见的失分点不是不知道三个名词,而是把三者的触发条件讲混。很多候选人能把「布隆过滤器」「互斥锁」「随机过期时间」背出来,但面试官追问一句「一个不存在的 user_id 反复打进来,命中率没掉但 DB 的 QPS 涨了,这算哪种」,就答不上来了。本文按「怎么判定 → 为什么会发生 → 具体对策 → 代码怎么写 → 线上怎么验
抓 500 个 URL,串行 requests 要跑七八分钟;直接 asyncio.gather(*tasks) 全量并发又容易被目标站限流、被本地文件描述符耗尽打回 OSError: [Errno 24] Too many open files。真正可用的做法是:协程模型 + asyncio.Semaphore 限流 + aiohttp.TCPConnec
线上 Go 服务跑着跑着 RSS 从 80MB 涨到 900MB,GOMAXPROCS 没变、QPS 没涨,runtime.NumGoroutine() 却在单调上升——这类问题十有八九和 context.WithCancel 用得不对有关。本文从一次真实的内存增长切入,讲清 WithCancel 的传播语义、四种最常见的泄漏写法、如何用 pprof 和 g
线上服务器经常出这种事:某个目录本该只读,结果被人手动改了个配置文件;或者 /etc/nginx/conf.d 下突然多出一个 .conf,reload 之后整站 502。事后翻 ~/.bash_history 往往已经断档,审计日志又重又慢。真正需要的是一层极轻的「哨兵」:目录内容一变,几秒内就把变更路径、事件类型、操作者推到你面前。 inotify 是
Docker 默认使用 json-file 日志驱动,而且默认不做任何轮转。一个打印量稍大的服务,跑上两周就能把宿主机的 /var/lib/docker 撑满,然后你会在 docker ps 里看到容器状态变成 Up 但业务全挂,或者在 dmesg 里看到 No space left on device。更麻烦的是,日志文件被删掉之后磁盘空间并不一定释放——
集群里最容易被忽略、又最容易引发"玄学故障"的基础项,就是时间。NTP 漂移几百毫秒,可能让 JWT 校验随机失败、让 Kafka 消费者位点错乱、让分布式锁提前释放、让 ELK 里的日志时间线对不上。而这类问题往往不具备可复现性,排查成本极高。 手工逐台 ssh 上去看 chronyc tracking 的运维方式,在几十台机器规模下就完全不可接受了。本文
用 curl 做服务健康检查几乎是所有运维脚本的标配,但大多数实现只写了一行 curl -s -o /dev/null -w "%{http_code}",然后判断是否等于 200。这种写法在真实生产环境里会暴露三个问题:没有设置超时导致脚本被挂死、把「服务不可达」和「服务返回业务错误」混为一谈、无法区分 HTTP 状态码中哪些属于自身异常、哪些属于上游依赖