Java ProcessBuilder中的process.destroy()无法在winXP中杀死子进程

10

我有一个使用ProcessBuilder准备操作系统命令并给我一个Process对象的Java应用程序。(实际的操作系统命令是使用cygwin上的ssh进行rsync)。

在Windows中,这个应用程序运行良好。但是,如果我想使用process.destroy()停止进程,它将无法终止子ssh和rsync进程...... 我必须手动使用Windows任务管理器杀死它们。

是否可以获取该进程的OutputStream并在调用destroy();之前以某种方式发送ctrl-c?

如果有人对解决方法有任何想法,那就太好了。 谢谢, D


1
Ctrl-C是一个终端功能,它向进程ID发送一个信号(SIGTERM?)。因此,要模拟它,您需要进程ID并能够发送信号。 - Brian Agnew
2个回答

5

我认为模拟Ctrl-C来完全终止ssh是有问题的。

我会采取以下方法之一。要么使用Windows命令查找谁是ssh的子进程(这有点棘手,因为您需要知道当前的pid以接收自己的子进程)。我相信sysinternals的pstools是一个很好的命令行工具,应该能够让您跟踪孤儿进程。请参见this example以控制Windows进程,可以使用taskList.exe(顺便说一下,它可以以CSV格式输出)或执行特殊的VBScript。

第二种方法是使用Java库,如winp来执行和控制ssh进程。我相信您可以列出所有子进程并强制终止它们,如果发送正确的消息不足以解决问题。这将是我的首选方法。请注意,killRecursively方法正是您想要的。
请注意,这些方法不应仅限于应用程序窗口。您可以将它们封装在一个类中,以便在Windows和Linux机器上运行不同。
请注意,我没有尝试过对Windows进程进行精细控制,因此我不确定我找到的解决方案有多成熟。

winp似乎越来越受欢迎,并且是Hudson的一部分(实际上是为其编写的)。java.net URL不再解析,但原始文章仍然存在于https://weblogs.java.net/blog/kohsuke/archive/2008/03/introducing_win.html(请注意,其中一些信息已过时,例如只有32位)。 winp的新URL(带有mvn和github链接)是:http://winp.kohsuke.org/ - toddkaufmann

0

我不确定 Process.destroy() 在底层做了什么(发送信号或类似的操作?)。

你可能会发现更好的方法是在一个 shell 脚本中调用你的 ssh/rsync,并在 stdout 上返回一个进程 ID,然后当你想要杀死这个进程时,使用该进程 ID 执行 /bin/kill。有点混乱,但可能更可靠。

请注意,你可以使用 SIGTERM 和 SIGKILL 来执行 /bin/kill,如果它特别顽固。


2
Process.destroy() 调用 Windows 函数 TerminateProcess (http://msdn.microsoft.com/en-us/library/ms686714(VS.85).aspx)。 - Michael Myers

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接