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).
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); >>
How to run linux commands in java?
To run Linux commands in a Java program, there are several methods available. Each method has its own advantages and disadvantages, depending on the specific requirements of the task at hand. In this article, we will discuss the most commonly used methods for running Linux commands in Java. The methods listed here are intended for developers who have some experience with Java and Linux, and are looking for ways to automate tasks or interact with the operating system from within their Java programs.
Method 1: Using Java ProcessBuilder Class
To run Linux commands in Java using the ProcessBuilder class, follow these steps:
- Create a ProcessBuilder object and set the command to be executed as argument to its constructor.
ProcessBuilder processBuilder = new ProcessBuilder("ls", "-l");
- Redirect the standard output and error streams of the command to the Java process by calling the inheritIO() method of the ProcessBuilder object.
Process process = processBuilder.start();
int exitCode = process.waitFor();
Here is an example code that lists the files in the current directory using the ls command:
import java.io.IOException; public class LinuxCommandRunner public static void main(String[] args) throws IOException, InterruptedException ProcessBuilder processBuilder = new ProcessBuilder("ls", "-l"); processBuilder.inheritIO(); Process process = processBuilder.start(); int exitCode = process.waitFor(); System.out.println("Exited with error code " + exitCode); > >
You can also pass arguments to the command using the ProcessBuilder object. Here is an example code that creates a new directory using the mkdir command:
import java.io.IOException; public class LinuxCommandRunner public static void main(String[] args) throws IOException, InterruptedException ProcessBuilder processBuilder = new ProcessBuilder("mkdir", "newDirectory"); processBuilder.inheritIO(); Process process = processBuilder.start(); int exitCode = process.waitFor(); System.out.println("Exited with error code " + exitCode); > >
In this example, the mkdir command is executed with the argument newDirectory , which creates a new directory with that name.
Using the ProcessBuilder class, you can run any Linux command in your Java program and get the output and error streams of the command as if it was executed in the Linux terminal.
Method 2: Using Runtime.getRuntime().exec() Method
To run Linux commands in Java using the Runtime.getRuntime().exec() method, follow these steps:
- Create a Process object by calling the exec() method of the Runtime class, passing the command you want to execute as a string parameter.
Process process = Runtime.getRuntime().exec("ls -la");
- Use the getInputStream() method of the Process object to get the output of the command as an input stream.
InputStream inputStream = process.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
- Use the readLine() method of the BufferedReader object to read the output of the command line by line.
String line; while ((line = reader.readLine()) != null)
int exitCode = process.waitFor();
Here’s an example that lists the files in the current directory:
import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; public class LinuxCommandRunner public static void main(String[] args) throws Exception Process process = Runtime.getRuntime().exec("ls -la"); InputStream inputStream = process.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); String line; while ((line = reader.readLine()) != null) System.out.println(line); > int exitCode = process.waitFor(); System.out.println("Exited with error code " + exitCode); > >
This code will execute the ls -la command and print the output to the console. You can replace this command with any other Linux command you want to run.
Method 3: Using JSch Library
To run Linux commands in Java, we can use the JSch library. Here’s a step-by-step guide on how to do it:
- First, we need to add the JSch library to our project. We can do this by adding the following dependency to our pom.xml file:
dependency> groupId>com.jcraftgroupId> artifactId>jschartifactId> version>0.1.55version> dependency>
- Next, we need to create a session with the remote Linux server. We can do this by calling the getSession method on the JSch instance and passing in the username, hostname, and port number:
Session session = jsch.getSession("username", "hostname", 22);
session.setPassword("password");
Channel channel = session.openChannel("shell"); channel.connect();
- We can then send commands to the remote server by writing to the output stream of the Channel :
OutputStream outputStream = channel.getOutputStream(); outputStream.write("ls -l\n".getBytes()); outputStream.flush();
- To read the output of the command, we can create a BufferedReader and read from the input stream of the Channel :
InputStream inputStream = channel.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); String line; while ((line = reader.readLine()) != null) System.out.println(line); >
channel.disconnect(); session.disconnect();
JSch jsch = new JSch(); Session session = jsch.getSession("username", "hostname", 22); session.setPassword("password"); session.connect(); Channel channel = session.openChannel("shell"); channel.connect(); OutputStream outputStream = channel.getOutputStream(); outputStream.write("ls -l\n".getBytes()); outputStream.flush(); InputStream inputStream = channel.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); String line; while ((line = reader.readLine()) != null) System.out.println(line); > channel.disconnect(); session.disconnect();
Running Bash commands in Java
See also When Runtime.exec() won’t for many good tips on creating and handling a process correctly. Then ignore it refers to exec and use a ProcessBuilder to create the process.
Hello. I tried to use your class to execute Bash- Commands in my Java application, but when I run the command «cat» it returns null.
8 Answers 8
You start a new process with Runtime.exec(command) . Each process has a working directory. This is normally the directory in which the parent process was started, but you can change the directory in which your process is started.
ProcessBuilder pb = new ProcessBuilder("ls"); pb.inheritIO(); pb.directory(new File("bin")); pb.start();
If you want to run multiple commands in a shell it would be better to create a temporary shell script and run this.
public void executeCommands() throws IOException < File tempScript = createTempScript(); try < ProcessBuilder pb = new ProcessBuilder("bash", tempScript.toString()); pb.inheritIO(); Process process = pb.start(); process.waitFor(); >finally < tempScript.delete(); >> public File createTempScript() throws IOException < File tempScript = File.createTempFile("script", null); Writer streamWriter = new OutputStreamWriter(new FileOutputStream( tempScript)); PrintWriter printWriter = new PrintWriter(streamWriter); printWriter.println("#!/bin/bash"); printWriter.println("cd bin"); printWriter.println("ls"); printWriter.close(); return tempScript; >
Of course you can also use any other script on your system. Generating a script at runtime makes sometimes sense, e.g. if the commands that are executed have to change. But you should first try to create one script that you can call with arguments instead of generating it dynamically at runtime.
It might also be reasonable to use a template engine like velocity if the script generation is complex.
You should also consider to hide the complexity of the process builder behind a simple interface.
Separate what you need (the interface) from how it is done (the implementation).
public interface FileUtils
You can then provide implementations that use the process builder or maybe native methods to do the job and you can provide different implementations for different environments like linux or windows.
Finally such an interface is also easier to mock in unit tests.