如何以编程方式检查是否在使用Java的ubuntu上安装了软件实用程序

时间:2011-12-13 11:07:21

标签: java runtime.exec

我正在为自己的学习开发一个Java项目,我所做的是一个可以使用Runtime.getRuntime().exec(cmd);读取和写入外部进程的类

现在我想知道是否有任何特殊的方法来检查系统上是否安装了特定的软件/工具。

就像我使用sshpass实用程序远程登录到其他机器一样,如果它不存在我想用我的程序安装它。但是对于这个我应该如何检查它是否存在?

我想到的想法是运行命令并查看响应,如果返回的字符串匹配基于我将决定它是否存在的特定表达式。

您认为这是正确的方法还是有其他方法可以找到这个?

就像在Windows上一样,我认为有像ftype,assoc等cmdline实用程序, 谢谢,

3 个答案:

答案 0 :(得分:2)

在Ubuntu / Debian中你可以使用:

dpkg -s packagname

查看是否已安装软件包。然后,您可以在应用程序中解析命令的输出。

答案 1 :(得分:1)

如果您已经知道软件二进制文件的名称(通常与进程名称相同),则可以使用which命令。

您可以在bash / shell中测试它     哪个火狐     的/ usr /斌/火狐

另外,我可以为您提供一个用B#输出读取的C#编写的示例:

string output = string.Empty;

string output = string.Empty;

try
{
    // Sets up our process, the first argument is the command
    // and the second holds the arguments passed to the command
    ProcessStartInfo ps = new ProcessStartInfo("bash");
    ps.Arguments = "-c 'firefox'";
    ps.UseShellExecute = false;

    // Redirects the standard output so it reads internally in out program
    ps.RedirectStandardOutput = true;

    // Starts the process
    using (Process p = Process.Start(ps))
    {
        // Reads the output to a string
        output = p.StandardOutput.ReadToEnd();

        // Waits for the process to exit must come *after* StandardOutput is "empty"
        // so that we don't deadlock because the intermediate kernel pipe is full.
        p.WaitForExit();
    }
}
catch
{
    // TODO manage errors
}

如果bash输出是多行的,你可以通过管道到grep命令预过滤它:

ps.Arguments = "-c 'cpuid | grep MySearchTerm'";

编辑1:回复评论

主要问题是软件安装,需要“管理”权限。 我试图创建一个解决方法,但以下行打破了所有代码:

process = Runtime.getRuntime().exec(new String[]{"/bin/bash","-c","'echo RIadminXsrv1 | sudo -S apt-get install telnet -qy'"});

在终端中,以下命令实际上会尝试安装telnet(您可能需要将用户插入/etc/sudoers以在PC上重现它)。

/bin/echo myUserPass | /usr/bin/sudo -S /usr/bin/apt-get install telnet -qy

在java中,它只会打印(echo输出)命令的剩余部分:

myUserPass | /usr/bin/sudo -S /usr/bin/apt-get install telnet -qy

这是因为我们只是用大量参数执行/bin/echo命令。 我认为可以使用bash实际运行整个命令集:

bash -c '/bin/echo myUserPass | /usr/bin/sudo -S /usr/bin/apt-get install telnet -qy'

..但事实并非如此,因为Java中的bash -c '..'不能正常工作。它说无法找到-c'echo ...'脚本文件,所以我认为它误解了-c选项。 顺便说一下,我从未在Mono C#中遇到过这种问题。

以下是整个代码段:

package javaapplication1;

import java.io.*;

public class JavaApplication1 {

    public static void main(String[] args) {

        Process process;
        String softwareToCheck = "telnet"; // Change here

        try
        {       
            if(!_softwareExists(softwareToCheck))
            {
                System.out.println("Installing missing software..");
                process = Runtime.getRuntime().exec(new String[]{"/bin/bash","-c","'echo RIadminXsrv1 | sudo -S apt-get install telnet -qy'"});

                try
                {
                    process.waitFor();
                }
                catch(InterruptedException e)
                {
                    System.out.println(e.getMessage());
                }

                if(!_softwareExists(softwareToCheck))
                {
                    System.out.println("Software is still missing!");
                }

            }
            else
            {
                System.out.println("Software is installed!");
            }
        }
        catch(IOException e)
        {
            System.out.println(e.getMessage());
        }        
    }

    private static boolean _softwareExists(String binaryName) throws IOException
    {
        String line;
        ProcessBuilder builder;
        BufferedReader reader;
        Process process;

        builder = new ProcessBuilder("/usr/bin/which", binaryName);
        builder.redirectErrorStream(true);
        process = builder.start();
        reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
        try
        {
            process.waitFor();
        }
        catch(InterruptedException e) {
            System.out.println(e.getMessage());
        }

        while ((line = reader.readLine ()) != null)
        {
            break; // Reads only the first line
        }

        return (line != null && !line.isEmpty());

    }
}

答案 2 :(得分:0)

如果软件包管理工具没有正确报告安装,我不知道有任何工具可以提供帮助。可能是某些工具已安装但未更新数据库。

检查目标可执行文件是否存在于$ PATH和标准位置的任何目录中可能很有用。

  String pathString = System.getenv("PATH");
   String[]  dirs= pathString.split(':');
   String[]  exes= { "name1", "name2" ....};

   for ( String exename : exes) {
     for ( String dirname : dirs) {
             File exeFile=new File( dirname, exename);
             //do some checks if file exists etc.
     }
   }