Java如何阻止以前在程序中启动的shell脚本

时间:2014-04-16 09:50:59

标签: java linux shell process

我创建了一个服务器程序,当它收到一些命令时,会执行一些操作。 我喜欢它收到命令" android" (当客户端从Android设备连接时发生)我的服务器启动一个shell脚本,当客户端断开连接时,我希望它停止执行这个脚本。

此外,当Web浏览器客户端连接并发送命令"浏览器"服务器将启动另一个脚本。

这两个脚本不能同时使用,因为它们使用相同的资源。这就是为什么我需要在客户端断开连接时阻止它们(我知道我不能同时连接两种类型的客户端)。

目前,我已经能够启动脚本,但不能阻止它们。这是我在服务器中运行方法的代码:

@Override
public void run() {
    try {
        BufferedReader ins = new BufferedReader(new InputStreamReader(soc.getInputStream()));

        Runtime r = Runtime.getRuntime();
        Process p = null;

        int i = 0;
        while (i < 1) {
            String request = ins.readLine();
            if (request == null || request.equals("close")) {
                p.destroy();
                System.out.println("The child was destroyed? "+p.exitValue());
                i++;
            }
            else {
                if (request.equals("android")) {
                    p = r.exec("sh /home/pi/test-raspicamsrc.sh &");
                }
                else if (request.equals("browser")) {
                    p = r.exec("sh /home/pi/test-http-launch.sh &");
                }
                else if (request.equals("left")) {
                    serialPort.writeBytes("4".getBytes());//Write data to port
                }
                else if (request.equals("right")) {
                    serialPort.writeBytes("6".getBytes());
                }
                else if (request.equals("stop")) {
                    serialPort.writeBytes("5".getBytes());
                }
                else if (request.equals("forward")) {
                    serialPort.writeBytes("8".getBytes());
                }
                else if (request.equals("backward")) {
                    serialPort.writeBytes("2".getBytes());
                }
                else {
                    System.out.println("Unknown command");
                }
            }
        }
        ins.close();
        soc.close();
        // We always stop the car in the end.
        serialPort.writeBytes("5".getBytes());
    }

第一次断开Android设备时,p.exitValue()的输出为143,脚本继续执行。之后,如果我再次与Android客户端连接,它似乎不会再次启动脚本(这是一件好事,我不知道为什么或者它确实启动它但是从资源开始已经在使用,它会很快关闭)当我断开连接时,新客户p.exitValue()会返回0。由于该过程不存在,这是正常的事情。但在此期间,第一个脚本启动的过程一直在运行。

我想知道为什么我的命令p.destroy()没有杀死我的脚本进程。我认为这可能是因为它停止了sh进程而不是我的脚本进程(两个不同的进程)有点像这里java Process stop entire process tree

我希望有办法解决这个问题,谢谢! :)

2 个答案:

答案 0 :(得分:0)

您可以通过以下命令检查服务器中的脚本是否正在运行。

ps -efw | grep&#39; process_name&#39;

现在要从java程序中停止脚本,可以执行以下命令。

pkill -9 -f&#39; test-raspicamsrc.sh&#39;

pkill命令用于通过提供进程模式来终止进程。如果你想在没有pid的情况下杀死你的firefox应用程序,你可以像下面这样执行。

pkill -9 -f&#39; firefox&#39;

答案 1 :(得分:0)

好的,我已经找到了如何让它发挥作用。实际上我必须使用pkill但是使用我脚本中执行的命令进程的名称。此外,我不得不改变我在Java中执行命令的方式。因为在shell中启动pkill -9 -f 'gst-launch-1.0'会正确停止脚本,但在java代码中killProcess = r.exec("pkill -9 -f 'gst-launch-1.0'");无效。所以我通过这种方式改变了执行shell命令的方式:killProcess = r.exec(new String[]{"bash","-c","pkill -9 -f 'gst-launch-1.0'"});(根据这个主题:Want to invoke a linux shell command from Java

所以这是我的工作代码:

@Override
    public void run() {
        try {
            BufferedReader ins = new BufferedReader(new InputStreamReader(soc.getInputStream()));

            Runtime r = Runtime.getRuntime();
            Process videoProcess = null;
            Process killProcess = null;
            boolean android = false;

            int i = 0;
            while (i < 1) {
                String request = ins.readLine();

                if (request == null || request.equals("close")) {
                    if (android) {
                        killProcess = r.exec(new String[]{"bash","-c","pkill -9 -f 'gst-launch-1.0'"});
                    }
                    else {
                        killProcess = r.exec(new String[]{"bash","-c","pkill -9 -f 'http-launch'"});
                    }
                    i++;
                }
                else {
                    if (request.equals("android")) {
                        videoProcess = r.exec(new String[]{"bash","-c","sh /home/pi/test-raspicamsrc.sh"});
                        android = true;
                    }
                    else if (request.equals("browser")) {
                        videoProcess = r.exec(new String[]{"bash","-c","sh /home/pi/test-http-launch.sh"});
                        android = false;
                    }
                    else if (request.equals("left")) {
                        serialPort.writeBytes("4".getBytes());//Write data to port
                    }
                    else if (request.equals("right")) {
                        serialPort.writeBytes("6".getBytes());
                    }
                    else if (request.equals("stop")) {
                        serialPort.writeBytes("5".getBytes());
                    }
                    else if (request.equals("forward")) {
                        serialPort.writeBytes("8".getBytes());
                    }
                    else if (request.equals("backward")) {
                        serialPort.writeBytes("2".getBytes());
                    }
                    else {
                        System.out.println("Unknown command");
                    }
                }
            }
            ins.close();
            soc.close();
            // We always stop the car in the end.
            serialPort.writeBytes("5".getBytes());

        }
        catch (IOException e) {
            System.out.println("Error input/output while initializing the server (Port 6020 may already be in use)");
        }
    }