ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Node.js脚本部署到服务器自动运行的完整指南:pm2与systemd实战

Node.js脚本部署到服务器自动运行的完整指南:pm2与systemd实战 1. 先别急着敲命令想清楚自动运行到底需要做到哪一步我见过太多人在Node.js脚本部署到服务器自动运行这件事上翻车翻车原因往往不是命令敲错而是从一开始就没想明白自己到底要什么。你写好的nodejs脚本扔到服务器上之后自动运行至少有三种不同层次的要求对应的技术方案天差地别。第一层服务器开机后我的脚本能自己跑起来。这是最朴素的诉求很多个人项目、爬虫任务、定时通知脚本都属于这一类。你要做的是在系统层面注册一个自启服务Windows有计划任务Linux有systemdJava系有supervisorNode生态里则是pm2一家独大。这个层次的技术核心是注册。第二层脚本崩了之后能自己重启而不是我半夜爬起来手动拉起来。这比第一层更进一步。脚本跑着跑着因为未捕获异常、内存溢出或者某个第三方接口超时被OOM Kill了你不能指望每次都有外人帮你盯着。这一层的技术核心是守护进程需要你的启动方案具备崩溃检测 自动拉起能力。第三层代码更新后我不需要SSH登录服务器手动去拉代码、重编译、重启服务。这是接近生产环境的标准了。配合Git Webhook、CI/CD甚至简单的Cron轮询拉代码加自动重启把整个发布链路自动化。这一层的技术核心是事件驱动 编排。如果你想清楚了这三层的差异再回头看网上铺天盖地的教程会发现大多数教程只讲了第一层和第二层的某个狭缝而你真正要搭的是这三层的组合方案。下面我按准备阶段 → 首次部署 → 进程守护 → 自动更新与运维这条完整路线把每一步该怎么走、会踩什么坑、为什么这样选一次说清。2. 环境准备阶段Node版本、依赖安装和那些让你想摔键盘的报错2.1 Node环境安装别用太新的版本也别用太旧的无论你用Ubuntu、Debian还是CentOS装Node环境的思路其实都一样不要用系统自带的包管理器直接装。我为什么这么说因为apt install nodejs或yum install nodejs装出来的Node版本往往滞后两三年而很多npm包尤其是新发布的框架和SDK对Node版本有硬性要求版本不满足直接报engine冲突错误。我个人的推荐是用 nvm 来装Node。nvm的优势不仅是能切换多版本更重要的是它把Node的安装目录固定在用户家目录下升级时不用动系统文件出问题直接清掉整个目录重来干净利落。安装命令很简单# 拉取并执行nvm安装脚本 curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash # 脚本执行完会自动写入 ~/.bashrc重新登录或执行 source 生效 source ~/.bashrc # 查看远程可安装的Node版本选一个LTS的 nvm ls-remote | grep -i lts nvm install 20.15.0 # 以Node 20 LTS为例 nvm use 20.15.0 nvm alias default 20.15.0这里有个细节很多人不知道nvm alias default必须设置否则服务器一重启nvm会回到没有Node的状态系统服务里的Node命令全部失效直接导致你的自动运行脚本起不来。这不是玄学是nvm的默认行为——它不会自动记住你最后一次use的版本。关于Windows场景多说两句。热搜词里高频出现的npm : 无法将npm项识别为 cmdlet、函数、脚本文件或可运行程序的名称和npm.ps1因为在此系统上禁止运行脚本这其实是Windows PowerShell的执行策略Execution Policy在作祟。Node本身安装没问题问题出在PowerShell默认不允许执行.ps1脚本而npm的启动脚本恰恰是.ps1后缀。解决办法有两条# 方法一以管理员身份运行PowerShell修改当前用户的执行策略为RemoteSigned Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser # 方法二绕过PowerShell直接用cmd运行npm # winR 输入 cmd然后在cmd里运行 npm这两个问题经常被人误解为Node没装好或者环境变量没配置其实Nodes目录下的node.exe路径已经在PATH里了只是PowerShell在执行策略层面拦了一道。如果你是在本机开发脚本最终要部署到Linux服务器我建议Windows端只要能正常跑起来就够了不必过度纠结真正的主战场是Linux。2.2 依赖安装npm ci和npm install的差别以及node_modules该不该提交把本地跑通的nodejs脚本部署到服务器第一步是在服务器上把依赖装齐。很多初学者会直接把本地的node_modules文件夹整个上传到服务器理由是省得在服务器上装依赖。这个做法在跨平台场景下风险很大——如果你本地是Windows或macOS某些依赖里面带有原生编译的二进制文件sharp、bcrypt、canvas等这些二进制文件是平台相关的Windows下编译出来的拿到Linux上根本跑不起来。正确的做法是在服务器执行依赖安装命令cd /你的项目目录 # 首选npm ci严格按package-lock.json安装保证与本地一致 npm ci --production # 如果没生成过package-lock.json才用npm install npm install --productionnpm ci和npm install的区别值得说清楚ci会先清空node_modules再按锁文件全新安装安装结果可复现install则会根据package.json的语义化版本范围去解析最新版本可能装上与你本地不一致的依赖版本。对于部署这种场景必须使用npm ci避免本地好好的服务器上就是报错这类灵异事件。另外--production参数会跳过devDependencies里的开发依赖比如nodemon、eslint、typescript都不需要装到生产环境。如果你的脚本是用TypeScript写的记得先在本地或CI里npm run build编译出dist目录然后部署时只需上传dist、package.json和锁文件服务器上再执行npm ci --production即可。线上不装TypeScript编译器编译一次少几百MB空间启动速度也更快。3. 第一次手动部署链路从上传到用nohup跑通全流程3.1 项目上传的推荐姿势rsync远胜scp很多人第一步是scp -r local_dir userserver:/data/project把整个项目拖上去。这个方式简单粗暴但有两个痛点一是重复上传时会把本地node_modules、.git目录一并传上去浪费时间也污染服务器二是中断后没法续传。我推荐用rsync# 排除没必要上传的目录增量同步 rsync -avz --delete --exclude node_modules --exclude .git --exclude .env \ ./你的本地项目/ user服务器IP:/data/你的项目/ # 首次登录需要输入密码后面可以配置SSH密钥跳过--delete参数的含义是服务器上存在但本地已被删除的文件同步时也删掉。注意不要为了省事把--delete用在一个不存在的空目录上否则会把服务器上整个目标路径清空。建议先在服务器上建好/data/项目名这样独立的目录再执行同步。如果你的脚本不需要编译服务器上也没有数据库迁移之类的额外步骤同步完代码后在服务器上装一次依赖就可以直接尝试启动了。3.2 用nohup让脚本跑在后台原理和一个隐蔽的坑nohup是Linux下最基础的后台运行方式虽然生产环境我会用pm2替代但理解它有助于你看懂所有高级工具的底层逻辑。它的作用是让进程忽略SIGHUP信号即使你关闭SSH终端也不会被杀掉。cd /data/你的项目/ nohup node dist/index.js app.log 21 echo $! # 打印进程PID记住这个值这里讲一个非常隐蔽、非常坑爹的细节nohup ... 执行的进程它的标准输入stdin默认来自终端本身还没有被完全脱离。如果你关闭SSH会话太快某些Node脚本尤其在等待键盘输入或者末处理stdin环境的场景下可能收到一个SIGTERM或SIGHUP而被终止。解决办法是把stdin也重定向掉nohup node dist/index.js /dev/null app.log 21 多了一个 /dev/null后台进程就彻底脱离了终端的输入流。这个细节以前经常被忽略直到线上脚本总是莫名其妙在关掉终端后死掉排查了很久才意识到是stdin未脱离开的锅。启动后要立刻验证# 看进程在不在 ps aux | grep node # 看端口有没有监听如果你的脚本是Web服务 ss -lntp | grep 8080 # 看日志输出 tail -f app.log如果脚本是定时任务型而非常驻服务型它可能执行几十秒就正常退出那么nohup就不合适了——你应该把这种脚本交给系统定时器Cron或systemd timer去管理而不是让一个本该退出还赖着不走的进程占用资源。4. 自动运行的灵魂pm2与systemd两条主路线的完整实测4.1 pm2路线一条命令解决崩溃重启、开机自启和负载均衡pm2是Node生态里应用最广泛的进程管理器核心价值在于守护进程。你的脚本因为未捕获异常崩溃了pm2会在毫秒级把它重新拉起服务器重启后pm2也可以注册为系统服务随开机自启。安装pm2建议全局安装npm install -g pm2然后在项目目录下启动cd /data/你的项目/ pm2 start dist/index.js --name my-script --max-memory-restart 300M拆解一下这条命令--name指定进程别名方便后续用pm2 logs my-script查看日志而不是凭PID找。--max-memory-restart这个参数最容易被忽略。它设置内存上限超过300MB自动重启。Node脚本的一个经典毛病就是内存泄漏——某个对象被闭包长时间引用释放不掉内存曲线一路上涨最终被系统OOM Kill。有了这个参数相当于给进程上了安全气囊内存快耗尽时主动重启而不是被动等系统强杀。强杀之后如果pm2没配好可能服务宕机很久才发现主动重启最多只是几秒的抖动。启动后查看状态pm2 status你会看到类似下面的表格输出┌─────┬───────────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┐ │ id │ name │ namespace │ version │ mode │ pid │ uptime │ ↺ │ status │ cpu │ ├─────┼───────────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┤ │ 0 │ my-script │ default │ 1.0.0 │ fork │ 32104 │ 2h │ 0 │ online │ 0% │ └─────┴───────────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┘其中↺列是重启次数如果这个数字不断增长说明脚本在反复崩溃赶紧去看日志才是正事。pm2真正强大的是开机自启方案。你需要在服务器上执行# 这一步会生成一个systemd服务单元用于pm2随系统启动 pm2 startup # 保存当前进程列表让pm2下次启动时自动恢复 pm2 savepm2 startup背后做的事情其实就两件写入一个systemd service文件并且在系统启动后执行你当前用户下的pm2进程恢复。现在服务器重启后你的node脚本就真的能自动跑起来了。pm2的日志管理也是一个实用点# 查看日志--lines指定行数 pm2 logs my-script --lines 100 # 清空日志 pm2 flushpm2默认会把每个进程的输出写到~/.pm2/logs/下文件名类似my-script-out.log和my-script-error.log。后续要做日志轮转可以装pm2-logrotate扩展包pm2 install pm2-logrotate pm2 set pm2-logrotate:max_size 50M pm2 set pm2-logrotate:retain 7不做日志轮转的后果用不了多久就能体会到几百GB的日志文件把磁盘塞满应用崩了都不知道。4.2 systemd路线不装任何额外依赖用Linux原生机理接管Node进程不想装pm2的话systemd是Linux系统自带的初始化系统和服务管理器也是我见过最稳的进程守护方案——它比pm2更底层不依赖Node安装即使Node整个卸载重装systemd服务也能在你手动配好命令后继续拉起。在/etc/systemd/system/下创建一个service文件[Unit] DescriptionMy Node Script Service Afternetwork.target [Service] Typesimple Userwww-data WorkingDirectory/data/你的项目 ExecStart/usr/bin/node /data/你的项目/dist/index.js Restartalways RestartSec5 EnvironmentNODE_ENVproduction EnvironmentFile/data/你的项目/.env # 内存限制单位可以设为M或G MemoryMax300M [Install] WantedBymulti-user.target这里解释每个字段的作用Afternetwork.target确保网络就绪后再启动服务否则可能请求外部API时直接连不上。Typesimple默认类型意味着ExecStart命令本身直接作为主进程运行适合Node这类长驻型进程。Restartalways无论什么原因退出正常退出也会重启都尝试重新拉起。RestartSec5重启前的等待秒数防止进程陷入崩溃-重启-崩溃的无限循环。EnvironmentFile从文件中加载环境变量这个后面讲密钥管理还会再提。MemoryMax300M与pm2的--max-memory-restart作用类似超限时systemd会杀进程并自动重启。配置完后执行# 重新加载service配置 systemctl daemon-reload # 启用开机自启 systemctl enable my-script.service # 启动服务 systemctl start my-script.service # 查看状态 systemctl status my-script.service要查看实时日志journalctl -u my-script.service -fsystemd方案的好处是干净、原生态、不占额外内存。坏处是配置语法不如pm2简单而且像集群模式多实例负载均衡这种高级玩法要靠自己写service模板。如果只是跑单个node脚本systemd完全够用。4.3 我到底该选pm2还是systemd一张表讲清楚这个选择题其实不用纠结维度pm2systemd推荐场景学习成本低几条命令搞定中要理解service配置语法新手建议pm2日志管理自带日志与轮转扩展用journalctl简单但按服务隔离想集中看日志选pm2开机自启pm2 startup pm2 savesystemctl enable都方便内存占用额外约20-50MB看守护进程数量无额外进程占用服务器内存紧张选systemd多实例/集群内置cluster模式要用模板实例手动写多核负载均衡场景pm2更省事依赖关系依赖Node环境系统级不依赖Node要避免Node挂了守护也挂的鸡生蛋问题选systemd我个人在跑单个脚本时喜欢systemd因为服务器上Node版本升级、pm2出问题都不影响原有服务。但如果你要并发跑很多个脚本、还希望统一看日志、统一批量重启pm2的体验要比systemd舒服得多。两者并不互斥一个服务器上完全可以同时用两种方案Web服务交给pm2系统级定时任务交给systemd timer。5. 自动更新与定时执行让脚本像钟表一样自己活5.1 用Cron实现定时执行时区、环境变量和PATH三个深坑如果你的nodejs脚本属于定时跑批型比如每天凌晨拉取一次数据、每5分钟推送一次监控通知那么你需要的不是常驻进程而是定时器。Cron是最经典的选择。# 编辑当前用户的crontab crontab -e # 每天凌晨2点执行脚本 0 2 * * * cd /data/你的项目 /usr/bin/node dist/index.js /data/你的项目/cron.log 21三个坑是必须提前避开的第一时区问题。服务器上执行timedatectl查看系统时区如果是UTC那你以为的凌晨2点其实是北京时间早上10点。国内项目强烈建议统一设置为上海时区timedatectl set-timezone Asia/Shanghai第二PATH和nvm环境。Cron执行时的环境变量和你在SSH终端里不同node命令很可能找不到——因为nvm把Node安装在用户目录下的特殊路径中而Cron默认只加载一堆系统级PATH。这就是为什么我在crontab里写了完整的/usr/bin/node路径或者你也可以在crontab顶部加一行PATH/home/你的用户名/.nvm/versions/node/v20.15.0/bin:/usr/bin:/bin第三日志追加的用法。 cron.log 21既捕获stdout也捕获stderr而且用追加模式而不是覆盖模式否则上一次的日志全部丢失排查问题连个参照都没有。5.2 用systemd timer替代Cron更优雅地清理僵尸任务如果服务器用的是systemd我更推荐用systemd timer管理定时任务理由很实在日志统一走journalctl不怕Cron环境的PATH问题而且可以设置错过执行时间后补跑的机制。创建两个文件/etc/systemd/system/my-script.service[Unit] DescriptionRun My Node Script [Service] Typeoneshot WorkingDirectory/data/你的项目 ExecStart/usr/bin/node /data/你的项目/dist/index.js EnvironmentFile/data/你的项目/.env/etc/systemd/system/my-script.timer[Unit] DescriptionRun My Node Script Every Day at 2 AM [Timer] OnCalendar*-*-* 02:00:00 Persistenttrue [Install] WantedBytimers.targetTypeoneshot表示脚本执行完即退出适合批处理。Persistenttrue有个好处如果执行时间点服务器正处于关机状态开机后会补跑一次避免漏跑关键任务。最后启用systemctl daemon-reload systemctl enable --now my-script.timer说句良心话对于定时执行型脚本systemd timer oneshot service的组合比Cron更接近生产级水准排查也好、补跑也好体验都更好。5.3 自动更新Git Pull加重启的伪CI/CD方案脚本上线后最常遇到的场景是本地代码改了、推了Git然后还要SSH登录服务器git pull重启服务。偶尔一两次能接受频率一高就烦了。我分享一个低成本的伪CI/CD方案适合个人项目和小团队。思路是写一个shell脚本交给Cron或systemd timer每5分钟执行一次#!/bin/bash # /data/你的项目/deploy.sh cd /data/你的项目 # 拉取最新代码如果本地有未提交修改会失败 git fetch origin main LOCAL$(git rev-parse HEAD) REMOTE$(git rev-parse origin/main) if [ $LOCAL ! $REMOTE ]; then echo [$(date)] 检测到新版本开始部署... git pull origin main /home/你的用户名/.nvm/versions/node/v20.15.0/bin/npm ci --production # 如果有编译步骤需要先执行构建 # npm run build # 然后重启服务以pm2为例 pm2 restart my-script echo [$(date)] 部署完成 fi加上pm2你已经配好的pm2 startup这套方案能实现代码推到Git → 几分钟内服务器自动拉取并重启的效果。虽然和GitLab CI/CD比它朴素但对于个人项目来说省掉了一套CI/CD基础设施的维护成本稳定性和可理解性都高。脚本执行权限别忘了加chmod x /data/你的项目/deploy.sh用Cron每5分钟检查一次*/5 * * * * /data/你的项目/deploy.sh /data/你的项目/deploy.log 21这个方案的另一个隐藏价值在于它把你部署过程中会遇到的问题权限、路径、依赖变更全部暴露在自动化的脚本里逼着你把流程固化成可重复执行的步骤。跑几次稳定了就再也不用担心忘了部署这种低级失误了。5.4 PM2的定时任务生态cron_restart与真实的定时调度如果你已经选了pm2管理常驻进程并且想要每天凌晨自动重启进程来清理内存碎片Node长驻进程即使没有明显泄漏工作一段时间后堆内存也会碎片化升高影响性能pm2原生支持cron-restartpm2 start dist/index.js --name my-script --cron-restart 0 4 * * * --max-memory-restart 300M--cron-restart 0 4 * * *表示每天凌晨4点自动重启进程。注意这跟定时执行脚本是两码事它重启的是进程本身不是触发脚本逻辑。如果你的脚本内部用了setInterval用它来定时重启进程是完全OK的。另外pm2也可以配合Node脚本里的定时库一起用比如node-cronconst cron require(node-cron); // 每天早上9点触发任务 cron.schedule(0 9 * * *, () { console.log(run daily task); // 你的业务逻辑 });这种方式适合那些既需要长驻响应外部事件又需要在特定时刻执行批处理的混合型脚本。它和Crontab / systemd timer的区别在于进程常驻时内存和连接池可以复用定时任务触发不需要重新初始化坏处是进程必须一直活着如果因为某种原因挂了定时任务也就算了。所以混合场景我一般建议pm2守护常驻进程 cron-restart每天重置配合使用兼顾稳定性和资源回收。6. 部署后最容易翻车的六个隐藏细节6.1 环境变量和密钥不要把密码明文写在代码里很多脚本部署后跑不通不是代码逻辑问题而是数据库密码、API Key、支付密钥这些敏感信息要么没配要么就直接写死在代码里推到Git仓库带来严重安全隐患。正确姿势是用环境变量管理配置。在项目根目录创建一个.env文件已被.gitignore排除不会推送到仓库内容形如DB_HOST127.0.0.1 DB_USERroot DB_PASSWORD这里填真实密码 API_KEYsk-xxx NODE_ENVproductionNode端加载方式两种使用dotenv库require(dotenv).config()然后在代码里process.env.DB_HOST读取。如果是systemd方案直接用我之前写的EnvironmentFile/data/你的项目/.env让systemd替你把变量注入进程。pm2也有类似能力pm2 start dist/index.js --env production # 配合ecosystem.config.js里的env_production配置关键提醒不管用哪种方式都要保证.env文件权限最小化例如chmod 600 .env只有项目所属用户能读。同时检查.gitignore里是否有.env避免哪天不小心把它提交进仓库——密钥一旦进过Git历史光从最新版本删掉是不够的历史commit里还躺着完整明文。6.2 端口、防火墙与云安全组脚本在本机能跑服务器上却连不上这类问题在所有Node部署问题里占比非常高脚本在本机好好的部署到服务器后从外部访问却始终超时。原因通常不在脚本本身而在这三处叠加第一Node进程是否真的监听了0.0.0.0。如果你用app.listen(8080, 127.0.0.1)那么只能本机回环访问外部请求根本到不了你端口。正确写法应该是app.listen(8080, 0.0.0.0, () { console.log(server listening on 0.0.0.0:8080); });第二系统防火墙有没有放行端口。Linux上很多发行版默认有ufw或firewalld先用ufw status或firewall-cmd --list-all查一下。放行ufw allow 8080/tcp第三云服务商的安全组规则。阿里云、腾讯云、AWS这些云平台的实例默认都有安全组即使OS内部放行了端口安全组没加规则照样进不来。这一步经常被新手忽略排查时一定要记得去云控制台看安全组入站规则。6.3 时区错位定时任务每天在错误的点跑之前提过时区问题这里展开说。很多云服务器默认时区是UTC而国内业务通常需要北京时间。如果你只是在前端显示时做了偏移但Cron定义的是UTC时间就会出现每天凌晨2点其实是上午10点执行这种错位。解决方案分两层# 系统级时区设置 sudo timedatectl set-timezone Asia/Shanghai # 如果跑的是Docker容器还要同步容器内时区 # 可以挂载 /etc/localtime 或用TZ环境变量Node端也有时区处理的问题new Date()返回的是服务器本地时间如果你在代码里做了date.getHours()之类的判断务必确认服务器时区与预期一致。更稳妥的做法是在代码里显式指定时区计算而不是依赖操作系统默认值。6.4 OOM Kill与内存监控脚本活得好好的怎么突然没了服务器内存有限Node脚本又有内存使用膨胀的天然倾向。当系统整体内存不足时Linux内核的OOM Killer会挑选罪魁祸首进程强制杀掉而你的Node脚本往往是那个占用高又相对低优先级的目标。我的实际排查经验是当发现脚本神秘死亡时第一步执行dmesg | tail -50看看内核日志里有没有Out of memory: Kill process记录。如果有那就实锤了。解决办法给脚本加上内存上限让它在OOM之前先自我重启pm2的--max-memory-restart或systemd的MemoryMax。给服务器加swap空间虽然性能不如物理内存但至少能缓冲偶发内存尖峰。释放Node的内存压力检查代码是否有未清理的定时器、事件监听器、大数组引用。6.5 回滚预案新版本跑挂了怎么快速回到上一个稳定版本自动化部署最怕的是没有回滚能力。部署前我强烈建议把当前版本打一个轻量级快照或者用Git标签做标记git tag deploy-20240601 git push origin deploy-20240601万一新版部署后大面积报错、进程反复崩溃执行以下两步即可回到上一个稳定点# 代码回滚到上一个tag git reset --hard deploy-上一次日期 # 重装依赖并重启 npm ci --production pm2 restart my-script # 或 systemctl restart my-script对于数据写入型脚本回滚时还要考虑数据兼容性。如果新版本改了数据库结构跑了一次迁移后就回滚裸代码反而可能让旧代码和新schema不兼容。这种情况不要盲目回滚优先考虑前向修复在新代码上打补丁而不是退回旧代码。6.6 日志切分与磁盘空间监控别等磁盘爆了才看日志这是所有运维事故里最隐蔽的一类。Node脚本打印的日志默认不做什么轮转长时间运行后app.log可能膨胀到几十GB把磁盘占满然后各种服务逐一崩溃——不是脚本自身的问题是磁盘满了导致写入失败。解决靠两条腿走路一条是日志轮转。pm2用户直接装pm2-logrotate扩展前面提过不多说。systemd用户可以让journald自动管理日志大小journalctl --vacuum-size100M手动清理或者改/etc/systemd/journald.conf里的SystemMaxUse。另一条是磁盘空间监控。用脚本监测磁盘使用率并告警这条其实也适合放在同一台服务器上#!/bin/bash # disk_watch.sh THRESHOLD85 CURRENT$(df / | awk NR2 {print $5} | sed s/%//) if [ $CURRENT -gt $THRESHOLD ]; then echo [$(date)] 磁盘使用率已超过 ${THRESHOLD}%当前 ${CURRENT}% # 这里的告警可以接企业微信机器人、钉钉机器人、Telegram Bot等 fi加进Crontab每10分钟跑一次。磁盘问题通常不是突发的涨到一定水位后给你预警时间就够做清理了。7. 最后聊几句我在生产环境里的真实感受这些年在各种服务器上部署nodejs脚本踩过的坑比代码行数还多。如果你只记住几个要点我的建议排序是这样的先把环境变量和密钥管好再谈自动化部署先把崩溃重启做扎实再追求更新自动化先保证可回滚再增加复杂特性。很多时候部署方案不是被复杂问题击垮的而是被一连串不起眼的小料细节慢慢消耗信心——npm ci版本不一致、PowerShell执行策略拦截、Cron里Node命令找不到、时区差8小时这些单拎出来都不难难的是提前知道它们的存在。按我上面的流程一步步走你的nodejs脚本从本机能跑到服务器上稳定自动运行通常一个下午就能完成。头一回搭建时慢一点没关系把每一条命令的意图、每个配置文件的作用都摸透后面再换服务器、加脚本就是一键的事了。
返回列表