问题描述
我创建了一个服务器程序,当它收到一些命令时,会执行一些操作.我希望当它收到命令android"(当客户端从 android 设备连接时发生)时,我的服务器启动一个 shell 脚本,当客户端断开连接时,我希望它停止执行这个脚本.
I've created a server program which, when it receives some commands, executes some actions.I'd like when it receives the command "android" (which happens when a client connects from an android device) that my server launches a shell script and when the client disconnects I'd like it to stop the execution of this script.
此外,当 Web 浏览器客户端连接并发送命令浏览器"时,服务器将启动另一个脚本.
Also, when a web browser clients connects and send the command "browser" the server would launch an other script.
这两个脚本不能同时使用,因为它们使用相同的资源.这就是为什么我需要在客户端断开连接时停止它们(我知道我不能同时连接两种类型的客户端).
Those two scripts can't be used at the same time because they use the same resources. That's why I need to stop them when a client disconnects (I'm aware that I can't have the two types of clients connected at the same time).
目前,我已经能够启动脚本,但不能阻止它们.这是我在服务器中运行方法的代码:
For now, I've been able to launch the scripts, but not to stop them. Here is the code of my run method in the server :
@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
.这是正常的事情,因为该过程不存在.但在这段时间内,第一个启动脚本的进程一直在运行.
The first time I disconnect an android device, the output of p.exitValue()
is 143
, and the script keeps executing. And after, if I connect one more time with the android client it doesn't seem to launch the script again (which is a good thing, I don't know why or maybe it does launch it but since the resource is already in use, it closes very quickly) and when I disconnect this new client p.exitValue()
returns 0
. Which is a normal thing since the process doesn't exist. But during this time the process of the first script launched keeps running.
我想知道为什么我的命令 p.destroy()
没有终止我的脚本进程.我认为这可能是因为它停止了 sh 进程而不是我的脚本进程(两个不同的进程)有点像这里 java 进程停止整个进程树
I'd like to know why my command p.destroy()
doesn't kill my script process. I think it could be because it stops the sh processes but not the process of my script (two different process) A bit like here java Process stop entire process tree
希望有办法解决这个问题,谢谢!:)
I hope there is a way to solve this problem, thank you ! :)
推荐答案
好的,我已经找到了让它工作的方法.实际上我不得不使用 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'"});
(根据本主题:想要从 Java 调用 linux shell 命令)
Ok I've found how to make it work. Actually I had to use pkill
but with the name of the process of the command executed in my script. Furthermore I had to change my way of executing commands in Java. Because launching pkill -9 -f 'gst-launch-1.0'
in the shell stopped the script correctly but in the java code killProcess = r.exec("pkill -9 -f 'gst-launch-1.0'");
was uneffective. So I changed my way of executing shell command by this way : killProcess = r.exec(new String[]{"bash","-c","pkill -9 -f 'gst-launch-1.0'"});
(according to this topic : 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)");
}
}
这篇关于Java如何停止之前在程序中启动的shell脚本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!