当前位置: 首页 > 知识库问答 >
问题:

如何在java中执行命令“ps-eaf | grep myprocess”

滕鸿畴
2023-03-14

我谷歌并检查了SO是否有任何代码来查找任何其他进程的PID。有一个解决方案可以创建一个外壳脚本,其中包含命令“ps-eaf|grep my进程”,并从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();
    }
}

我添加了正在工作的代码,当我传递命令为:

  1. new String[]{/bin/sh',“-c”,“ps-eaf | grep”“myProcess”“| grep-v grep”}-空响应
  2. new String[]{ps',“-eaf”,“grep-m1 myProcess”,“awk-F''{print$2}'}-空响应

提前感谢您提供的任何线索。

共有2个答案

龙博
2023-03-14

您的问题是,您试图在命令中使用管道,因此需要一个shell来执行它。可以使用以下命令:

p = new ProcessBuilder("/bin/sh", "-c", "ps -aux | grep myProcess").start();

您可以在这里阅读更多内容:使用Java ProcessBuilder执行管道命令

为了测试它,我在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只是一个占位符,供实际进程检查。

我注意到的一件事是,当从快照运行htop时,在htop之后使用上面的代码进行grep时,将返回类似于您的注释中的答案,但按top进行grep将包括实际的过程。我还使用gedit进行了检查,看起来grep with gedit返回的结果与您的情况类似,但仅使用edit将返回实际的过程。不确定这件事出了什么问题。

郁承运
2023-03-14

正如@Slimo answer所指出的,您必须启动一个shell来执行shell命令(管道),并读取错误流以确定可能出现的错误。

在不使用waitFor()的情况下启动子流程,或同时使用stdout和stderr可能会导致问题,请使用文件重定向或本例中的merge stderr-

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()))
 类似资料:
  • 问题内容: 我想使用Java程序将avi文件转换为3gp。 为此,我使用“ EM Total Video Converter命令行2.43”,其命令为 “ C:\ EM TVCC > TVCC -f E:\ TestVideo \ 01.avi -o E:\ OutputFiles \ target.3gp” 我在站点http://www.rgagnon.com/javadetails/java-

  • 问题内容: 我正在尝试在Java中为Linux / unix os执行awk命令,但问题是当我执行命令时它没有显示任何错误它。但是执行后没有输出,执行它需要几分之一秒,我不知道问题请帮忙。 该代码是 谢谢您的帮助 问题答案: 使用Java正确启动命令行过程并不容易。我建议您使用commons- exec 而不是自己尝试。 现在,您在命令行中有两件事需要特殊处理: AWK脚本周围的单引号。当您将每个

  • 问题内容: 我如何在Java URLConnection中实现以下curl命令 提前致谢 问题答案: 使用URLConnection的派生类(即HttpURLConnection),您可以轻松地做到这一点。 对于

  • 问题内容: 我想问一下如何多次执行1条命令 例如此代码 我要运行500次,该怎么办? 谢谢 问候威廉姆斯 问题答案: 使用循环, 请阅读基本的Java教程。可以在这里找到一个

  • 问题内容: 我正在尝试通过Java执行命令行参数。例如: 上面的命令打开命令行,但是不执行或。有任何想法吗?我正在运行Windows XP,JRE6。 (我已经对问题进行了更详细的修订。以下答案很有用,但不能回答我的问题。) 问题答案: 你发布的代码使用自己的命令启动三个不同的过程。要打开命令提示符然后运行命令,请尝试以下操作(请勿自己尝试):

  • 问题内容: 我正在使用ProcessBuilder执行bash命令: 但我想做这样的事情: 如何将超级用户密码传递给bash? 不会解决这个问题,因为它是从Ubuntu 13.04开始删除的,我需要使用默认命令来执行此操作。 编辑 gksudo在最近的更新中回到了Ubuntu 13.04。 问题答案: 我想您可以使用它,但是我有点犹豫要发布它。所以我只想说: 使用此方法后果自负,不建议您使用,请勿