I'm trying to process data obtained from a run of diff to an instance of GNU grep in a java program. I've managed to get the output of diff using the Process object's outputStream, but I'm currently having programs sending this data to the standard input of grep (through another Process object created in Java). Running Grep with the input only returns status code 1. What am I doing wrong?
Below is the code I have so far:
public class TestDiff {
final static String diffpath = "/usr/bin/";
public static void diffFiles(File leftFile, File rightFile) {
Runtime runtime = Runtime.getRuntime();
File tmp = File.createTempFile("dnc_uemo_", null);
String leftPath = leftFile.getCanonicalPath();
String rightPath = rightFile.getCanonicalPath();
Process proc = runtime.exec(diffpath+"diff -n "+leftPath+" "+rightPath, null);
InputStream inStream = proc.getInputStream();
try {
proc.waitFor();
} catch (InterruptedException ex) {
}
byte[] buf = new byte[256];
OutputStream tmpOutStream = new FileOutputStream(tmp);
int numbytes = 0;
while ((numbytes = inStream.read(buf, 0, 256)) != -1) {
tmpOutStream.write(buf, 0, numbytes);
}
String tmps = new String(buf,"US-ASCII");
inStream.close();
tmpOutStream.close();
FileInputStream tmpInputStream = new FileInputStream(tmp);
Process addProc = runtime.exec(diffpath+"grep \"^a\" -", null);
OutputStream addProcOutStream = addProc.getOutputStream();
numbytes = 0;
while ((numbytes = tmpInputStream.read(buf, 0, 256)) != -1) {
addProcOutStream.write(buf, 0, numbytes);
addProcOutStream.flush();
}
tmpInputStream.close();
addProcOutStream.close();
try {
addProc.waitFor();
} catch (InterruptedException ex) {
}
int exitcode = addProc.exitValue();
System.out.println(exitcode);
inStream = addProc.getInputStream();
InputStreamReader sr = new InputStreamReader(inStream);
BufferedReader br = new BufferedReader(sr);
String line = null;
int numInsertions = 0;
while ((line = br.readLine()) != null) {
String[] p = line.split(" ");
numInsertions += Integer.parseInt(p[1]);
}
br.close();
}
}
Both leftPath and rightPath are File objects pointing to the files to be compared.
Just a couple of hints, you could:
pipe the output of diff directly into grep: diff -n leftpath rightPath | grep "^a"
read the output file from grep instead of stdin: grep "^a" tmpFile
use ProcessBuilder to get your Process where you can easily avoid a blocking process because you're not reading stderr by using redirectErrorStream
Related
I am trying to execute commands using Java. So when I try to convert the process Inputstream to string using BufferedReader, the code works if I call process.waitFor() after processing the inputstream to string. But when I try to convert the process input stream using ByteArrayOutputStream to string, the results are not returned if I write process.waitFor() after processing the inputstream to string. It works only process.waitFor is written before inputstream.isavailable(). I don't understand why this is behaving like this? Also I want to know how to determing the buffer array size incase of using ByteArrayStream. I am trying to use isavailable() to know to number of bytes.
``ProcessBuilder pb = new ProcessBuilder();
String cmd = "ls -l /Users/uma/data";
pb.command("bash", "-c",cmd);
try {
Process process = pb.start();
StringBuilder output = new StringBuilder();
BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
output.append(line + "\n");
}
intexitVal = process.waitFor();
if (exitVal == 0) {
System.out.println("Success!");
System.out.println(output);
System.exit(0);
} else {
try (final BufferedReader b = new BufferedReader(new InputStreamReader(process.getErrorStream()))) {
String errorline;
if ((errorline = b.readLine()) != null)
System.out.println(errorline);
} catch (final IOException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
`
``ProcessBuilder pb = new ProcessBuilder();
String cmd = "ls -l /Users/uma/data";
pb.command("bash", "-c",cmd);
try {
Process process = pb.start();
int exitVal = process.waitFor();
InputStream is = process.getInputStream();
ByteArrayOutputStream result = new ByteArrayOutputStream();
byte[] buffer = newbyte[is.available()];
int length;
while ((length = is.read(buffer)) != -1) {
result.write(buffer, 0, length);
}
String output = result.toString();
if (exitVal == 0) {
System.out.println("Success!");
System.out.println(output);
System.exit(0);
} else {
try (final BufferedReader b = new BufferedReader(new InputStreamReader(process.getErrorStream()))) {
String errorline;
if ((errorline = b.readLine()) != null)
System.out.println(errorline);
} catch (final IOException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}`
How to determine the buffer size? Also when should I call waitFor()?
waitFor() waits for the target process to exit, and returns the exit code given by it. You can use it to wait for the program to stop, before logging any errors or checking the exit code.
As for the buffer size, I recommend using is.readAllBytes() if you just want to get the entire input stream as a byte array. To then convert that to a string, use new String(is.readAllBytes());.
If you just want to stream the content of the input stream into another stream (such as System.out or System.err), use this:
InputStream is = /* get input stream */;
byte[] buffer = new byte[128];
int read;
while((read = is.read(buffer)) != -1) {
System.out.write(buffer, 0, read);
}
This will just write the entire is input stream into System.out, you can configure or change this as you'd like.
How to execute docker exec -it netvertex bash by Java Program.
By this i am trying to execute but not working
public void execute(String command) {
try {
System.out.println("===========>" + command);
Channel channel1 = session.openChannel("exec");
((ChannelExec) channel1).setPty(true);
((ChannelExec) channel1).setCommand(command);
// X Forwarding
// channel.setXForwarding(true);
//channel.setInputStream(System.in);
channel1.setInputStream(null);
//channel.setOutputStream(System.out);
//FileOutputStream fos=new FileOutputStream("/tmp/stderr");
//((ChannelExec)channel).setErrStream(fos);
((ChannelExec) channel1).setErrStream(System.err);
InputStream in1 = channel1.getInputStream();
channel1.connect();
byte[] tmp1 = new byte[1024];
while (true) {
while (in1.available() > 0) {
int i = in1.read(tmp1, 0, 1024);
if (i < 0) break;
System.out.print(new String(tmp1, 0, i));
}
if (channel1.isClosed()) {
if (in1.available() > 0) continue;
System.out.println("exit-status: " + channel1.getExitStatus());
break;
}
try {
Thread.sleep(1000);
} catch (Exception ee) {
}
}
} catch (Exception e) {
}
}
By above code my other Linux command are working. But docker exec it not working.
And the other option i tried
try {
String host = "root#10.121.21.224";
String passwd = "root#10";
Terminal exec = new Terminal(pageUiUtils);
exec.loginSSH(host, passwd);
String[] command = {"docker", "exec", "-it", "netvertex", "bash"};
ProcessBuilder pb = new ProcessBuilder(command);
pb.inheritIO();
Process proc = pb.start();
InputStream is = proc.getInputStream();
OutputStream os = proc.getOutputStream();
BufferedReader reader
= new BufferedReader(new InputStreamReader(is));
BufferedWriter writer
= new BufferedWriter(new OutputStreamWriter(os));
writer.write("pwd");
writer.flush();
String line = "";
while ((line = reader.readLine()) != null) {
System.out.print(line + "\n");
}
exec.execute("docker exec -it netvertex bash");
pageUiUtils.pause(1000);
exec.execute("pwd");
//proc.waitFor();
} catch (Exception e) {
e.printStackTrace();
}
by above code also showing error that
The input device is not a TTY
I want to execute curl command from java code. I have already seen couple of documents, stackoverflow questions regarding the same. But it is not giving the desired result, I am trying to run this curl command :
curl --noproxy <ip>
-i
-d "INSERT IN GRAPH <http://graph.com>{ <prop/Advanced_Data_Types> rdf:type owl:NamedIndividual ,
<http://abcd/Video> ,
<http://abcd/LearningResource/BookChapter> ;
<http://abcd/hasAuthor> <prop/Eric_Grimson> ;
<http://abcd/inLanguage> <http://abcd/#Hindi> ;
<http://abcd/sourceOrganization> <prop/IIT_Hyderabad> .}"
-u "demo:demo"
-H "Content-Type: application/sparql-query" http://<ip>:<port>/DAV/home/dba/xx
And the JAVA code :
ProcessBuilder pb = new ProcessBuilder(
"curl",
"-i",
"-d \"INSERT IN GRAPH <http://graph.com>{ <prop/Advanced_Data_Types> rdf:type owl:NamedIndividual ,<http://abcd/Video> ,<http://abcd/LearningResource/BookChapter> ;<http://abcd/hasAuthor> <prop/Eric_Grimson> ;<http://abcd/inLanguage> <http://abcd/#Hindi> ;<http://abcd/sourceOrganization> <prop/IIT_Hyderabad> .} ",
"-u \"demo:demo\"",
"-H \"Content-Type: application/sparql-query\"",
"http://<ip>:<port>/DAV/home/dba/xx");
pb.redirectErrorStream(true);
Process p = pb.start();
InputStream is = p.getInputStream();
String line;
BufferedInputStream bis = new BufferedInputStream(is);
System.out.println(bis);
Is anything wrong in my code? I want to use this particular curl command. Please help.
I used it like this that executing curl in java.
public static String invokeCurlGet(String _host, int _connectTimeout, int _maxTimeout, int _maxResLength, Charset _charset) throws IOException
{
byte[] res = execute("curl --connect-timeout " + _connectTimeout + " --max-time " + _maxTimeout + " -X GET " + _host, _maxResLength);
return new String(res, _charset);
}
public static byte[] execute(String _cmd, int _maxResLength) throws IOException
{
Process process = Runtime.getRuntime().exec(_cmd);
try
{
int result = process.waitFor();
if(result != 0)
{
throw new IOException("Fail to execute cammand. Exit Value[" + result + "], cmd => " + _cmd);
}
}
catch(InterruptedException e)
{
process.destroyForcibly();
throw new IOException(e);
}
BufferedInputStream in = null;
try
{
ByteArrayOutputStream out = new ByteArrayOutputStream();
in = new BufferedInputStream(process.getInputStream());
byte[] buf = new byte[1024];
int read = 0;
while((read = in.read(buf)) != -1)
{
out.write(buf, 0, read);
out.flush();
if(_maxResLength > 0 && out.size() > _maxResLength)
{
throw new IOException("Response length exceeded.");
}
}
return out.toByteArray();
}
finally
{
if(in != null)
{
in.close();
}
}
}
public static void main(String[] args) throws Exception
{
System.out.println(invokeCurlGet("http://127.0.0.1:9000?messageId=aaaaaaaa&to=asdfsefwaf", 3, 10, 0, Charset.defaultCharset()));
// System.out.println(invokeCurlGet("https://github.com", 1, 1, 0, Charset.defaultCharset()));
}
Your understanding on how to convert a command line to a list of string arguments is slightly incorrect. (This is roughly equivalent to how a Unix shell works).
Generally when a space is present on the command line it means starting a new argument. So
"-H \"Content-Type: application/sparql-query\""
should be
"-H", "\"Content-Type: application/sparql-query\""
My goal is to print all the internet connections on my computer. When i type netstat on cmd i get the internet connections list. I wanted to do the same in java, automatically.
My code:
Runtime runtime = Runtime.getRuntime();
process = runtime.exec(pathToCmd);
byte[] command1array = command1.getBytes();//writing netstat in an array of bytes
OutputStream out = process.getOutputStream();
out.write(command1array);
out.flush();
out.close();
readCmd(); //read and print cmd
But with this code i get C:\eclipse\workspace\Tracker>Mais? instead of the list of connections. Obviously i'm working with eclipse, in windows 7. What am I doing wrong? I've looked in similar topics but i cound't find whats wrong. Thank you for the answers.
EDIT:
public static void readCmd() throws IOException {
is = process.getInputStream();
isr = new InputStreamReader(is);
br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
}
Try this : I was able to create a file in my default temporary directory with all the connections
final String cmd = "netstat -ano";
try {
Process process = Runtime.getRuntime().exec(cmd);
InputStream in = process.getInputStream();
File tmp = File.createTempFile("allConnections","txt");
byte[] buf = new byte[256];
OutputStream outputConnectionsToFile = new FileOutputStream(tmp);
int numbytes = 0;
while ((numbytes = in.read(buf, 0, 256)) != -1) {
outputConnectionsToFile.write(buf, 0, numbytes);
}
System.out.println("File is present at "+tmp.getAbsolutePath());
} catch (Exception e) {
e.printStackTrace(System.err);
}
You can also use an instance of java.util.Scanner to read the output of the command.
public static void main(String[] args) throws Exception {
String[] cmdarray = { "netstat", "-o" };
Process process = Runtime.getRuntime().exec(cmdarray);
Scanner sc = new Scanner(process.getInputStream(), "IBM850");
sc.useDelimiter("\\A");
System.out.println(sc.next());
sc.close();
}
final String cmd = "netstat -ano";
try {
Process process = Runtime.getRuntime().exec(cmd);
InputStream in = process.getInputStream();
InputStreamReader isr = new InputStreamReader(in);
BufferedReader br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (Exception e) {
e.printStackTrace(System.err);
} finally{
in = null;
isr = null;
br = null;
}
I'm working on something that requires me to start to subprocess(command prompt) and execute some commands on it. I need to fetch the output from the subprocess and store it in a file or String.
here's what I have done so far, and it doesn't work:
public static void main(String args[])
{
try
{
Runtime RT = Runtime.getRuntime();
String command = "cmd /c start javap java.lang.String";
File file = new File("write.txt");
Writer output = new BufferedWriter(new FileWriter(file));
BufferedReader br = new(BufferedReader(newInputStreamReader(RT.exec(command).getInputStream()));
String temp = br.readLine();
while(!temp.equals(null))
{
output.write(temp);
temp = br.readLine();
}
output.close();
RT.exec("exit");
}
catch(Exception e)
{
System.out.println(e);
}
}
Start changing this:
new(BufferedReader(newInputStreamReader(
To:
new BufferedReader(new InputStreamReader(
Compile and see if you still have the problem
edit
Also, there is a good reason why you shouldn't catch Exception, you also catch programming errors like a NullPointerException
while( !temp.equals(null)) { //Throws NullPointerExceptin when temp is null
Change it with:
while( temp != null ) { //!temp.equals(null)) {
Finally you don't have to "exit" since you're not inside the cmd really.
Corrected version
This version runs as you intend:
import java.io.*;
class Rt {
public static void main(String args[]) throws Exception {
Runtime RT = Runtime.getRuntime();
String command = "javap java.lang.String" ;
File file = new File("write.txt");
Writer output = new BufferedWriter(new FileWriter(file));
BufferedReader br = new BufferedReader(new InputStreamReader(RT.exec(command).getInputStream()));
String temp = br.readLine();
while( temp != null ) { //!temp.equals(null)) {
output.write(temp);
temp = br.readLine();
}
output.close();
//RT.exec("exit");
}
}
edit
Final remarks:
Since Java 1.5 the preferred way to invoke a command is using ProcessBuilder and it is better if you use an array of strings instead of a single string ( or varargs ).
When you're building your output you can get rid of the file object and pass the file name directly to the filewriter.
While reading the line you can assign and evaluate in the condition.
Java's coding conventions suggest to use the opening brace in the same like.
This would be my version of your code:
class Rt {
public static void main(String args[]) throws Exception {
Writer output = new BufferedWriter(new FileWriter ( "write.txt"));
InputStream in = new ProcessBuilder("javap", "java.lang.String").start().getInputStream();
BufferedReader br = new BufferedReader( new InputStreamReader(in));
String line = null;
while( ( line = br.readLine() ) != null ) {
output.write( line );
}
output.close();
}
}
It might need still some work, but I hope it helps you.
Here is an example which should work:
StringBuffer outStream = new StringBuffer();
StringBuffer errStream = new StringBuffer();
Runtime runtime = Runtime.getRuntime();
Process process = null;
try {
process = runtime.exec(command);
} catch (IOException ex) {
ex.printStackTrace();
return;
}
InputStream outIs = process.getInputStream();
MonitorOutputThread sout = new MonitorOutputThread(outIs, outStream);
sout.run();
InputStream errIs = process.getErrorStream();
MonitorOutputThread serr = new MonitorOutputThread(errIs, errStream);
serr.run();
while (sout.isAlive() || serr.isAlive()) {
try {
sleep(100);
} catch (InterruptedException ex) {
ex.printStackTrace();
// ignore
}
}
And the code for MonitorOutputThread
private class MonitorOutputThread extends Thread {
private final InputStream is;
private final StringBuffer output;
public MonitorOutputThread(InputStream is, StringBuffer output) {
this.is = is;
this.output = output;
}
#Override
public void run() {
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line = null;
try {
while ((line = br.readLine()) != null) {
output.append(line);
output.append(LINE_SEPARATOR);
}
if (output.length() >= 1) {
char lastChar = output.charAt(output.length() - 1);
if (lastChar == '\n') {
output.deleteCharAt(output.length() - 1);
}
}
} catch (IOException ex) {
ex.printStackTrace();
return;
}
}
}
This should catch both the standard output and standard error of the command.
DevDaily has a simple example of how to work with Process class.
See the snippet:
import java.io.*;
public class JavaRunCommand {
public static void main(String args[]) {
String s = null;
try {
// run the Unix "ps -ef" command
// using the Runtime exec method:
Process p = Runtime.getRuntime().exec("ps -ef");
BufferedReader stdInput = new BufferedReader(new
InputStreamReader(p.getInputStream()));
BufferedReader stdError = new BufferedReader(new
InputStreamReader(p.getErrorStream()));
// read the output from the command
System.out.println("Here is the standard output of the command:\n");
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
// read any errors from the attempted command
System.out.println("Here is the standard error of the command (if any):\n");
while ((s = stdError.readLine()) != null) {
System.out.println(s);
}
System.exit(0);
}
catch (IOException e) {
System.out.println("exception happened - here's what I know: ");
e.printStackTrace();
System.exit(-1);
}
}
}
or even check this code I've writen some time ago