脚本在本地跑得稳,搬到服务器上却常出问题。终端一关进程就没了,服务器重启后任务没人拉起,有时脚本悄悄报错退出,几天后才发现数据断了一截。所以脚本挂阿里云服务器,难点通常在断线、重启和出错之后,它还能不能自己恢复。让它先跑起来,反而是最容易的一步。这里借一位朋友的例子说明问题出在哪,再讲守护方式、安全设置和上线前的检查项。

从一个抓取脚本的遭遇说起
一位做电商选品的朋友写了个 Python 脚本,每十分钟抓一次竞品价格,写进 MySQL。在自己笔记本上跑得不错,可笔记本一合盖,数据就出现缺口。于是他买了台阿里云 ECS,打算把脚本搬上去。
他第一次直接在 SSH 终端里运行 python3 spider.py,关掉终端,脚本也跟着没了。接着他在命令后面加了 & 放到后台,能跑,但服务器一重启又得手动来一遍。两周后,数据库里出现了一段三天的空白。原因是网络超时抛了异常,脚本直接退出,没有任何提醒。
这几个坑很典型:进程和终端绑在一起,开机不会自动拉起,异常也没人知道。下面逐个处理。
先让脚本能独立跑起来
守护之前,先确认脚本在服务器上不依赖你本机的环境。这一步看着琐碎,但很多故障都出在这里。
- 用虚拟环境装依赖,别用系统自带的 Python 包,用 venv 或 conda 隔离,并把 requirements.txt 一起传上去。
- 路径用绝对路径,配置文件和日志文件都写完整路径。进程的工作目录和你手动执行时不一样,相对路径很容易找不到文件。
- 密码和密钥不写进代码,数据库密码、API 密钥走环境变量或独立的配置文件,别硬编码,更别提交到代码仓库。
- 先手动跑一遍,在服务器上直接执行一次,确认依赖齐全、目标地址能访问、数据库连接正常。
选对守护方式
长期运行的脚本常见有三种做法。选之前先分清脚本是跑完就退出,还是一直运行。
nohup、screen 和 tmux
nohup 能让进程在退出终端后继续跑,并把输出重定向到日志文件,大致可以这样写:
nohup python3 /opt/spider/spider.py > /opt/spider/run.log 2>&1 &
上手最快,适合临时跑一下的任务。短板也很明显:服务器重启后不会恢复,进程挂了也没人管。screen 和 tmux 把任务挂在一个可以随时重连的会话里,方便看输出,但同样解决不了开机自启和崩溃重启的问题。
crontab 定时触发
如果脚本是定期执行一次、跑完就退出的类型,crontab 最合适。比如每十分钟执行一次,可以这样写:
*/10 * * * * /usr/bin/python3 /opt/spider/spider.py >> /opt/spider/cron.log 2>&1
它简单,系统自带,重启后依然有效。有两个地方要留意。cron 的环境变量很少,最好在脚本里写明解释器的完整路径。另外,如果上一轮还没结束,下一轮又触发了,就会重复执行,可以用 flock 加一把文件锁挡住。
systemd 常驻守护
对于需要持续运行的服务型脚本,比如一直监听消息队列的消费者,推荐 systemd。它支持开机自启、崩溃后自动拉起,还能统一查看状态。一个最简单的服务文件长这样:
[Unit]
Description=price spider
After=network.target
[Service]
ExecStart=/opt/spider/venv/bin/python /opt/spider/spider.py
WorkingDirectory=/opt/spider
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
保存到 /etc/systemd/system/spider.service 后,执行 systemctl daemon-reload,再用 systemctl enable –now spider 启动。之后用 systemctl status spider 看状态,用 journalctl -u spider 看日志。团队如果更习惯 Python 生态,supervisor 也能做到类似的事,配置思路相近,同样支持自动重启。
回到那位朋友的方案
他的脚本是持续抓取,但每一轮本身是有限的任务,所以最后选的是 systemd 加脚本内部的循环和异常捕获。他做了三处调整。
- 主循环里用 try/except 包住单次抓取。网络超时只记一条日志,等下一轮再来,进程不退出。
- systemd 设置 Restart=always,即使真的崩溃也能被拉起。
- 在阿里云控制台开通云监控,给服务器的 CPU、内存设置告警,并把关键节点的失败日志推送到钉钉机器人。
调整之后,他连续运行了两个月,没有再出现数据断档。他觉得,“脚本能跑”和“脚本能稳定地跑”之间隔着的,主要是异常处理、自启动和告警这一层。
上线前的安全和日志
脚本挂在公网服务器上,安全不能靠运气。以下几项最好在上线前做完。
- 安全组只开必要端口,如果脚本只需要主动访问外网,入方向就不用开额外端口,SSH 也只放行可信的来源 IP。
- 关掉密码登录,改用 SSH 密钥,并禁止 root 直接远程登录。
- 日志做轮转,长期运行的脚本日志会越长越大,用 logrotate 按天或按大小切分,免得占满磁盘。
- 核心数据要有备份,可以用阿里云快照,也可以用数据库自身的备份功能,并定期检查备份能不能恢复。
上线前检查清单
每次部署前对照以下几条过一遍。
- 依赖在虚拟环境里固定了版本,并在服务器上手动跑通过一次。
- 配置和密钥与代码分开,没有明文进仓库。
- 守护方式已选定:定时任务用 crontab,常驻服务用 systemd,并设置开机自启。
- 单次失败有兜底,不会让整个进程退出。
- 日志路径明确、已配轮转,出问题时能快速找到。
- 安全组和 SSH 登录方式已加固。
- 至少配置了基础告警,能知道脚本是不是停了。
脚本挂阿里云服务器本身不复杂。费功夫的是把“跑起来”变成“长期稳定地跑”。先选对守护方式,再把日志、告警和安全补齐,大部分问题都能提前避开。