Runtime exec java linux

How to invoke a Linux shell command from Java

I am trying to execute some Linux commands from Java using redirection (>&) and pipes (|). How can Java invoke csh or bash commands? I tried to use this:

Process p = Runtime.getRuntime().exec("shell command"); 

i can understand the question for other commands, but for cat: why the hell don’t you just read in the file?

Everyone gets this wrong first time — Java’s exec() does not use the underlying system’s shell to execute the command (as kts points out). The redirection and piping are features of a real shell and are not available from Java’s exec().

System.exit(0) is not inside conditional checking if process is done, so it will always exit without outputting errors. Never write conditionals without braces, to avoid exactly this sort of mistake.

3 Answers 3

exec does not execute a command in your shell

Process p = Runtime.getRuntime().exec(new String[]); 

EDIT:: I don’t have csh on my system so I used bash instead. The following worked for me

Process p = Runtime.getRuntime().exec(new String[]); 

@Narek. Sorry about that. I fixed it by removing the extra \» ‘s Apparently they aren’t needed. I don’t have csh on my system, but it works with bash.

Warning: this solution will very likely run into the typical problem of it hanging because you didn’t read its output and error streams. For example: stackoverflow.com/questions/8595748/java-runtime-exec

Use ProcessBuilder to separate commands and arguments instead of spaces. This should work regardless of shell used:

import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.List; public class Test < public static void main(final String[] args) throws IOException, InterruptedException < //Build command Listcommands = new ArrayList(); commands.add("/bin/cat"); //Add arguments commands.add("/home/narek/pk.txt"); System.out.println(commands); //Run macro on target ProcessBuilder pb = new ProcessBuilder(commands); pb.directory(new File("/home/narek")); pb.redirectErrorStream(true); Process process = pb.start(); //Read output StringBuilder out = new StringBuilder(); BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream())); String line = null, previous = null; while ((line = br.readLine()) != null) if (!line.equals(previous)) < previous = line; out.append(line).append('\n'); System.out.println(line); >//Check result if (process.waitFor() == 0) < System.out.println("Success!"); System.exit(0); >//Abnormal termination: Log command parameters and output and throw ExecutionException System.err.println(commands); System.err.println(out.toString()); System.exit(1); > > 

@Stephan I’ve updated the example code above to remove the logging statements and variables that were declared outside the pasted code, and it should now compile & run. Feel free to try and let me know how it works out.

Читайте также:  Astra linux настройка dns сервера

Building on @Tim’s example to make a self-contained method:

import java.io.BufferedReader; import java.io.File; import java.io.InputStreamReader; import java.util.ArrayList; public class Shell < /** Returns null if it failed for some reason. */ public static ArrayListcommand(final String cmdline, final String directory) < try < Process process = new ProcessBuilder(new String[] ) .redirectErrorStream(true) .directory(new File(directory)) .start(); ArrayList output = new ArrayList(); BufferedReader br = new BufferedReader( new InputStreamReader(process.getInputStream())); String line = null; while ( (line = br.readLine()) != null ) output.add(line); //There should really be a timeout here. if (0 != process.waitFor()) return null; return output; > catch (Exception e) < //Warning: doing this is no good in high quality applications. //Instead, present appropriate error messages to the user. //But it's perfectly fine for prototyping. return null; >> public static void main(String[] args) < test("which bash"); test("find . -type f -printf '%T@\\\\t%p\\\\n' " + "| sort -n | cut -f 2- | " + "sed -e 's/ /\\\\\\\\ /g' | xargs ls -halt"); >static void test(String cmdline) < ArrayListoutput = command(cmdline, "."); if (null == output) System.out.println("\n\n\t\tCOMMAND FAILED: " + cmdline); else for (String line : output) System.out.println(line); > > 

By the way, if somebody can tell me why I need four and eight backslashes there, instead of two and four, I can learn something. There is one more level of unescaping happening than what I am counting.

Edit: Just tried this same code on Linux, and there it turns out that I need half as many backslashes in the test command! (That is: the expected number of two and four.) Now it’s no longer just weird, it’s a portability problem.

Источник

How to run Linux commands in Java?

I want to create diff of two files. I tried searching for code in Java that does it, but didnt find any simple code/ utility code for this. Hence, I thought if I can somehow run linux diff/sdiff command from my java code and make it return a file that stores the diff then it would be great. Suppose there are two files fileA and fileB. I should be able to store their diff in a file called fileDiff through my java code. Then fetching data from fileDiff would be no big deal.

10 Answers 10

You can use java.lang.Runtime.exec to run simple code. This gives you back a Process and you can read its standard output directly without having to temporarily store the output on disk.

For example, here’s a complete program that will showcase how to do it:

import java.io.BufferedReader; import java.io.InputStreamReader; public class testprog < public static void main(String args[]) < String s; Process p; try < p = Runtime.getRuntime().exec("ls -aF"); BufferedReader br = new BufferedReader( new InputStreamReader(p.getInputStream())); while ((s = br.readLine()) != null) System.out.println("line: " + s); p.waitFor(); System.out.println ("exit: " + p.exitValue()); p.destroy(); >catch (Exception e) <> > > 

When compiled and run, it outputs:

line: ./ line: ../ line: .classpath* line: .project* line: bin/ line: src/ exit: 0 

You can also get the error stream for the process standard error, and output stream for the process standard input, confusingly enough. In this context, the input and output are reversed since it’s input from the process to this one (i.e., the standard output of the process).

Читайте также:  Linux all in one iso

If you want to merge the process standard output and error from Java (as opposed to using 2>&1 in the actual command), you should look into ProcessBuilder .

