程序出问题怎么查,以及如何让它不掉线
上一篇把程序跑起来了但好日子没几天。第一天你 ssh 进去想看一眼结果什么都没有程序不知道什么时候挂了。第二天终于跑住了你一关终端窗口它又没了。服务器上的程序活得像个需要人盯着的孩子问题就出在你对「进程、日志、端口、终端」这几件事没有完整的认识。这篇把排查和保活一起讲透学完你的程序才真正算「部署完成」。问题来了先搞清楚程序还活着没判断程序生死靠的是ps这个查看进程的命令。aux三个字母的组合表示显示所有进程的完整信息psaux|greppythongrep python是从输出里筛选关键词。看到一行包含你程序名的记录说明它还活着第二列的数字是它的进程号PID后面排查和杀进程都要用到。什么都没有说明已经退出了。还有一种「活着但没反应」的状态程序进程在但服务没响应。这种时候就不该再看进程了往下走看日志和端口。病根基本都在日志里程序把运行情况写进日志文件这是排查的第一现场。实时跟踪日志输出tail-f你的日志文件路径-f表示持续跟踪新写入的内容会实时滚出来。看完按CtrlC退出跟踪。按惯例讲日志不是垃圾信息崩溃前最后几行往往直接写着原因。最常见的两种没找到文件路径配置错连不上外部服务数据库或 API 的地址、端口不对。大多数程序挂掉根因就藏在这几行里。顺带提一句服务器的资源情况也值得瞄一眼free-h# 看内存df-h# 看磁盘程序突然「不知道为什么崩了」很多时候是内存被吃满或者磁盘写满了。你想想看程序一崩就去看代码但资源和日志往往先于代码暴露真相。这两个命令的输出是即时的内存看free -h的 available 列磁盘看df -h的 Use% 列超过 90% 就该动手清理了。先看资源再看代码很多玄学问题当场就破了案。端口被占web 服务的老事故如果你的程序要对外提供服务会监听一个端口。端口被占用是 web 类应用的经典事故比如你昨天部署的另一个服务还占着 8000新程序自然起不来报错可能是「Address already in use」也可能是别的反正看日志不一定能一眼看出来。查看本机端口监听情况ss-tlnpss是查看网络连接的命令-t只看 TCP-l只看监听中的-n显示数字端口-p显示占用进程。看到目标端口后面跟着别的程序名就是它把路堵了。三件套到此就齐了ps看进程、tail看日志、ss看端口。它们针对的是三类不同的问题进程不在了是程序崩溃进程在但服务没反应是内部错误或资源耗尽端口被占是新起的服务起不来。记住了这个对应关系排查就不会像无头苍蝇。排查铁律先确认问题类型再选对应工具。进程、日志、端口三类问题三件工具别用错方向。杀掉僵住的进程程序僵住了比如卡在死循环里这时候的诉求从「查」变成「杀」。还是用前面学的找到进程号再动手psaux|grep你的程序kill进程号# 正常终止kill-9进程号# 强制杀掉最后手段kill默认发温和的终止信号给了程序善后时间。-9是强制击杀用于前面那招无效的情况。注意别把 PID 搞错杀错进程是新手最容易犯的事故。让程序脱离你的终端回到开头那个问题程序明明起来了一关 SSH 窗口就消失。原因是终端关闭时系统会给这个终端下的所有进程发一个挂断信号SIGHUP进程收到信号就默认退出了。逃出这个限制有两个手段python main.py# 后台运行nohuppython main.py# 后台运行 忽略挂断信号把进程丢到后台nohup让进程无视终端的关闭信号。配合日志重定向程序就彻底脱离了你的终端nohuppython main.pyapp.log21这条命令的每一个零件都值得记住是输出重定向21表示把报错也一并写进日志末尾的是后台运行。之后不管终端怎么关程序照跑日志都进app.log。但 nohup 有个短板它只管「不死」不管「想不想让它休」。程序占着前台你想再进服务器做点别的事都难更别说回头再看一眼程序界面。想要重新看到程序舍不得放的输出得靠 tmux。tmux把整个终端会话托管起来tmuxterminal multiplexer终端复用器是跑在服务器上的一个守护进程它把你打开的终端窗口托管起来即使 SSH 连接断开窗口和里面跑的程序依旧留在服务器上。区别在哪nohup 是「让程序活下来」tmux 是「让整个终端会话活下来」。其实这俩不冲突只是解决两个不同层面的问题。前者你只能靠日志确认程序状态后者你可以随时再连回去重新看到那个界面继续跟程序交互。终端会话与进程存活是两件事tmux 管的是前者nohup 管的是后者。Ubuntu 20.04 之后基本都自带 tmux没有就一条命令安装sudoaptinstall-ytmuxtmux 的日常操作只有三个新建会话、离开会话、回到会话。tmux new-smyapp python main.py-s myapp是给会话起名之后按名字找它。程序开始在会话里跑起来后按CtrlB再按D脱离会话。这是 tmux 的核心操作先按组合键松开再按 D不要一起按。此时你又回到了普通 SSH 命令行但程序还在那个会话里继续跑。下次登录服务器随时回到会话tmux attach-tmyapp程序的原界面立刻出现在你眼前就跟从未离开过一样。不再需要了先 attach 进去退出程序或直接删会话tmux kill-session-tmyapp会话活着的时候里面还有几个高频操作值得记下。快捷键作用CtrlB 然后 D脱离会话程序继续跑CtrlB 然后 C在会话里开一个新终端窗口CtrlB 然后 N切换到下一个窗口CtrlB 然后 0-9直接跳到对应编号的窗口打开多个窗口这个能力很实用。一个窗口跑程序盯日志另一个窗口继续敲命令操作服务器互不干扰这是纯 nohup 方案给不了的自由度。坦率讲tmux 适合「手工挂机」场景但有一类需求它管不了。服务器重启、程序崩溃自动拉起、开机自启这些 tmux 都做不到那是 systemd 的领域。维度tmuxsystemd本质终端会话托管系统服务管理适配场景手动挂机、开发调试生产服务、开机自启崩溃自动重启不行可以学习成本低一篇学会较高要写配置判断标准很简单自己手动跑着玩的工具用 tmux。要 7x24 对外提供服务、机器重启后要自动恢复的去学 systemd 服务文件。生产级的路还有多远两篇的路走到这里收个尾。回头看全套流程买的是一台永远在线的电脑进出靠 SSH文件靠 tar 和 scp环境靠 venv 和镜像源出问题靠 ps、tail、ss 三件套保活靠 nohup 和 tmux。每一步解决的其实都是同一件事让程序离开你的电脑也能可靠运行。进程不在了查 ps服务没反应查 tail端口被占查 ss先分型再动手free 和 df 瞄一眼资源很多玄学崩溃当场破案nohup 让进程活tmux 让会话活两者搭配各司其职tmux 三连new 建会话、attach 回会话、kill 删会话CtrlB 是总开关要崩溃自动拉起、开机自启从 systemd 入门开始再往下进阶的方向也给你列好。域名解析与 Nginx 反向代理让服务有名字、走 80/443 端口crontab 定时任务让服务器到点自动干活systemd 服务化把生产级保活讲透。服务器这扇门已经推开了剩下的路走得越深越好玩。