杰瑞科技汇

Java程序如何在Linux后台运行?

最简单的后台运行(不推荐用于生产环境)

这是最直接的方法,适合临时测试或简单的脚本。

Java程序如何在Linux后台运行?-图1
(图片来源网络,侵删)

使用 & 符号

在命令行的末尾加上 & 符号,可以让命令在后台异步执行。

nohup java -jar your-app.jar &
  • nohup: "No Hang Up" 的缩写,它的作用是让程序忽略 SIGHUP 信号,这个信号通常在终端关闭时由系统发送给终端下的所有进程,使用 nohup 可以确保即使你关闭了 SSH 终端,程序也会继续运行。
  • &: 将命令放入后台执行。

执行后会发生什么?

  • 程序会启动,并立即返回命令提示符,你可以在终端做其他事情。
  • 程序的输出(标准输出和标准错误)会被重定向到一个名为 nohup.out 的文件中,如果这个文件已存在,新输出会被追加到文件末尾。
  • 如果当前用户没有写入权限,输出可能会被重定向到 ~/nohup.out

缺点:

  • 管理困难:一旦启动,就很难优雅地停止或重启程序,你需要手动找到进程 ID (PID),然后用 kill 命令。
  • 输出混乱:所有日志都挤在一个 nohup.out 文件里,没有日志级别区分,难以管理。
  • 无法随系统启动:需要手动配置开机自启。

使用 screentmux(推荐用于开发/调试)

screentmux 是强大的终端复用工具,它们可以创建一个持久的“会话”,你可以在其中运行程序,然后安全地断开 SSH 连接,当你重新连接时,可以“附加”回之前的会话,看到程序的实时输出。

Java程序如何在Linux后台运行?-图2
(图片来源网络,侵删)

screen 为例

  1. 创建一个新的会话

    screen -S my-java-app

    这会创建一个名为 my-java-app 的新会话,并进入该会话的终端。

  2. 在会话中启动 Java 程序

    java -jar your-app.jar

    程序现在就在这个 screen 会话中运行了,你可以看到它的实时输出。

  3. 断开会话 按下 Ctrl + A,然后松开,再按 D,你会 detached(分离)会话,但程序在后台继续运行,终端会提示 [detached from ...]

  4. 重新附加到会话 当你想查看程序状态或输出时,可以执行:

    screen -r my-java-app

    你会重新看到程序的终端界面。

  5. 停止程序 附加到会话后,像正常操作一样,按 Ctrl + C 终止程序。

优点:

  • 交互性强:可以实时查看日志,方便调试。
  • 会话持久化:断开 SSH 后程序不受影响。
  • 简单易用:基本命令很少,上手快。

缺点:

  • 不适合无人值守:如果服务器重启,screen 会话不会自动恢复,需要手动启动。
  • 不适合复杂管理:对于需要监控、自动重启、日志轮转等生产级需求,screen 仍然不够。

使用进程管理器(推荐用于生产环境)

这是在 Linux 服务器上运行长期服务的最佳实践,进程管理器可以帮你解决所有后台运行的问题:启动、停止、重启、监控日志、开机自启、资源限制等。

最流行的两个进程管理器是 systemdsupervisor

方案 A: 使用 systemd (现代 Linux 发行版首选)

systemd 是现在绝大多数现代 Linux 发行版(如 Ubuntu 16.04+, CentOS 7+, Debian 8+)的默认系统和服务管理器。

  1. 创建一个服务单元文件/etc/systemd/system/ 目录下创建一个文件,my-java-app.service

    sudo nano /etc/systemd/system/my-java-app.service
  2. 编写服务文件内容 将以下内容填入文件,并根据你的实际情况进行修改。

    [Unit]
    Description=My Awesome Java Application
    # 在网络服务启动后启动,在关机时停止
    After=network.target
    [Service]
    # 运行程序的用户,建议使用非root用户
    User=javauser
    Group=javauser
    # Java 程序的启动命令
    # 注意:确保 JAVA_HOME 已配置,或者使用完整路径的 java
    ExecStart=/usr/bin/java -jar /path/to/your-app.jar --spring.profiles.active=prod
    # 重启策略
    # on-failure: 当进程非正常退出时(退出码非0)重启
    # always: 总是重启
    Restart=on-failure
    RestartSec=10s # 重启前等待10秒
    # 设置工作目录,程序会在此目录下查找配置文件等
    WorkingDirectory=/path/to/your-app-dir
    # 标准输出和标准错误重定向到 journalctl
    StandardOutput=journal
    StandardError=journal
    # 环境变量(可选)
    Environment="JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64"
    [Install]
    # 开机自启的级别
    WantedBy=multi-user.target
  3. 管理服务

    • 重新加载 systemd 配置

      sudo systemctl daemon-reload
    • 启动服务

      sudo systemctl start my-java-app
    • 停止服务

      sudo systemctl stop my-java-app
    • 重启服务

      sudo systemctl restart my-java-app
    • 查看服务状态

      sudo systemctl status my-java-app
    • 设置开机自启

      sudo systemctl enable my-java-app
    • 禁用开机自启

      sudo systemctl disable my-java-app
    • 查看日志 systemd 的日志集成在 journalctl 中。

      # 查看实时日志
      sudo journalctl -u my-java-app -f
      # 查看最近的100行日志
      sudo journalctl -u my-java-app --lines 100

