程序出问题怎么查,以及如何让它不掉线

上一篇把程序跑起来了,但好日子没几天。第一天你 ssh 进去想看一眼,结果什么都没有,程序不知道什么时候挂了。第二天终于跑住了,你一关终端窗口,它又没了。服务器上的程序活得像个需要人盯着的孩子,问题就出在你对「进程、日志、端口、终端」这几件事没有完整的认识。这篇把排查和保活一起讲透,学完你的程序才真正算「部署完成」。

问题来了,先搞清楚程序还活着没

判断程序生死,靠的是 ps 这个查看进程的命令。aux 三个字母的组合表示显示所有进程的完整信息,

bash 复制代码
ps aux | grep python

grep python 是从输出里筛选关键词。看到一行包含你程序名的记录,说明它还活着,第二列的数字是它的进程号(PID),后面排查和杀进程都要用到。什么都没有,说明已经退出了。

还有一种「活着但没反应」的状态,程序进程在,但服务没响应。这种时候就不该再看进程了,往下走,看日志和端口。

病根基本都在日志里

程序把运行情况写进日志文件,这是排查的第一现场。实时跟踪日志输出,

bash 复制代码
tail -f 你的日志文件路径

-f 表示持续跟踪,新写入的内容会实时滚出来。看完按 Ctrl+C 退出跟踪。

按惯例讲,日志不是垃圾信息,崩溃前最后几行往往直接写着原因。最常见的两种,没找到文件,路径配置错;连不上外部服务,数据库或 API 的地址、端口不对。大多数程序挂掉,根因就藏在这几行里。

顺带提一句,服务器的资源情况也值得瞄一眼,

bash 复制代码
free -h    # 看内存
df -h      # 看磁盘

程序突然「不知道为什么崩了」,很多时候是内存被吃满或者磁盘写满了。你想想看,程序一崩就去看代码,但资源和日志往往先于代码暴露真相。这两个命令的输出是即时的,内存看 free -h 的 available 列,磁盘看 df -h 的 Use% 列,超过 90% 就该动手清理了。先看资源再看代码,很多玄学问题当场就破了案。

端口被占,web 服务的老事故

如果你的程序要对外提供服务,会监听一个端口。端口被占用是 web 类应用的经典事故,比如你昨天部署的另一个服务还占着 8000,新程序自然起不来,报错可能是「Address already in use」也可能是别的,反正看日志不一定能一眼看出来。

查看本机端口监听情况,

bash 复制代码
ss -tlnp

ss 是查看网络连接的命令,-t 只看 TCP,-l 只看监听中的,-n 显示数字端口,-p 显示占用进程。看到目标端口后面跟着别的程序名,就是它把路堵了。

三件套到此就齐了,ps 看进程、tail 看日志、ss 看端口。它们针对的是三类不同的问题,进程不在了是程序崩溃,进程在但服务没反应是内部错误或资源耗尽,端口被占是新起的服务起不来。记住了这个对应关系,排查就不会像无头苍蝇。

排查铁律,先确认问题类型,再选对应工具。进程、日志、端口,三类问题三件工具,别用错方向。

杀掉僵住的进程

程序僵住了,比如卡在死循环里,这时候的诉求从「查」变成「杀」。还是用前面学的,找到进程号再动手,

bash 复制代码
ps aux | grep 你的程序

kill 进程号        # 正常终止
kill -9 进程号     # 强制杀掉,最后手段

kill 默认发温和的终止信号,给了程序善后时间。-9 是强制击杀,用于前面那招无效的情况。注意别把 PID 搞错,杀错进程是新手最容易犯的事故。

让程序脱离你的终端

回到开头那个问题,程序明明起来了,一关 SSH 窗口就消失。原因是终端关闭时,系统会给这个终端下的所有进程发一个挂断信号(SIGHUP),进程收到信号就默认退出了。

逃出这个限制有两个手段,

bash 复制代码
python main.py &          # 后台运行

nohup python main.py &    # 后台运行 + 忽略挂断信号

& 把进程丢到后台,nohup 让进程无视终端的关闭信号。配合日志重定向,程序就彻底脱离了你的终端,

bash 复制代码
nohup python main.py > app.log 2>&1 &

这条命令的每一个零件都值得记住,> 是输出重定向,2>&1 表示把报错也一并写进日志,末尾的 & 是后台运行。之后不管终端怎么关,程序照跑,日志都进 app.log

但 nohup 有个短板,它只管「不死」,不管「想不想让它休」。程序占着前台,你想再进服务器做点别的事都难,更别说回头再看一眼程序界面。想要重新看到程序舍不得放的输出,得靠 tmux。

tmux,把整个终端会话托管起来

