努力
加油

在Linux服务器上怎样同时运行多个代码实例?

在 Linux 服务器上同时运行多个代码实例,核心思路其实就两个:隔离和调度。

根据你跑的代码类型(是 Web 服务、后台任务、还是交互式脚本)以及资源需求,有几种主流且成熟的方案。别整那些虚的,直接上干货,按场景分类:

1. 最轻量级:终端复用工具 (Screen / Tmux)

如果你只是想在 SSH 连接断开后让程序继续跑,或者在一个终端里开好几个窗口分别看不同日志,这是首选。

  • 适用场景:运维调试、临时运行脚本、需要实时查看输出但不希望被中断的场景。
  • 优点:系统自带,零配置,资源占用极低。
  • 缺点:不是真正的“进程管理”,如果服务器重启,Session 还在但进程可能会挂(取决于具体实现和信号处理),不适合生产环境长期托管。

操作示例 (Tmux):

# 安装
yum install tmux  # CentOS/RHEL
apt install tmux  # Ubuntu/Debian

# 创建会话
tmux new -s my_project

# 在里面运行你的代码
python3 app.py

# 快捷键分离会话:Ctrl+b, 然后按 d
# 重新连接:tmux attach -t my_project

注:现在大家更推荐用 tmux 而不是 screen,因为 tmux 支持分屏、复制粘贴体验更好,且在云原生时代兼容性更强。

2. 标准生产方案:Systemd Service

这是 Linux 发行版(CentOS 7+, Ubuntu 16.04+)的标准做法。把每个代码实例注册为一个 Systemd 服务。

  • 适用场景:Web 应用、常驻后台进程、需要开机自启、崩溃自动重启的服务。
  • 优点:原生集成,支持依赖管理、日志收集(journalctl)、权限控制、优雅重启。
  • 缺点:每增加一个实例就要写一个 .service 文件,实例多了配置文件会爆炸。

操作示例:
假设你要跑 3 个 Node.js 实例,监听不同端口或处理不同数据流。

  1. 创建 /etc/systemd/system/myapp@.service (注意那个 @,表示它是模板单元)。
  2. 内容大致如下:

    [Unit]
    Description=My App Instance %i
    After=network.target
    
    [Service]
    Type=simple
    User=www-data
    WorkingDirectory=/var/www/myapp
    ExecStart=/usr/bin/node /var/www/myapp/index.js --instance-id=%i
    Restart=always
    EnvironmentFile=/etc/default/myapp-%i.env
    
    [Install]
    WantedBy=multi-user.target
  3. 启动三个实例:
    systemctl start myapp@1.service
    systemctl start myapp@2.service
    systemctl start myapp@3.service

    技巧:通过 %i 获取实例 ID,可以在代码里动态读取环境变量或配置文件,实现逻辑隔离。

3. 容器化方案:Docker + Docker Compose

现在互联网大厂和绝大多数初创公司都在用这个。即使你没用 K8s,单机跑 Docker 也是最佳实践。

  • 适用场景:微服务架构、多语言混合部署、依赖复杂、需要环境一致性。
  • 优点:环境隔离彻底(互不干扰),迁移方便,扩展性强。
  • 缺点:有一定学习曲线,需要维护镜像。

操作示例 (docker-compose.yml):

version: '3'
services:
  worker-1:
    image: my-node-app
    command: node worker.js --id 1
    ports:
      - "3001:3000"
  worker-2:
    image: my-node-app
    command: node worker.js --id 2
    ports:
      - "3002:3000"
  worker-3:
    image: my-node-app
    command: node worker.js --id 3
    ports:
      - "3003:3000"

启动命令:docker-compose up -d。这样你就有了三个完全隔离的进程,各自占自己的 CPU 和内存配额(可以通过 deploy.resources 限制)。

4. 进程管理器:PM2 / Supervisor

如果你的代码是 Python、Node.js、PHP 等解释型语言,这些专用管理器比 Systemd 更懂业务逻辑。

  • PM2 (Node.js/JS):

    pm2 start app.js --name "app-1"
    pm2 start app.js --name "app-2"
    pm2 scale app 3  # 一键扩容到 3 个实例,负载均衡

    PM2 内置了集群模式(Cluster Mode),可以自动利用多核 CPU,并处理负载均衡,非常适合 Node.js。

  • Supervisor (Python/通用):
    适合 Python 项目。配置简单,能监控子进程状态,崩溃后自动拉起。

5. 高级调度:Kubernetes (K8s) / ECS / ACK

如果你的实例数量达到几十上百,或者需要动态扩缩容,那就得上编排引擎了。

  • 国内厂商对应产品:
    • 阿里云:ACK (Kubernetes) 或 ECS 弹性伸缩组。
    • 腾讯云:TKE 或 SCF (Serverless 函数计算,按调用次数计费,适合突发流量)。
    • 华为云:CCE。
  • 适用场景:大规模分布式系统、高可用要求、自动化运维。
  • 优点:自愈能力极强,滚动更新无停机,资源利用率最大化。
  • 缺点:架构复杂,运维成本高,小团队没必要。

如何选择?决策树建议

  1. 你是个人开发者/小团队,跑几个测试脚本?
    👉 用 Tmux。简单粗暴,断线重连不掉线。

  2. 你是正经做线上服务,比如一个 Web API 或后台 Worker?
    👉 用 Systemd (通用性最强) 或 Docker (环境隔离最好)。

    • 如果不想折腾 Docker,Systemd 是最稳的选择。
    • 如果需要频繁更新版本且不希望影响其他服务,Docker 更好。
  3. 你是 Node.js 项目,想利用多核并发?
    👉 用 PM2 Cluster Mode。它帮你做了负载均衡和进程守护,省心。

  4. 你是 Python 项目?
    👉 用 Supervisor 或者 Gunicorn/uWSGI (如果是 Web 框架)。Gunicorn 本身就可以指定 worker 数量 (gunicorn -w 4 app:app),这就是一种“多实例”运行方式。

  5. 实例很多,需要自动扩缩容?
    👉 上 K8s 或云厂商的 Serverless/FaaS。

关键注意事项(避坑指南)

  1. 端口冲突:多个实例如果都绑定 0.0.0.0:8080,第二个肯定起不来。要么用不同端口,要么前面加 Nginx/HAProxy 做反向XX和负载均衡。
  2. 资源争抢:Linux 默认没有硬性的 CPU/内存限制。如果 10 个 Java 实例一起跑,可能把机器撑爆。
    • 解法:使用 Systemd 的 CPUQuota= 和 MemoryLimit=;或者直接用 Docker/K8s 的资源限制功能。
  3. 日志混乱:多个实例往同一个日志文件写,会导致日志交错。
    • 解法:每个实例必须有自己的独立日志文件(如 app-1.log, app-2.log),或者接入 ELK/Loki 等集中式日志系统。
  4. 锁文件竞争:如果多个实例操作同一个本地文件(如 SQLite 数据库),会有并发写入问题。
    • 解法:改用 MySQL/PostgreSQL 等支持并发的事务型数据库,或者使用 Redis 做分布式锁。

总结一句话:小项目用 Tmux/Superivsor,中项目用 Systemd/Docker,大项目上 K8s。 别为了用技术而用技术,选最适合当前规模的那个。