在后台作业完成之前,使用 Powershell 的 SSM 发送命令不会完成

SSM send-command with Powershell does not complete until background job finishes

我正在使用 SSM 发送命令在 Windows EC2 实例上启动 Tomcat 进程。

例如:

aws ssm send-command --instance-id i-xxxx --document-name "AWS-RunPowerShellScript"
   --parameters 'commands=["startup.bat"]'

这确实启动了 Tomcat,但我注意到 SSM 命令调用本身一直在进行中,直到我最终关闭 Tomcat,此时它立即成功。

我的预感是 SSM 在任何派生的子进程上运行 Powershell 块的方式(start java ... 在 Tomcat 的情况下)。不过,我不认为这是 Tomcat 甚至 Java 独有的。

有没有办法让 Powershell 退出,让子进程 运行 留在后台?

如果你想在PowerShell中启动一个独立进程——一个即使在创建进程终止后仍然存在的进程——使用Start-Process cmdlet:

Start-Process aws -ArgumentList @'
send-command --instance-id i-xxxx --document-name AWS-RunPowerShellScript --parameters commands=["startup.bat"]
'@

注意使用(文字)here-string (@'<newline>...<newline>'@) 使嵌入引号更容易;有关 PowerShell 字符串文字的信息,请参阅 this answer 的底部部分。

虽然 -ArgumentList 可以接受 array 参数,但从 PowerShell 7.0 开始,将这些参数转换为命令行的方式已损坏(并且可能不会得到修复由于向后兼容性问题;请参阅 this GitHub issue).

因此,最好使用带有嵌入式引号单个参数。

请注意,在调用 时,您应该 仅使用 双引号 引号 (") 作为参数定界符外部程序(例如本例中的aws)。[1]


[1] 通过 直接 调用外部程序,您可以自由使用任何一种引用样式,因为 PowerShell 在重建命令行时在幕后,仅使用 " 来引用参数(如果需要的话)。在 Start-Process 的情况下,-ArgumentList 值被传递到 .NET API (System.Diagnostics.ProcessStartInfo),其中不执行此类转换。