Ok, thanks. I worried that using p.exitValue() might have some esoteric advantage. So it’s just unecessary bloat in the Process API.

You can also write a shell script file and invoke that file from the java code. as shown below

Write the linux commands in the script file, once the execution is over you can read the diff file in Java.

The advantage with this approach is you can change the commands with out changing java code.

You need not store the diff in a 3rd file and then read from in. Instead you make use of the Runtime.exec

Process p = Runtime.getRuntime().exec("diff fileA fileB"); BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream())); while ((s = stdInput.readLine()) != null)

try to use unix4j. it s about a library in java to run linux command. for instance if you got a command like: cat test.txt | grep «Tuesday» | sed «s/kilogram/kg/g» | sort in this program will become: Unix4j.cat(«test.txt»).grep(«Tuesday»).sed(«s/kilogram/kg/g»).sort();

You can call run-time commands from java for both Windows and Linux.

import java.io.*; public class Test < public static void main(String[] args) < try < Process process = Runtime.getRuntime().exec("pwd"); // for Linux //Process process = Runtime.getRuntime().exec("cmd /c dir"); //for Windows process.waitFor(); BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); String line; while ((line=reader.readLine())!=null) < System.out.println(line); >> catch(Exception e) < System.out.println(e); >finally < process.destroy(); >> > 
Runtime run = Runtime.getRuntime(); //The best possible I found is to construct a command which you want to execute //as a string and use that in exec. If the batch file takes command line arguments //the command can be constructed a array of strings and pass the array as input to //the exec method. The command can also be passed externally as input to the method. Process p = null; String cmd = "ls"; try < p = run.exec(cmd); p.getErrorStream(); p.waitFor(); >catch (IOException e) < e.printStackTrace(); System.out.println("ERROR.RUNNING.CMD"); >finally

The suggested solutions could be optimized using commons.io, handling the error stream, and using Exceptions. I would suggest to wrap like this for use in Java 8 or later:

public static List execute(final String command) throws ExecutionFailedException, InterruptedException, IOException < try < return execute(command, 0, null, false); >catch (ExecutionTimeoutException e) < return null; >/* Impossible case! */ > public static List execute(final String command, final long timeout, final TimeUnit timeUnit) throws ExecutionFailedException, ExecutionTimeoutException, InterruptedException, IOException < return execute(command, 0, null, true); >public static List execute(final String command, final long timeout, final TimeUnit timeUnit, boolean destroyOnTimeout) throws ExecutionFailedException, ExecutionTimeoutException, InterruptedException, IOException < Process process = new ProcessBuilder().command("bash", "-c", command).start(); if(timeUnit != null) < if(process.waitFor(timeout, timeUnit)) < if(process.exitValue() == 0) < return IOUtils.readLines(process.getInputStream(), StandardCharsets.UTF_8); >else < throw new ExecutionFailedException("Execution failed: " + command, process.exitValue(), IOUtils.readLines(process.getInputStream(), StandardCharsets.UTF_8)); >> else < if(destroyOnTimeout) process.destroy(); throw new ExecutionTimeoutException("Execution timed out: " + command); >> else < if(process.waitFor() == 0) < return IOUtils.readLines(process.getInputStream(), StandardCharsets.UTF_8); >else < throw new ExecutionFailedException("Execution failed: " + command, process.exitValue(), IOUtils.readLines(process.getInputStream(), StandardCharsets.UTF_8)); >> > public static class ExecutionFailedException extends Exception < private static final long serialVersionUID = 1951044996696304510L; private final int exitCode; private final ListerrorOutput; public ExecutionFailedException(final String message, final int exitCode, final List errorOutput) < super(message); this.exitCode = exitCode; this.errorOutput = errorOutput; >public int getExitCode() < return this.exitCode; >public List getErrorOutput() < return this.errorOutput; >> public static class ExecutionTimeoutException extends Exception < private static final long serialVersionUID = 4428595769718054862L; public ExecutionTimeoutException(final String message) < super(message); >> 

Источник

Читайте также:  Best linux all in one desktop

how to run a command at terminal from java program?

Update: As suggested by xav, it is advisable to use ProcessBuilder instead:

String[] args = new String[] ; Process proc = new ProcessBuilder(args).start(); 

Usage of Runtime.exec() is now discouraged: use shall use ProcessBuilder instead (docs.oracle.com/javase/7/docs/api/java/lang/…)

I vote for Karthik T’s answer. you don’t need to open a terminal to run commands.

// file: RunShellCommandFromJava.java import java.io.BufferedReader; import java.io.InputStreamReader; public class RunShellCommandFromJava < public static void main(String[] args) < String command = "ping -c 3 www.google.com"; Process proc = Runtime.getRuntime().exec(command); // Read the output BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream())); String line = ""; while((line = reader.readLine()) != null) < System.out.print(line + "\n"); >proc.waitFor(); > > 
$ javac RunShellCommandFromJava.java $ java RunShellCommandFromJava PING http://google.com (123.125.81.12): 56 data bytes 64 bytes from 123.125.81.12: icmp_seq=0 ttl=59 time=108.771 ms 64 bytes from 123.125.81.12: icmp_seq=1 ttl=59 time=119.601 ms 64 bytes from 123.125.81.12: icmp_seq=2 ttl=59 time=11.004 ms --- http://google.com ping statistics --- 3 packets transmitted, 3 packets received, 0.0% packet loss round-trip min/avg/max/stddev = 11.004/79.792/119.601/48.841 ms 

Источник

Оцените статью
Adblock
detector