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

Posted

技术标签:

【中文标题】如何在java中执行命令“ps -eaf | grep myprocess”【英文标题】:how to execute command "ps -eaf | grep myprocess" in java 【发布时间】:2022-01-23 10:21:31 【问题描述】:

如果有任何代码可以找到任何其他进程的 PID,我搜索并检查了 SO。 有一种解决方案可以创建一个带有命令“ps -eaf | grep myprocess”的 shell 脚本并从 java 执行该脚本。

但我想使用 java ProcessBuilder 或 Runtime 方法执行。下面是我尝试过的代码,它没有给我 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 $2' " - 空响应。

提前感谢任何线索。

【问题讨论】:

"不给我 null 作为输出" 你能解释一下你的意思吗?你有一个空的 catch 块,所以可能你得到一个异常并忽略它。 也可以考虑在没有shell脚本的情况下运行ps命令,并在代码中做grep部分。 @tgdavies 请参阅我已更新代码和输出以确认输出为空。 如果有任何问题,请查看 stderr。 @Subhajit 简单地更改使用的 cmd 并不能解决您的问题。您需要根据两个都说以特定方式使用“ProcessBuilder”的答案来修复代码 - 您没有阅读上面的 stderr 流。 【参考方案1】:

你的问题是你试图在你的命令中使用管道,所以你需要一个 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 中运行 htop 时,在 htop 之后使用上面的代码 grep 将返回您评论中的答案,但通过 top 进行 grepping 将包括实际过程。我还用 gedit 进行了检查,看起来 grep 与 gedit 的返回就像你的情况一样,但仅使用 edit 将返回实际过程。不知道在这种情况下是什么问题。

【讨论】:

由于某种原因,它没有给出预期的输出。下面是命令的输出: >> java TestShellCommand sdc 48747 48714 0 15:12 pts/6 00:00:00 /bin/sh -c ps -eaf | grep myProcess sdc 48750 48747 0 15:12 pts/6 00:00:00 grep myProcess【参考方案2】:

@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()))

【讨论】:

首先感谢您的回复。而且,我还尝试将 waitFor() 选项设置为 true,以等待我们从该过程中获得整个输出。但是我不确定为什么在 waitFor 的情况下它会等待很长时间并且没有完成命令执行。我尝试将输出重定向到系统输出,发现存储信息需要很长时间。为什么 waitFor 需要更长的时间可能需要更多调查。 您能否使用您现在尝试的更改和错误消息来编辑您的问题,这可能有助于解释此问题。 请检查更新的代码和试用版。

以上是关于如何在java中执行命令“ps -eaf | grep myprocess”的主要内容,如果未能解决你的问题,请参考以下文章

如何在Java中执行Hive命令或HiveQL

JAVA中如何执行DOS命令

如何在 Java 的 linux 终端中交互地执行多个命令?

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

在 Blue-J 中执行命令后如何退出 Java 窗口?

在java里面如何运行多条cmd命令?我是用for来循环,一次运行一条,可是老是不执行。