tmux(terminal multiplexer,终端复用器)是跑在服务器上的一个守护进程,它把你打开的终端窗口托管起来,即使 SSH 连接断开,窗口和里面跑的程序依旧留在服务器上。

区别在哪,nohup 是「让程序活下来」,tmux 是「让整个终端会话活下来」。其实这俩不冲突,只是解决两个不同层面的问题。前者你只能靠日志确认程序状态,后者你可以随时再连回去,重新看到那个界面,继续跟程序交互。

终端会话与进程存活是两件事,tmux 管的是前者,nohup 管的是后者。

Ubuntu 20.04 之后基本都自带 tmux,没有就一条命令安装,

bash 复制代码
sudo apt install -y tmux

tmux 的日常操作只有三个,新建会话、离开会话、回到会话。

bash 复制代码
tmux new -s myapp

python main.py

-s myapp 是给会话起名,之后按名字找它。程序开始在会话里跑起来后,按 Ctrl+B 再按 D,脱离会话。这是 tmux 的核心操作,先按组合键,松开,再按 D,不要一起按。

此时你又回到了普通 SSH 命令行,但程序还在那个会话里继续跑。下次登录服务器,随时回到会话,

bash 复制代码
tmux attach -t myapp

程序的原界面立刻出现在你眼前,就跟从未离开过一样。不再需要了,先 attach 进去退出程序,或直接删会话,

bash 复制代码
tmux kill-session -t myapp

会话活着的时候,里面还有几个高频操作值得记下。

快捷键 作用
Ctrl+B 然后 D 脱离会话,程序继续跑
Ctrl+B 然后 C 在会话里开一个新终端窗口
Ctrl+B 然后 N 切换到下一个窗口
Ctrl+B 然后 0-9 直接跳到对应编号的窗口

打开多个窗口这个能力很实用。一个窗口跑程序盯日志,另一个窗口继续敲命令操作服务器,互不干扰,这是纯 nohup 方案给不了的自由度。

坦率讲,tmux 适合「手工挂机」场景,但有一类需求它管不了。服务器重启、程序崩溃自动拉起、开机自启,这些 tmux 都做不到,那是 systemd 的领域。

维度 tmux systemd
本质 终端会话托管 系统服务管理
适配场景 手动挂机、开发调试 生产服务、开机自启
崩溃自动重启 不行 可以
学习成本 低,一篇学会 较高,要写配置

判断标准很简单,自己手动跑着玩的工具用 tmux。要 7x24 对外提供服务、机器重启后要自动恢复的,去学 systemd 服务文件。

生产级的路还有多远

两篇的路走到这里收个尾。回头看全套流程,买的是一台永远在线的电脑,进出靠 SSH,文件靠 tar 和 scp,环境靠 venv 和镜像源,出问题靠 ps、tail、ss 三件套,保活靠 nohup 和 tmux。每一步解决的其实都是同一件事,让程序离开你的电脑也能可靠运行。

  • 进程不在了查 ps,服务没反应查 tail,端口被占查 ss,先分型再动手
  • free 和 df 瞄一眼资源,很多玄学崩溃当场破案
  • nohup 让进程活,tmux 让会话活,两者搭配各司其职
  • tmux 三连,new 建会话、attach 回会话、kill 删会话,Ctrl+B 是总开关
  • 要崩溃自动拉起、开机自启,从 systemd 入门开始

再往下进阶的方向也给你列好。域名解析与 Nginx 反向代理,让服务有名字、走 80/443 端口;crontab 定时任务,让服务器到点自动干活;systemd 服务化,把生产级保活讲透。服务器这扇门已经推开了,剩下的路走得越深越好玩。

相关推荐
雾时之林1 小时前
Linux----cron定时服务
linux·运维·服务器
这个DBA有点耶1 小时前
3000万个应用共享一套数据库:多租户“逻辑表”架构是如何做到的?
数据库·架构·dba
壹玖玖肆1 小时前
医院后勤智能运维系统实用性评测
运维
测试运维日常笔记1 小时前
Oracle 数据库连接认证方式详解
数据库·oracle
数据知道2 小时前
反序列化漏洞:Java、PHP、Python 三条线各讲透
java·网络·python·安全·网络安全·php
2601_949950632 小时前
Java 面试准备,用练题簿把“背过八股”变成“真正会答”
java·开发语言·面试·刷题·小程序推荐
ClouGence2 小时前
PostgreSQL 同步到 Iceberg:开源、私有部署与 SaaS 方案对比
数据库·postgresql·开源
無限進步D2 小时前
Java 函数式编程(Lambda)
java·开发语言
这个DBA有点耶2 小时前
DBA进阶之路:从“修数据库”到“管架构债”
数据库·架构·dba