如何通过 java 的 ProcessBuilder 通过 ssh 将参数传递给 pkill?

How do I pass arguments to pkill, over ssh, through java's ProcessBuilder?

我正在尝试使用 ProcessBuilder 通过 java 到 shell 的接口远程终止进程。我的代码如下所示:

ProcessBuilder builder = new ProcessBuilder( 
  "ssh", 
  "user@host", 
  "pkill -f \"'instanceId XXXXXX'\"");
Process process = builder.start();

其中 instanceId XXXXX 匹配进程启动时的一些命令行参数。

当我得到最终的命令字符串时,使用

builder.command()

它returns

ssh user@host pkill -f "'instanceId XXXXX'"

其中,当 运行 在命令行上手动工作时。不幸的是,当 ProcessBuilder 运行 时,它无法识别目标进程。

在过去几周花了太多时间与关于 ssh/ProcessBuilder 的争论进行斗争之后,有人可以阐明它为什么这样做,并且可能会向我指出一些并不完全神秘的相关文档?

问题出在双引号上。

当您在命令行中 运行 命令时,shell 将自行解释双引号或单引号。因此,如果你 运行

ssh user@host pkill -f 'instanceId XXXXX'

(或与双引号相同)来自命令行,它将去除这些引号。尽管本地 shell 将字符串 instanceID XXXX 视为单个参数,但 remote shell 将命令视为一个整体,看不到任何引号,因此将 "InstanceId" 和 "XXXXX" 视为两个独立的实体。

因此,当您从命令行运行 时,您需要在引号上添加引号。本地 shell 将去除外部引号,ssh 将使用内部引号传递命令,这将导致远程 shell 将 instanceID XXXX 视为单个参数。

但是,当您 运行 来自进程构建器时,您不会 运行 来自本地 shell。您自己适当地构建参数,然后将它们 字面意思 发送到 ssh。因此,当您发送 "'InstanceID XXXX'" 时,远程 shell 将看到的是 "'InstanceID XXXX'"。它只会剥离一对,并且 'InstanceID XXXX' 不在远程机器上的任何进程命令行中。不是那些引号...

因此,当您使用流程构建器时,您不应该像在 运行 中直接在 shell 中那样引用。只需要一对。