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);
If you already know the name of the software binary (which is usually the same to process name) you can use which
command.
You can test it in bash/shell which firefox /usr/bin/firefox
Also I can supply you an example written in C# of bash output reading:
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
}
If the bash output is multi-line you can pre-filter it by piping to the grep command:
ps.Arguments = "-c 'cpuid | grep MySearchTerm'";
EDIT 1: Reply to comments
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'"});
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
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
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'
..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#.
Here is the entire snippet:
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());
}
}