You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

通过SSH在Windows启动后台进程,断开后进程不终止的问题

解决Jenkins SSH执行PowerShell脚本后Java进程被终止的问题

问题根源

通过SSH远程执行PowerShell脚本时,SSH会话会创建专属进程组,原脚本中Start-Process启动的javaw进程默认隶属于该组。当脚本执行完毕、SSH会话关闭时,系统会终止该进程组下的所有子进程,导致Java应用被强制杀死。

解决方案

方法1:调整PowerShell的Start-Process参数

在原脚本中为Start-Process添加-CreateNoWindow、-WindowStyle Hidden和-NoNewWindow参数,让进程脱离SSH会话的控制台控制:

$SSL_KEYSTORE_PASSWORD = $args[0]
Write-Output "Running war in the background"
Start-Process javaw -ArgumentList "-jar", `
    "e:\app\app.war", `
    $("-Dserver.ssl.key-store-password=" + $SSL_KEYSTORE_PASSWORD), `
    "-Dserver.tomcat.basedir=e:\app" `
    -RedirectStandardOutput "e:\app\output\stdout.txt" `
    -RedirectStandardError "e:\app\output\stderr.txt" `
    -CreateNoWindow `
    -WindowStyle Hidden `
    -NoNewWindow
Write-Output "Starting javaw instance"

方法2:通过CMD的start /b启动独立进程

利用Windows CMD的start /b命令启动javaw,让进程完全脱离当前SSH会话的进程组:

$SSL_KEYSTORE_PASSWORD = $args[0]
Write-Output "Running war in the background"
$arguments = @(
    "-jar",
    "e:\app\app.war",
    "-Dserver.ssl.key-store-password=$SSL_KEYSTORE_PASSWORD",
    "-Dserver.tomcat.basedir=e:\app"
) -join " "

# 通过cmd启动独立进程,输出重定向到指定文件
cmd /c "start /b javaw $arguments > e:\app\output\stdout.txt 2> e:\app\output\stderr.txt"
Write-Output "Starting javaw instance"

方法3:将Java应用注册为Windows服务(推荐长期稳定运行)

使用NSSM(Non-Sucking Service Manager)将Java应用注册为Windows服务,彻底脱离SSH会话依赖,还能实现开机自启:

  1. 下载NSSM到服务器e:\app目录
  2. 修改PowerShell脚本添加服务管理逻辑:
$SSL_KEYSTORE_PASSWORD = $args[0]
$serviceName = "MyJavaApp"
$javawPath = (Get-Command javaw).Path
$arguments = "-jar e:\app\app.war -Dserver.ssl.key-store-password=$SSL_KEYSTORE_PASSWORD -Dserver.tomcat.basedir=e:\app"
$stdoutPath = "e:\app\output\stdout.txt"
$stderrPath = "e:\app\output\stderr.txt"

# 检查服务是否存在,不存在则注册
if (-not (Get-Service -Name $serviceName -ErrorAction SilentlyContinue)) {
    e:\app\nssm.exe install $serviceName $javawPath
    e:\app\nssm.exe set $serviceName AppParameters $arguments
    e:\app\nssm.exe set $serviceName AppStdout $stdoutPath
    e:\app\nssm.exe set $serviceName AppStderr $stderrPath
    e:\app\nssm.exe set $serviceName Start SERVICE_AUTO_START
}

# 停止运行中的服务
if ((Get-Service -Name $serviceName).Status -eq 'Running') {
    e:\app\nssm.exe stop $serviceName
    Start-Sleep -Seconds 5
}

# 启动服务
e:\app\nssm.exe start $serviceName
Write-Output "Started Java application service: $serviceName"

启动校验逻辑扩展

可以在PowerShell脚本中添加进程启动校验,避免Jenkinsfile臃肿:

# 校验进程是否启动成功
Start-Sleep -Seconds 10
$javawProcess = Get-Process javaw -ErrorAction SilentlyContinue
if ($javawProcess) {
    Write-Output "Java application started successfully, PID: $($javawProcess.Id)"
} else {
    Write-Error "Failed to start Java application"
    exit 1
}

内容的提问来源于stack exchange,提问作者Riggs Markham

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 05:48:24