在Windows上通过SSH连接启动后台进程,使其在SSH断开连接时不会停止。

huangapple go评论60阅读模式
英文:

Starting a background process on Windows through an SSH connection that doesn't get stopped when SSH disconnects

问题

我有一个Java应用程序,我正在尝试通过SSH(通过Jenkins)部署到Windows服务器。我编写了一个PowerShell脚本,使用start-process和javaw在后台启动进程:

$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"
Write-Output "Starting javaw instance"

当我在服务器上运行该脚本时,它完美运行:进程在后台无限运行,并且所有输出都到了正确的位置。但是,当我尝试通过Jenkins从SSH运行它时,Java应用程序将正常启动,但一旦PowerShell脚本结束,进程就被终止。最初,我以为是Jenkins在杀死进程,但我进行了一些调试,发现它在退出PowerShell脚本后立即被终止,因此我认为与SSH有关。这是Jenkins文件中尝试启动进程的行:

sh 'ssh -o StrictHostKeyChecking=no $ssh_target powershell e:\\app\\startup $SSL_KEYSTORE_PASSWORD'

我希望使用类似这样的PowerShell脚本启动进程,因为一旦我使其工作,我想在PowerShell脚本中添加一些其他内容,以确保它已正常启动,并且我不想让Jenkins文件变得更加混乱。

英文:

I have a java application that I'm trying to deploy to a Windows server via SSH (via Jenkins). I wrote a powershell script to start the process in the background using start-process and javaw:

$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"
Write-Output "Starting javaw instance"

When I run the script from the server, it works perfectly: the process runs in the background indefinitely and all the output goes to the right place. But, when I attempt to run it via SSH from jenkins, the java application will start up properly, but as soon as the powershell script ends, the process gets killed. Initially, I thought it was jenkins killing the process, but I did some debugging and figured out that it's getting killed as soon as it exits the powershell script, so I think it's related to SSH. This is the line in the jenkinsfile that's attempting to start up the process:

sh 'ssh -o StrictHostKeyChecking=no $ssh_target powershell e:\\app\\startup $SSL_KEYSTORE_PASSWORD'

I would like to start the process using a powershell script like this, because once I get this working, I'd like to add some other stuff into the powershell script to make sure it started up properly, and I don't want to clutter up the jenkinsfile even more than it already is.

答案1

得分: 0

我找到了一种方法来实现这一点,使用此答案,以及此答案中的评论,以及大量的试错。

首先,不相关的一点是,我不得不更改脚本的行顺序,以便应用程序可以正确启动(尽管它一直说SSL证书密码不正确)。

$SSL_KEYSTORE_PASSWORD = $args[0]
Write-Output "在后台运行war"
Start-Process javaw -ArgumentList "-jar", `
    $(" -Dserver.ssl.key-store-password=" + $SSL_KEYSTORE_PASSWORD), `
    "-Dserver.tomcat.basedir=e:\app", `
    "e:\app\app.war" `
    -RedirectStandardOutput "e:\app\output\stdout.txt" `
    -RedirectStandardError "e:\app\output\stderr.txt"
Write-Output "启动javaw实例"

现在,进入主要问题,我解决它的方式是使用在这两个链接中提到的Invoke-WmiMethod命令。

实际工作的命令看起来是这样的:

sh "ssh -o StrictHostKeyChecking=no $ssh_target powershell Invoke-WmiMethod -Class Win32_Process -Name Create -ArgumentList 'C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe e:\app\startup ${SSL_KEYSTORE_PASSWORD}'"

原来我必须将-ArgumentList中的内容用单引号括起来(因此,我当然必须对它们进行转义),并且如果我想调用PowerShell脚本,我必须调用PowerShell可执行文件的完整文件路径。

现在它至少可以工作了。

英文:

I figured out a way to do this using this answer, a comment on this answer, and a whole bunch of trial and error.

First of all, on an unrelated note, I had to switch the line order on the script for the app to start properly (it kept saying the ssl certificate password was incorrect even though it wasn't).

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

Now, to get to the main question, the way I solved it was by using the Invoke-WmiMethod command mentioned in those two links.

The actual working line looks like this:

sh "ssh -o StrictHostKeyChecking=no $ssh_target powershell Invoke-WmiMethod -Class Win32_Process -Name Create -ArgumentList \'C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe e:\\app\\startup " + "${SSL_KEYSTORE_PASSWORD}" + "\'"

It turns out that I had to wrap whatever was in the -ArgumentList in single quotes (so, of course, I had to escape them) and that if I wanted to call a powershell script, I had to invoke the full file path of the powershell executable.

It works now at least.

huangapple
  • 本文由 发表于 2023年2月18日 04:04:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/75488795.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定