英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论