如何以编程方式检查是否在使用Java的ubuntu上安装了软件实用程序
我正在为自己的学习开发Java项目,我所做的是一个可以使用 Runtime.getRuntime()。exec(cmd)读写外部进程的类;
I am working on a Java Project for my own learning, what i have made is a class which can both read and write to external process using Runtime.getRuntime().exec(cmd);
现在我想知道是否有任何特殊的方法来检查系统上是否安装了特定的软件/工具。
Now i was wondering is there any special way of checking if a particular software/tool is installed on the system.
就像我使用sshpass实用程序远程登录到其他机器一样,如果它不存在我想用我的程序安装它。但是对于这个我应该如何检查它是否存在?
Like i use sshpass utility to remotely login to other machines, and if it is not there already i would like to install it using my program. But for this how should i go about checking if it exists there or not?
我想到的想法是运行命令并查看响应,如果返回的字符串与特定表达式匹配,则基于我将决定它是否存在或非存在。
The idea i have in my mind is to run the command and see the response, if the returned string matches particular expression based on that i would decide it's existence or non-existence.
您认为这是正确的方法还是有其他方法可以找到这个?
Do you think it is the right approach or is there any other way to find out this?
就像在Windows上一样,我认为有像ftype,assoc等cmdline工具,
谢谢你,
Like on windows, i think there are cmdline utilities like ftype, assoc etc, thank you,
如果您已经知道软件二进制文件的名称(通常与进程名称相同),您可以使用
命令。
If you already know the name of the software binary (which is usually the same to process name) you can use which
command.
你可以在bash / shell中测试它
firefox
/ usr / bin / firefox
You can test it in bash/shell which firefox /usr/bin/firefox
另外,我可以为您提供一个用B#输出读取的C#编写的示例:
Also I can supply you an example written in C# of bash output reading:
string output = string.Empty;
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命令预过滤它:
If the bash output is multi-line you can pre-filter it by piping to the grep command:
ps.Arguments = "-c 'cpuid | grep MySearchTerm'";
编辑1:回复评论
主要问题是软件安装,需要管理权限。
我试图创建一个解决方法,但以下行打破了所有代码:
The major problem is the software installation, which requires "administrative" rights. I've tried to create a workaround, but the following line breaks all code:
process = Runtime.getRuntime().exec(new String[]{"/bin/bash","-c","'echo RIadminXsrv1 | sudo -S apt-get install telnet -qy'"});
在终端中,以下命令实际上会尝试安装telnet(您可能需要将用户插入 / etc / sudoers 重现它在你的电脑上。)
While in terminal the following command will actually attempt to install telnet (you might have to insert your user into /etc/sudoers to reproduce it on your PC).
/ bin / echo myUserPass | / usr / bin / sudo -S / usr / bin / apt-get install telnet -qy
在java中它只会打印( echo
output)命令的剩余部分:
In java it will simply print (echo
output) the remaining part of the command:
myUserPass | / usr / bin / sudo -S / usr / bin / apt-get install telnet -qy
这是因为我们只是在执行 / bin / echo
包含大量参数的命令。
我认为可以使用bash实际运行整个命令集:
This happens because we are simply executing /bin/echo
command with a lot of parameters.
I thought that it is possible to actually run the entire set of commands using bash:
bash -c '/bin/echo myUserPass | /usr/bin/sudo -S /usr/bin/apt-get install telnet -qy'
..但它不是,因为Java中的 bash -c'..'
不能正常工作。它说无法找到-c'echo ...'脚本文件,所以我认为它误解了-c选项。
BTW我从来没有在Mono C#中遇到过这种问题。
..but it's not, because bash -c '..'
in Java doesn't work like it should. It says that -c 'echo ...' script file can not be found, so I suppose that it misinterprets -c option.
BTW I have never had this kind of problem in 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());
}
}