优点:

  • 功能强大:支持启动、停止、重启、依赖管理、资源限制(CPU, 内存)、日志管理等。
  • 与系统集成:是操作系统的一部分,开机自启、关机处理非常可靠。
  • 标准化:是 Linux 服务的标准管理方式。

方案 B: 使用 supervisor (Python 写的,跨平台)

supervisor 是一个用 Python 写的进程管理工具,非常成熟和稳定,也广泛用于生产环境。

  1. 安装 supervisor

    # Debian/Ubuntu
    sudo apt-get update
    sudo apt-get install supervisor
    # CentOS/RHEL
    sudo yum install supervisor
  2. 创建配置文件 supervisor 的配置文件通常在 /etc/supervisor/conf.d/ 目录下,创建一个新文件,my-java-app.conf

    sudo nano /etc/supervisor/conf.d/my-java-app.conf
  3. 编写配置文件内容

    [program:my-java-app]
    command=/usr/bin/java -jar /path/to/your-app.jar --spring.profiles.active=prod
    directory=/path/to/your-app-dir
    user=javauser
    autostart=true
    autorestart=true
    startsecs=5
    stopwaitsecs=10
    redirect_stderr=true
    stdout_logfile=/var/log/supervisor/my-java-app.log
  4. 管理 supervisor

    • 更新配置并启动程序

      # 读取所有新配置或修改过的配置文件
      sudo supervisorctl update
      # 启动 my-java-app 程序
      sudo supervisorctl start my-java-app
    • 停止程序

      sudo supervisorctl stop my-java-app
    • 重启程序

      sudo supervisorctl restart my-java-app
    • 查看状态

      sudo supervisorctl status
    • 查看日志

      # 日志文件由配置文件中的 stdout_logfile 指定
      tail -f /var/log/supervisor/my-java-app.log
      # 或者使用 supervisorctl 的 tail 命令
      sudo supervisorctl tail my-java-app

优点:

  • 配置简单ini 格式的配置文件比 systemd 的单元文件更直观。
  • 跨平台:不仅限于 Linux。
  • 功能完善:同样支持自动重启、日志管理等。

总结与推荐

方法 优点 缺点 适用场景
nohup & 极其简单,无需额外工具 管理困难,日志混乱,无法自启 临时任务、快速测试、调试脚本
screen / tmux 交互性强,可实时查看日志 不适合无人值守,管理功能弱 开发调试、需要交互式查看输出的后台任务
systemd 功能最强大,与系统集成度高,是现代 Linux 标准 配置稍复杂,有学习曲线 生产环境、长期运行的服务、需要开机自启的服务
supervisor 配置简单直观,成熟稳定 功能略少于 systemd,是第三方工具 生产环境、特别是非 systemd 系统或偏好 Python 生态的环境

最终建议:

  • 对于任何严肃的生产环境部署,请毫不犹豫地选择 systemd,它是目前 Linux 服务的黄金标准,提供了最全面和可靠的保障。
  • 对于个人开发或需要频繁交互调试的场景screen 是一个非常高效和便捷的工具。
  • 避免在生产环境中单独使用 nohup & 来管理长期服务,除非你非常清楚它的局限性并愿意手动处理所有后续问题。
分享:
扫描分享到社交APP
上一篇
下一篇