如何在 java 中执行命令 "ps -eaf | grep myprocess"
how to execute command "ps -eaf | grep myprocess" in java
我用谷歌搜索并检查了 SO 是否有任何代码可以找到任何其他进程的 PID。
有一个解决方案可以创建一个 shell 脚本,其中包含命令“ps -eaf | grep myprocess”,并从 java.
执行该脚本
但我想使用 java ProcessBuilder 或运行时方法执行。下面是我试过的代码,它没有给我 null 作为输出。
import java.io.*;
public class TestShellCommand {
public static void main(String args[]) {
Process p = null;
String command = "ps -ef | grep myProcess";
try {
// p = new ProcessBuilder(command).start();
p = Runtime.getRuntime().exec(command);
BufferedReader br[] = new BufferedReader[2];
br[1] = new BufferedReader(new InputStreamReader(p.getErrorStream()));
br[0] = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = null;
if(br[0].readLine() == null){
System.out.println("The input stream is null.");
}
while ((line = br[0].readLine()) != null) {
System.out.println(line);
}
try {
br[0].close();
} catch (Exception a) {
a.printStackTrace();
}
try {
br[1].close();
} catch (Exception a) {
a.printStackTrace();
}
} catch (Exception grrr) {
grrr.printStackTrace();
} finally {
try {
closeStreams(p);
p.destroy();
} catch (Exception r) {
r.printStackTrace();
}
}
}
static void closeStreams(Process p) throws IOException {
p.getInputStream().close();
p.getOutputStream().close();
p.getErrorStream().close();
}
}
命令的输出是:
java TestShellCommand
The input stream is null.
{sdc@ip-172-31-32-49}[26] echo $?
0
如果我的代码中有任何错误,请告诉我,当我从 shell 手动搜索时,我确实得到了如下预期的输出:
ps -ef | grep myProcess
root 7433 1 0 10:33 ? 00:00:00 myProcess hello
sdc 19894 14130 0 11:24 pts/7 00:00:00 grep myProcess
[更新代码 - 没有 grep 命令]
import java.io.*;
public class TestShellCommand {
public static void main(String args[]) {
Process p = null;
String [] command = {"ps", "-eaf"};
try {
p = Runtime.getRuntime().exec(command);
BufferedReader br[] = new BufferedReader[2];
br[1] = new BufferedReader(new InputStreamReader(p.getErrorStream()));
br[0] = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = null;
if(br[0].readLine() == null){
System.out.println("The input stream is null.");
}
while ((line = br[0].readLine()) != null) {
System.out.println(line);
}
// Then code to find by process name by using string methods ...
try {
br[0].close();
} catch (Exception a) {
a.printStackTrace();
}
try {
br[1].close();
} catch (Exception a) {
a.printStackTrace();
}
} catch (Exception grrr) {
grrr.printStackTrace();
} finally {
try {
closeStreams(p);
p.destroy();
} catch (Exception r) {
r.printStackTrace();
}
}
}
static void closeStreams(Process p) throws IOException {
p.getInputStream().close();
p.getOutputStream().close();
p.getErrorStream().close();
}
}
我添加了有效的代码,当我传递命令时:
new String[]{"/bin/sh","-c", "ps -eaf | grep "+ "myProcess" +" | grep -v grep"}
- 空响应。
new String[] {"ps", "-eaf", "grep -m 1 myProcess", "awk -F ' ' '{print }' "}
- 空响应。
提前感谢任何线索。
你的问题是你试图在你的命令中使用管道,所以你需要一个 shell 来执行它。您可以使用以下命令:
p = new ProcessBuilder("/bin/sh", "-c", "ps -aux | grep myProcess").start();
您可以在此处阅读更多内容:Using Java ProcessBuilder to Execute a Piped Command
为了测试它,我在 shell 和 运行 命令中启动了 top
并将其作为 grep 模式。这是我得到的输出:
<edited> 139890 0.4 0.0 23640 4376 pts/0 S+ 16:05 0:00 top
<edited> 139945 0.0 0.0 20996 3448 ? S 16:06 0:00 /bin/bash -c ps -aux | grep top
<edited> 139947 0.0 0.0 20536 2776 ? S 16:06 0:00 grep top
根据您的评论,我建议您首先 运行 shell 中的命令以查看输出并检查它是否与 Java 程序的输出相匹配。我想 myProcess
只是实际过程检查的占位符。
我注意到的一件事是,当 运行 从 snap 中 ning htop 时,并使用上面的代码在 htop 之后进行 grep 将 return 像您的评论中那样回答,但是通过 top 进行 grep 将包括实际过程。我还检查了 gedit,它看起来像 grep with gedit returns 就像你的情况一样,但仅使用 edit
将 return 实际过程。不确定这种情况下的问题是什么。
正如@Slimo 的回答所示,您必须启动 shell 来执行 shell 命令(管道),并读取错误流以确定可能出了什么问题。
在不使用 waitFor()
或同时使用 stdout 和 stderr 的情况下启动子进程可能会导致问题,使用文件重定向或在此示例中合并 stderr -> stdout 并仅读取一个流:
String procname = "myProcess";
String[] cmd = new String[]{"bash","-c", "ps -eaf | grep "+procname+" | grep -v grep"}
ProcessBuilder pb = new ProcessBuilder(cmd);
pb.redirectErrorStream(true);
Process process = pb.start();
process.getInputStream().transferTo(System.out);
int rc = process.waitFor();
if (rc != 0)
throw new RuntimeException("Failed rc="+rc+" cmd="+Arrays.toString(cmd));
以后 JDK 您不需要 ProcessBuilder,您可能会在 ProcessHandle
:
返回的数据结构中找到所有流程属性
ProcessHandle.allProcesses()
.filter(ph -> ph.info().command().isPresent() && ph.info().command().get().contains(procname))
.forEach(ph -> System.out.println("PID: "+ph.pid()+" command: "+ph.info().command()))
我用谷歌搜索并检查了 SO 是否有任何代码可以找到任何其他进程的 PID。 有一个解决方案可以创建一个 shell 脚本,其中包含命令“ps -eaf | grep myprocess”,并从 java.
执行该脚本但我想使用 java ProcessBuilder 或运行时方法执行。下面是我试过的代码,它没有给我 null 作为输出。
import java.io.*;
public class TestShellCommand {
public static void main(String args[]) {
Process p = null;
String command = "ps -ef | grep myProcess";
try {
// p = new ProcessBuilder(command).start();
p = Runtime.getRuntime().exec(command);
BufferedReader br[] = new BufferedReader[2];
br[1] = new BufferedReader(new InputStreamReader(p.getErrorStream()));
br[0] = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = null;
if(br[0].readLine() == null){
System.out.println("The input stream is null.");
}
while ((line = br[0].readLine()) != null) {
System.out.println(line);
}
try {
br[0].close();
} catch (Exception a) {
a.printStackTrace();
}
try {
br[1].close();
} catch (Exception a) {
a.printStackTrace();
}
} catch (Exception grrr) {
grrr.printStackTrace();
} finally {
try {
closeStreams(p);
p.destroy();
} catch (Exception r) {
r.printStackTrace();
}
}
}
static void closeStreams(Process p) throws IOException {
p.getInputStream().close();
p.getOutputStream().close();
p.getErrorStream().close();
}
}
命令的输出是:
java TestShellCommand
The input stream is null.
{sdc@ip-172-31-32-49}[26] echo $?
0
如果我的代码中有任何错误,请告诉我,当我从 shell 手动搜索时,我确实得到了如下预期的输出:
ps -ef | grep myProcess
root 7433 1 0 10:33 ? 00:00:00 myProcess hello
sdc 19894 14130 0 11:24 pts/7 00:00:00 grep myProcess
[更新代码 - 没有 grep 命令]
import java.io.*;
public class TestShellCommand {
public static void main(String args[]) {
Process p = null;
String [] command = {"ps", "-eaf"};
try {
p = Runtime.getRuntime().exec(command);
BufferedReader br[] = new BufferedReader[2];
br[1] = new BufferedReader(new InputStreamReader(p.getErrorStream()));
br[0] = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = null;
if(br[0].readLine() == null){
System.out.println("The input stream is null.");
}
while ((line = br[0].readLine()) != null) {
System.out.println(line);
}
// Then code to find by process name by using string methods ...
try {
br[0].close();
} catch (Exception a) {
a.printStackTrace();
}
try {
br[1].close();
} catch (Exception a) {
a.printStackTrace();
}
} catch (Exception grrr) {
grrr.printStackTrace();
} finally {
try {
closeStreams(p);
p.destroy();
} catch (Exception r) {
r.printStackTrace();
}
}
}
static void closeStreams(Process p) throws IOException {
p.getInputStream().close();
p.getOutputStream().close();
p.getErrorStream().close();
}
}
我添加了有效的代码,当我传递命令时:
new String[]{"/bin/sh","-c", "ps -eaf | grep "+ "myProcess" +" | grep -v grep"}
- 空响应。new String[] {"ps", "-eaf", "grep -m 1 myProcess", "awk -F ' ' '{print }' "}
- 空响应。
提前感谢任何线索。
你的问题是你试图在你的命令中使用管道,所以你需要一个 shell 来执行它。您可以使用以下命令:
p = new ProcessBuilder("/bin/sh", "-c", "ps -aux | grep myProcess").start();
您可以在此处阅读更多内容:Using Java ProcessBuilder to Execute a Piped Command
为了测试它,我在 shell 和 运行 命令中启动了 top
并将其作为 grep 模式。这是我得到的输出:
<edited> 139890 0.4 0.0 23640 4376 pts/0 S+ 16:05 0:00 top
<edited> 139945 0.0 0.0 20996 3448 ? S 16:06 0:00 /bin/bash -c ps -aux | grep top
<edited> 139947 0.0 0.0 20536 2776 ? S 16:06 0:00 grep top
根据您的评论,我建议您首先 运行 shell 中的命令以查看输出并检查它是否与 Java 程序的输出相匹配。我想 myProcess
只是实际过程检查的占位符。
我注意到的一件事是,当 运行 从 snap 中 ning htop 时,并使用上面的代码在 htop 之后进行 grep 将 return 像您的评论中那样回答,但是通过 top 进行 grep 将包括实际过程。我还检查了 gedit,它看起来像 grep with gedit returns 就像你的情况一样,但仅使用 edit
将 return 实际过程。不确定这种情况下的问题是什么。
正如@Slimo 的回答所示,您必须启动 shell 来执行 shell 命令(管道),并读取错误流以确定可能出了什么问题。
在不使用 waitFor()
或同时使用 stdout 和 stderr 的情况下启动子进程可能会导致问题,使用文件重定向或在此示例中合并 stderr -> stdout 并仅读取一个流:
String procname = "myProcess";
String[] cmd = new String[]{"bash","-c", "ps -eaf | grep "+procname+" | grep -v grep"}
ProcessBuilder pb = new ProcessBuilder(cmd);
pb.redirectErrorStream(true);
Process process = pb.start();
process.getInputStream().transferTo(System.out);
int rc = process.waitFor();
if (rc != 0)
throw new RuntimeException("Failed rc="+rc+" cmd="+Arrays.toString(cmd));
以后 JDK 您不需要 ProcessBuilder,您可能会在 ProcessHandle
:
ProcessHandle.allProcesses()
.filter(ph -> ph.info().command().isPresent() && ph.info().command().get().contains(procname))
.forEach(ph -> System.out.println("PID: "+ph.pid()+" command: "+ph.info().command()))