【问题标题】:Long running process remote termination?长时间运行的进程远程终止?
【发布时间】:2013-01-15 19:13:54
【问题描述】:

我正在开发一个允许用户在服务器上远程运行 AI 算法的应用程序。其中一些算法需要很长时间。它的设置使得 AJAX 调用提供算法参数并在服务器上启动 C++ 算法。通过 AJAX 调用轮询状态文件来跟踪计算的结果和状态。该解决方案似乎适用于同时使用该服务的多个用户,但我现在正在寻找一种方法来取消用户浏览器的计算。我有一个停止按钮,用于停止 AJAX 更新服务并停止浏览器与服务器上正在运行的进程之间的任何通信。问题是进程还在运行,我想在用户取消操作时释放服务器资源。以下是更多详细信息。

AJAX调用命中的web服务运行在用户'tomcat'下,可以通过ps -U tomcat列出。算法执行都是'java'的子进程,可以ps --ppid ###列出。

浏览器记录当前计算开始的时间(用户系统时间,而不是服务器系统时间)。

从不同位置连接的用户可能会同时进行多个计算,从而产生多个同名和父进程下的进程。

restful 服务通过 java runtime.exec() 执行终端命令。

我对 shell 脚本不是很了解,所以任何帮助都将不胜感激。谁能想到一种方法来使用 java 进程对象或 shell 脚本/awk 通过timestamp(可能是最接近用户系统时间的时间戳......?)或其他方式来定位进程?

提前致谢。

--编辑

如果您有 pid...,在 java 中是否有办法获取给定进程的句柄...?好像不是。

--编辑

我无法更改服务器上长时间运行的进程的源代码。 :(

【问题讨论】:

    标签: linux shell unix process pid


    【解决方案1】:

    您的 AJAX 调用应该操作某种资源(最方便的是文本文件),该资源充当进程的semaphore,在每次轮询迭代中检查该信号量文件是否已设置为停止状态.如果 AJAX 将信号量文件更改为停止,则该进程将停止,因为您的应用程序会对其进行检查并做出相应的响应。这反过来意味着需要将功能编程到您的 Java AI 应用程序中,而不是弄清楚 PID 是什么,然后在操作系统级别将其杀死。当然,这假设您可以访问应用程序的源代码。

    当然,信号量不必是文件,也可以是数据库等中的值,以适合您的口味和配置。

    【讨论】:

    • 不幸的是,我没有能力改变算法。非常不方便。我有一个用于保持状态更新的文本文件,但即使 AJAX 轮询识别出状态处于 STOP 模式,它也无法在没有 pid 的情况下将该发现传达给进程,除非我错过了一些东西。我想我在 java 中有一个解决方案,使用 runtime.exec(ps -U tomcat --sort=start_time -o time,pid | awk "parse ps times here") 然后获取第一个进程时间 >= 原始用户时间戳和被pid杀死。试试看,汤姆。感谢您的回答!
    • 您应该在原始帖子中包含有关无法更改应用代码的注释。我上面解释的几乎是大多数程序员会同意的标准模式,假设您可以更改代码。很抱歉您的限制
    • 这确实是一个无赖...谢谢你的想法。在尝试实现我的 java/awk 解决方案时,java exec() 似乎无法解析 exec() 中的 awk。不知道..
    • 非常好。我感谢您接受我的回答——但如果您觉得您的回答更好(或者更适合特定情况),您应该将其作为接受者进行检查——我知道接受自己的回答可能不是很勇敢回答,但如果你认为它比任何其他都好,你应该
    【解决方案2】:

    我终于找到了一个安全的解决方案。在 restful java 服务中,使用Process p = Runtime.getRuntime().exec() 可以为您提供正在运行的进程的句柄。然而,获取 pid 的唯一方法是通过一种称为反射的技术。

    Field f = p.getClass().getDeclaredField();
    f.setAccessible(true);
    String pid = Integer.toString(f.getInt(p));
    

    多么令人难以置信的尴尬......

    无论如何,由于 p 从服务器传递到客户端是不可能的,并且允许远程调用通过参数传递的 pid 杀死任意服务器进程的不安全性,我能想出的唯一逻辑策略是将获取的pid写入初始客户端时间戳指示的进程唯一文件,并在restful服务函数返回时删除该文件。这个唯一的文件可以通过另一个读取文件的restful服务用作终止句柄,并以等于文件内容的pid终止进程。这个

    【讨论】:

      【解决方案3】:

      您可以保留runtime.exec 返回的Process 实例并调用 Process.destroy 来终止子进程。不太了解您的 Web 服务应用程序,我假设您可以将流程实例保存在将用户映射到流程列表的全局会话映射中。确保对该映射的访问是线程安全的。此外,它仅在您有一个允许在不同请求之间共享此类全局会话映射的 Web 服务进程时才有效。

      或者看看Get subprocess id in Java

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-11-12
        • 1970-01-01
        • 1970-01-01
        • 2014-02-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-06-03
        相关资源
        最近更新 更多