I'm trying to parse some text that is generated by a command-line command. The command-line command I want to use is Ubuntu's landscape-sysinfo. In an attempt to run this, I'm using the following Java code:
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec(new String[] { "landscape-sysinfo" });
The thing I'm not sure of is, how do I get the output of the command-line command into a string that I work with in my Java app?
Thank you so much for your valuable insights!
Hope this one helps its what the Apprentice Queue said
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class BatchExecuteService {
public static void main(String[] args) {
BatchExecuteService batchExecuteService = new BatchExecuteService();
batchExecuteService.run();
}
public void run() {
try {
String cmds[] = {"D:\\test.bat"};
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec(cmds);
process.getOutputStream().close();
InputStream inputStream = process.getInputStream();
InputStreamReader inputstreamreader = new InputStreamReader(inputStream);
BufferedReader bufferedrReader = new BufferedReader(inputstreamreader);
String strLine = "";
while ((strLine = bufferedrReader.readLine()) != null) {
System.out.println(strLine);
}
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
}
Reference
Related
I'm trying to get the terminal width by executing tput cols command and parse the output.
public class Test {
public static void main(String[] args) throws IOException {
Process p = Runtime.getRuntime().exec("tput cols");
String output = new String(p.getInputStream().readAllBytes());
System.out.println(output);
}
}
But it outputs empty string.
However, if I executes it in the terminal I can see the output.
You need to wait for the command to terminate. When you read the output of the tput command, it has not yet terminated and therefore there is not yet any output.
I prefer using class ProcessBuilder rather than class Runtime.
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
public class PrcBldTs {
public static void main(String[] args) {
ProcessBuilder pb = new ProcessBuilder("tput", "cols");
try {
Process p = pb.start();
InputStream is = p.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line = br.readLine();
while (line != null) {
System.out.println(line);
line = br.readLine();
}
int result = p.waitFor();
System.out.println("result = " + result);
}
catch (Exception x) {
x.printStackTrace();
}
}
}
I am trying to create a program (personal practice) to access CMD and type any command you want, as if you were working on cmd.exe;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;
public class CMD_Live {
public static void main(String[] args) throws IOException {
// The purpose of this program is to use Java to perform CMD commands as if you are working on it live
Scanner ScanCMD = new Scanner(System.in);
while(true) {
System.out.print("Insert your Command> ");
String CMDcommand = ScanCMD.nextLine();
Process processToCMD = Runtime.getRuntime().exec(CMDcommand);
BufferedReader readerToCMD = new BufferedReader(new InputStreamReader(processToCMD.getInputStream()));
String line;
while ((line = readerToCMD.readLine()) != null) {
System.out.println(line);
}
System.out.println();
readerToCMD.close();
}
}
}
The problem with this code is, it works for straightforward commands,
like ping google.com, or nslookup google.com,
but if I insert nslookup and hit enter to access advance mode, then the response goes off.
Is there a way to fix it?
This should work for you:
ProcessBuilder processBuilder = new ProcessBuilder(CMDcommand); //note, that you can build your command here step by step.
Process process = processBuilder.start();
String response = null;
InputStream inputStream = process.getInputStream();
BufferedReader bufferedInputStream = new BufferedReader(new InputStreamReader(inputStream));
//and then do whatever you want to do.. my example is this:
while(response=bufferedInputStream.readLine()!=null) {
..some code..
}
} catch (IOException e) {
e.printStackTrace();
}
I am trying to set the date and time of a linux system from a remote system using Java. In order to do that I have created a server to accept time from the remote system as:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class Set_date_n_time {
public static void main(String[] args) throws IOException, InterruptedException {
// TODO Auto-generated method stub
String date_time = new String();
//#SuppressWarnings("resource")
ServerSocket s1 = new ServerSocket(7105);
System.out.println("server started");
while (true) {
Socket sckt = s1.accept();
InputStream input = sckt.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
date_time = reader.readLine();
String command="sudo date -s "+"\""+date_time+"\"";
Process p;
try {
p = Runtime.getRuntime().exec(command);
p.waitFor();
System.out.println ("date set");
p.destroy();
} catch (Exception e) {}
}
}
}
and the remote system from which the time will be copied as:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Fix_my_Date {
public static void main(String args[]) throws IOException {
String addr_list=args[0];
String[] hostList = readAddressList(addr_list);
for(int i=0; i<hostList.length;i++) {
setDate(hostList[i]);
}
}
//#SuppressWarnings("resource")
private static void setDate(String address) throws IOException {
{
Scanner sc = new Scanner(System.in);
Socket s = null;
String date =new String();
String time = new String();
try {
s = new Socket(address, 7105);
System.out.println("connection to "+address+" done");
Process p, p1;
try {
p = Runtime.getRuntime().exec("date +%Y%m%d");
BufferedReader br = new BufferedReader(
new InputStreamReader(p.getInputStream()));
date = br.readLine();
br.close();
p.waitFor();
p.destroy();
p1 = Runtime.getRuntime().exec("date +%H:%M:%S");
BufferedReader br1 = new BufferedReader(
new InputStreamReader(p1.getInputStream()));
time = br1.readLine();
br1.close();
p1.waitFor();
p1.destroy();
PrintStream pr = new PrintStream(s.getOutputStream());
pr.print(date+" "+time+"");
sc.close();
s.close();
} catch (Exception e) {
System.out.println("Problem Setting date and time");
}
//s.close();
} catch (Exception e) {
System.out.println("Couldn't connect to: "+address+"");
sc.close();
//s.close();
}
}
return;
}
private static String[] readAddressList(String addr_list) throws IOException {
FileReader fileReader = new FileReader(addr_list);
BufferedReader bufferedReader = new BufferedReader(fileReader);
List<String> lines = new ArrayList<String>();
String line = null;
while ((line = bufferedReader.readLine()) != null)
{
lines.add(line);
}
bufferedReader.close();
System.out.println("Loaded the host list");
return lines.toArray(new String[lines.size()]);
}
}
But the time is not being set by the server code. Where is my mistake?
The mistake I, you, and lots of others make is also (besides the other helpful answers here) that you don't read Standard Output and Standard Error and if your command produces any output or error it blocks because there is no buffer that it can write to which you may observe with strace.
This could be fixed with an extra thread as described here: https://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html
If you use sudo it might fail depending on the sudo settings if it doesn't allow sudo without a terminal (requiretty), see for more info e.g.: https://bugzilla.redhat.com/show_bug.cgi?id=1196451
Are you trying to set the time on a VM? If that's the case, it may be set to synchronise to the host which overwrites your date -s command.
I could not get it to work (yet) with Runtime.exec(), but it works perfectly with ProcessBuilder. Here it is:
package set_date_n_time;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class Set_date_n_time {
public static void main(String[] args) throws IOException, InterruptedException {
// TODO Auto-generated method stub
String date_time = new String();
//#SuppressWarnings("resource")
ServerSocket s1 = new ServerSocket(7105);
System.out.println("server started");
while (true) {
Socket sckt = s1.accept();
InputStream input = sckt.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
date_time = reader.readLine();
ProcessBuilder builder = new ProcessBuilder("date", "--set=" + date_time + "");
final Process p = builder.start();
p.waitFor();
p.destroy();
}
}
}
Obviously you have to run as root and make sure you run
sudo systemctl stop systemd-timesyncd.service
or something similar to make sure the system does not override you date fixing.
In case you need, or prefer, to use Runtime.exec() then (don't ask me why) just change:
String command = "sudo date -s " + "\"" + date_time + "\"";
to
String[] command = new String[]{"sudo", "date", "-s", date_time};
in class Set_date_n_time.
Replace this:
} catch (Exception e) {}
With this:
} catch (Exception e) {
throw new IllegalStateException("Unexpected exception", e);
}
As Ole V.V. said, the empty catch-block in your code is almost certainly discarding real failures you care about. I would guess that either sudo is rejecting the call or the command itself is malformed. The exception will tell you exactly what is going wrong.
If you discover there are exceptions being thrown that you really do want to ignore, handle them separately, but you should almost never catch (Exception e) and throw away the exception.
It's also a good idea to use ProcessBuilder instead of Runtime.exec(). This is a more powerful and flexible API for interacting with sub-processes. In particular, never use Runtime.exec(String); although it works for simple commands it is not a shell, and will fail in surprising ways for commands with special characters, like quotes or whitespace.
For example:
p = new ProcessBuilder("sudo", "date", "-s", date_time).start();
I want to open installed softwares in my pc using a java program. For Example- If I want to open Microsoft Outlook using java program, how would I do it? Thanks in advance!!
You can use Java ProcessBuilder to launch any program.
Example from this site
package com.javacodegeeks.process;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class ProcessBuilderExample {
public static void main(String[] args) throws InterruptedException,
IOException {
ProcessBuilder pb = new ProcessBuilder("echo", "This is ProcessBuilder Example from JCG");
System.out.println("Run echo command");
Process process = pb.start();
int errCode = process.waitFor();
System.out.println("Echo command executed, any errors? " + (errCode == 0 ? "No" : "Yes"));
System.out.println("Echo Output:\n" + output(process.getInputStream()));
}
private static String output(InputStream inputStream) throws IOException {
StringBuilder sb = new StringBuilder();
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(inputStream));
String line = null;
while ((line = br.readLine()) != null) {
sb.append(line + System.getProperty("line.separator"));
}
} finally {
br.close();
}
return sb.toString();
}
}
I am using intellij both on my imac and mac book. when i run the following code on my mac book, everything works.
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
public class Main {
public ProcessBuilder pb;
public Main(){
try {
pb = new ProcessBuilder();
pb.directory(new File("~/IdeaProjects/test"));
Map<String, String> env;
env = pb.environment();
env.put("PATH", "/usr/local/fsl/bin/");
} catch (Exception e) {
e.printStackTrace();
}
}
public void getMeanImage(String base, String file){
List<String> cmd = new LinkedList<>();
cmd.add("fslmaths");
cmd.add(base + file);
cmd.add("-Tmean");
cmd.add(base + file + "_mean");
pb.command(cmd);
try {
String s = "";
Process p = pb.start();
BufferedReader stdInput = new BufferedReader(new
InputStreamReader(p.getInputStream()));
BufferedReader stdError = new BufferedReader(new
InputStreamReader(p.getErrorStream()));
// read the output from the command
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
while ((s = stdError.readLine()) != null) {
System.out.println(s);
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String [ ] args) {
Main m = new Main();
m.getMeanImage("", "scan.nii.gz");
}
}
On the imac I run into problems. I copied the PATH value used by printenv.
env.put("PATH", "/usr/local/fsl/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin");
I get the exception:
java.io.IOException: Cannot run program "fslmaths" (in directory "~/IdeaProjects/test"): error=2, No such file or directory
Why can't the process builder find the program fslmaths in /usr/local/fsl/bin on the imac?
which fslmaths
/usr/local/fsl/bin/fslmaths
thanks in advance,
Martin
I found the solution. In the 'Run/Debug Configurations' of intellij under 'Environment Variables' the checkbox 'Include parent environment variables' was not enabled.