How to run Linux commands in Java? - 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.

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
as expected.
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.

You can also write a shell script file and invoke that file from the java code. as shown below
{
Process proc = Runtime.getRuntime().exec("./your_script.sh");
proc.waitFor();
}
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) {
System.out.println(s);
}

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();
}
}
}
Hope it Helps.. :)

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{
p.destroy();
}

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<String> 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<String> execute(final String command, final long timeout, final TimeUnit timeUnit) throws ExecutionFailedException, ExecutionTimeoutException, InterruptedException, IOException {
return execute(command, 0, null, true);
}
public static List<String> 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 List<String> errorOutput;
public ExecutionFailedException(final String message, final int exitCode, final List<String> errorOutput) {
super(message);
this.exitCode = exitCode;
this.errorOutput = errorOutput;
}
public int getExitCode() {
return this.exitCode;
}
public List<String> getErrorOutput() {
return this.errorOutput;
}
}
public static class ExecutionTimeoutException extends Exception {
private static final long serialVersionUID = 4428595769718054862L;
public ExecutionTimeoutException(final String message) {
super(message);
}
}

if the opening in windows
try {
//chm file address
String chmFile = System.getProperty("user.dir") + "/chm/sample.chm";
Desktop.getDesktop().open(new File(chmFile));
} catch (IOException ex) {
Logger.getLogger(Frame.class.getName()).log(Level.SEVERE, null, ex);
{
JOptionPane.showMessageDialog(null, "Terjadi Kesalahan", "Error", JOptionPane.WARNING_MESSAGE);
}
}

ProcessBuilder processBuilder = new ProcessBuilder();
// -- Linux --
// Run a shell command
processBuilder.command("bash", "-c", "ls /home/kk/");
// Run a shell script
//processBuilder.command("path/to/hello.sh");
// -- Windows --
// Run a command
//processBuilder.command("cmd.exe", "/c", "dir C:\\Users\\kk");
// Run a bat file
//processBuilder.command("C:\\Users\\kk\\hello.bat");
try {
Process process = processBuilder.start();
StringBuilder output = new StringBuilder();
BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
output.append(line + "\n");
}
int exitVal = process.waitFor();
if (exitVal == 0) {
System.out.println("Success!");
System.out.println(output);
System.exit(0);
} else {
//abnormal...
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}

Related

Run a shell file in java

In Java you can call a shell file like this:
public class Shell {
private static Shell rootShell = null;
private final Process proc;
private final OutputStreamWriter writer;
private Shell(String cmd) throws IOException {
this.proc = new ProcessBuilder(cmd).redirectErrorStream(true).start();
this.writer = new OutputStreamWriter(this.proc.getOutputStream(), "UTF-8");
}
public void cmd(String command) {
try {
writer.write(command+'\n');
writer.flush();
} catch (IOException e) { }
}
public void close() {
try {
if (writer != null) {
writer.close();
if(proc != null) {
proc.destroy();
}
}
} catch (IOException ignore) {}
}
public static void exec(String command) {
Shell.get().cmd(command);
}
public static Shell get() {
if (Shell.rootShell == null) {
while (Shell.rootShell == null) {
try {
Shell.rootShell = new Shell("su"); //Open with Root Privileges
} catch (IOException e) { }
}
}
return Shell.rootShell;
}
}
Shell.exec("echo " + bt.getLevel() + " > "+ flashfile);
right.
but I have a shell which giving an argument after executing it.
how can I pass that argument? I don't want user type anything to run this shell file. in another word, I want to fully automate a shell file.
If you want to automate a shell file with a Java programme, this can be done. You could even pipe a series of commands to this programme saved in a file and executing these as a batch.
You can execute commands batches of commands from like this:
java -cp experiments-1.0-SNAPSHOT.jar ConsoleReader < commands.txt
commands.txt is a file with a series of commands:
cmd /k date
cmd /k dir
netstat
ipconfig
Or you can with the same programme allow the user to execute commands on the command line.
Below you can find a sample programme which you can compile and be run in the above described manner.
What does it do?
It hooks a java.util.Scanner to the console input and consumes each line.
Then it spawns two threads which listen to the error and input streams and write out either to stderr or stdin.
Empty lines on the console are ignored
If you type "read " it will execute the commands on that file.
Source:
public class ConsoleReader {
public static void main(String[] args) throws IOException, DatatypeConfigurationException {
try(Scanner scanner = new Scanner(new BufferedInputStream(System.in), "UTF-8")) {
readFromScanner(scanner);
}
}
private static final Pattern FILE_INPUT_PAT = Pattern.compile("read\\s*([^\\s]+)");
private static void readFromScanner(Scanner scanner) {
while (scanner.hasNextLine()) {
try {
String command = scanner.nextLine();
if(command != null && !command.trim().isEmpty()) {
command = command.trim();
if("exit".equals(command)) {
break; // exit shell
}
else if(command.startsWith("read")) { // read from file whilst in the shell.
readFile(command);
}
else {
Process p = Runtime.getRuntime().exec(command);
Thread stdout = readFromStream(p.getInputStream(), System.out, "in");
Thread stderr = readFromStream(p.getErrorStream(), System.err, "err");
stdout.join(200);
stderr.join(200);
}
}
}
catch(Exception e) {
Logger.getLogger("ConsoleReader").log(Level.SEVERE, String.format("Failed to execute command %s", e));
}
}
}
private static void readFile(String command) throws FileNotFoundException {
Matcher m = FILE_INPUT_PAT.matcher(command);
if(m.matches()) {
String file = m.group(1);
File f = new File(file);
if (f.exists()) {
try (Scanner subScanner = new Scanner(f)) {
readFromScanner(subScanner);
}
}
}
else {
System.err.printf("Oops, could not find '%s'%n", command);
}
}
private static Thread readFromStream(InputStream stdin, PrintStream out, String name) throws IOException {
Thread thread = new Thread(() -> {
try (BufferedReader in = new BufferedReader(new InputStreamReader(stdin))) {
String line;
while ((line = in.readLine()) != null) {
out.println(line);
}
} catch (IOException e) {
Logger.getLogger("ConsoleReader").log(Level.SEVERE, "Failed to read from stream.", e);
}
}, name);
thread.setDaemon(true);
thread.start();
return thread;
}
}
Runtime.getRuntime().exec("src/[FILE LOCATION]");
I think this is the command you're looking for. Let me know if it works!

Detecting terminal command errors in Java

In my Java application I am using the exec() command to call a terminal function:
p = Runtime.getRuntime().exec(command);
p.waitFor();
The call uses the zip and unzip calls. Originally I call:
zip -P password -r encrypted.zip folderIWantToZip
When I call the unzip function through java, I specify the password as the method parameter. If the correct password is specified then the call should unzip the encrypted folder:
unzip -P password encrypted.zip
I want a way to find out if the password entered is incorrect. For example, if password is correct, then the call will correctly unzip the zip file. But I notice that no exception is thrown for an incorrect password. How can I determine this?
You could read the process's ErrorStream and InputStream to determine the process output. Sample code given below
public static void main(String[] args) {
try {
String command = "zip -P password -r encrypted.zip folderIWantToZip";
Process p = Runtime.getRuntime().exec(command);
InputStream is = p.getInputStream();
int waitFor = p.waitFor();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
String line;
while ((line = reader.readLine()) != null) {
System.out.println("line:" + line);
}
is = p.getErrorStream();
reader = new BufferedReader(new InputStreamReader(is));
while ((line = reader.readLine()) != null) {
System.out.println("ErrorStream:line: " + line);
}
System.out.println("waitFor:" + waitFor);
System.out.println("exitValue:" + p.exitValue());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
You could use the exitcode to validate the process status as well but it is specific to to program. Normally zero means successfully terminated otherwise abnormal termination.
As per my comment, first thing I would do would be to capture the Process's InputStream and ErrorStream via getInputStream() and getErrorStream(), but especially the latter, the ErrorStream, and check to see what it outputs if the input is in error. Note that these would have to be done in their own thread, else you'll tie up your program. I usually use some type of StreamGobbler class for this. Also, don't ignore the int returned by p.waitFor().
e.g.,
ProcessBuilder pBuilder = new ProcessBuilder(COMMAND);
Process process = null;
try {
process = pBuilder.start();
new Thread(new StreamGobbler("Input", process.getInputStream())).start();
new Thread(new StreamGobbler("Error", process.getErrorStream())).start();
int exitValue = process.waitFor();
System.out.println("Exit Value: " + exitValue);
process.destroy();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if (process != null) {
process.destroy();
}
}
And:
class StreamGobbler implements Runnable {
private String name;
private Scanner scanner;
public StreamGobbler(String name, InputStream inputStream) {
this.name = name;
scanner = new Scanner(inputStream);
}
#Override
public void run() {
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
System.out.println(name + ": " + line); // or better, log the line
}
scanner.close();
}
}

Runtime Process BufferedReader not outputting all lines (Psexec)

I am trying to read the output of Psexec into Java using a BufferedReader on a Process InputStream for use on a network however it is only outputting the first line.
Runtime rt = Runtime.getRuntime();
try {
Process p = rt.exec("C:\\Users\\*****\\Desktop\\PS\\Psexec \\\\" + "******" + " -u ****** -p ****** cmd /c dir D:\\");
BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
log.add("Computer: " + address);
String s = null;
while ((s = stdInput.readLine()) != null) {
log.add(s);
}
} catch (IOException e) {
e.printStackTrace();
}
What would be the reason for this happening and how would this be fixed?
The process is probably producing some of its output on stderr. Either read both the output and the error streams, in separate threads, or use the ProcessBuilder to create the Process, and merge the output streams before you do so, with redirectErrorStream().
So, I spent some time playing around with this, using ProcessBuilder.
I tried redirecting the IO through the INHERITED and PIPE options, but could not get it to display the output of the remote command (the psexec content was fine)
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
public class Test1 {
public static void main(String[] args) {
ProcessBuilder pb = new ProcessBuilder(
"C:\\Users\\shane\\Downloads\\PSTools\\PsExec.exe",
"\\\\builder",
"-u",
"xxx",
"-p",
"xxx",
"cmd",
"/c", "dir", "c:\\"
);
try {
Process p = pb.start();
StreamConsumer.consume(p.getErrorStream());
StreamConsumer.consume(p.getInputStream());
System.out.println("Exited with :" + p.waitFor());
} catch (IOException | InterruptedException exp) {
exp.printStackTrace();
}
}
public static class StreamConsumer implements Runnable {
private InputStream is;
public StreamConsumer(InputStream is) {
this.is = is;
}
public static void consume(InputStream is) {
StreamConsumer consumer = new StreamConsumer(is);
new Thread(consumer).start();
}
#Override
public void run() {
try {
int in = -1;
while ((in = is.read()) != -1) {
System.out.print((char)in);
}
} catch (IOException exp) {
exp.printStackTrace();
}
}
}
}
I even tried redirecting the InputStreams to File without any success. It would seem that whatever mechanism psexec is using to stream the results from the remote machine don't seem to be picked up by Java.
You might try PAExec which did work, but didn't seem to wait to exit after the remote command exited...
It could be the case that you started the process and didn't wait for it to finish before checking it's output. If this is the case, your main thread will exit your while loop because it reads null even though the subprocess is still executing. I would suggest using Process.waitFor() so that all of the output ends up in the stream before you begin polling it.

Running a java program from another java program

I am working on a simple java program. It simply compiles and executes another java program. I am using Runtime.exec() function to compile and run. There is no problem with compilation. but when it runs, if the second program needs an input to read from keyboard, I can't give it from the master process. I used getOutputStream() function. but it couldn't help. I will provide my code.
public class sam {
public static void main(String[] args) throws Exception {
try {
Process p = Runtime.getRuntime().exec("javac sam2.java");
Process p2 = Runtime.getRuntime().exec("java sam2");
BufferedReader in = new BufferedReader(
new InputStreamReader(p2.getInputStream()));
OutputStream out = p.getOutputStream();
String line = null;
line = in.readLine();
System.out.println(line);
input=input+"\n";
out.write(input.getBytes());
p.wait(10000);
out.flush();
}catch (IOException e) {
e.printStackTrace();
}
}
}
This is my master program(sam.java).
The following is the code of sam2.java
public class sam2 {
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str;
System.out.println("Enter the number..\n");
str = br.readLine();
System.out.println(Integer.parseInt(str));
}
}
There is no problem, if my second program has only printing statements. But the problem arises when I have to read something from the other.
It is a bit strange but you can run the second program without forking it. Just calling the main method in it. So forget the runtime section and do this:
sam2.main(new String[0]);
Of course this way you must compile sam2 at compile time
Each process needs to be allowed to run and finish. You can use Process#waitFor for this purpose. Equally, you need to consume any output from the process at the same time. waitFor will block so you will need use a Thread to read the input (and if you need to, write output to the process)
Depending on the location of the java/class file, you may also need to specify a starting folder from which the execution of the process can start.
Most of this significantly easier using ProcessBuilder
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
public class CompileAndRun {
public static void main(String[] args) {
new CompileAndRun();
}
public CompileAndRun() {
try {
int result = compile("compileandrun/HelloWorld.java");
System.out.println("javac returned " + result);
result = run("compileandrun.HelloWorld");
} catch (IOException | InterruptedException ex) {
ex.printStackTrace();
}
}
public int run(String clazz) throws IOException, InterruptedException {
ProcessBuilder pb = new ProcessBuilder("java", clazz);
pb.redirectError();
pb.directory(new File("src"));
Process p = pb.start();
InputStreamConsumer consumer = new InputStreamConsumer(p.getInputStream());
consumer.start();
int result = p.waitFor();
consumer.join();
System.out.println(consumer.getOutput());
return result;
}
public int compile(String file) throws IOException, InterruptedException {
ProcessBuilder pb = new ProcessBuilder("javac", file);
pb.redirectError();
pb.directory(new File("src"));
Process p = pb.start();
InputStreamConsumer consumer = new InputStreamConsumer(p.getInputStream());
consumer.start();
int result = p.waitFor();
consumer.join();
System.out.println(consumer.getOutput());
return result;
}
public class InputStreamConsumer extends Thread {
private InputStream is;
private IOException exp;
private StringBuilder output;
public InputStreamConsumer(InputStream is) {
this.is = is;
}
#Override
public void run() {
int in = -1;
output = new StringBuilder(64);
try {
while ((in = is.read()) != -1) {
output.append((char) in);
}
} catch (IOException ex) {
ex.printStackTrace();
exp = ex;
}
}
public StringBuilder getOutput() {
return output;
}
public IOException getException() {
return exp;
}
}
}
Now obviously, you should check the return results of the processes, and may be produce a better mechanism for interacting with the processes, but that's the basic idea...
You can just call the main method of the second class. The main method is just like any other static method.
This is what worked for me:
try {
single.main(new String[0]);
} catch (Exception e) {
JOptionPane.showMessageDialog(null, e);
}
Just call the main class file. For example, if your java class file name is xyz.java, you can call and execute the same in java swing application on click of a JButton, code is
private void Btn_createdatabaseActionPerformed(java.awt.event.ActionEvent evt) {
xyz.main(new String[0]);
}
That's it...

StreamGobbler short output or very quick process

I use StreamGobbler to read output from external program. Before I used to read and parse big(20-40 strings) output from stderr of ffmpeg. Now I want to read and parse only one string from stdout(one string is all output of program and this program ends very quickly) of identify(ImageMagick). And sometimes it works, but sometimes I have error "Stream closed". I think that StreamGobbler has no time to work with stream(process ends before streamGobler do some work).
Below you can see class ExecThread and example of it's usage.
Sorry for my English...
String command = ffmpegExe.getAbsolutePath()+ " -i \""+ fileName +"\"";
ExecThread thread = new ExecThread(command);
thread.setPriority(ExecThread.MIN_PRIORITY);
thread.start();
thread.waitFor(DEFAULT_WAIT);
//reading ffmpeg stderr
BufferedReader ffmpegErr = thread.getErrBufferedReader();
String line;
try
{
while((line = ffmpegErr.readLine()) !=null)
//some code
private static class ExecThread extends Thread
{
public ExecThread(String command)
{
this.command = command;
}
#Override
public void run()
{
try
{
ExecCommand(command);
exitVal = process.waitFor();
}
catch (Exception e )
{
logger.error("Error while executing command: " + command + e.getMessage(),e);
System.err.println("Error");
System.exit(1);
}
}
public void waitFor(long millis)
{
try
{
this.join(millis);
process.destroy();
} catch (Exception e)
{
logger.error("Error while interupting command: " + command + e.getMessage(), e);
}
}
private void ExecCommand(String command) throws IOException
{
//run command
Runtime rt = Runtime.getRuntime();
process = rt.exec(new String[]{shellName,shellOption, command}, null, null);
//get stderr buffered reader
StreamGobbler errGobbler = new StreamGobbler(process.getErrorStream());
StreamGobbler outGobbler = new StreamGobbler(process.getInputStream());
ErrBufferedReader = new BufferedReader(new InputStreamReader(errGobbler));
OutBufferedReader = new BufferedReader(new InputStreamReader(outGobbler));
}
private BufferedReader ErrBufferedReader;
public BufferedReader getOutBufferedReader()
{
return OutBufferedReader;
}
private BufferedReader OutBufferedReader;
private Process process;
private String command;
private int exitVal=-1;
public BufferedReader getErrBufferedReader()
{
return ErrBufferedReader;
}
public Process getProcess()
{
return process;
}
public String getCommand()
{
return command;
}
public int getExitVal()
{
return exitVal;
}
}
I'd recommend two changes:
Use the Java Process instead of writing a Thread.
Close your input, output, and error streams and destroy the Process. You'll have file handle leaks if you don't.
This is not good decision but it works. Before it was String command = identifyExe.getAbsolutePath() + " \"" + file.getAbsolutePath() + "\"";
now it String command = "sleep 1 ; " + identifyExe.getAbsolutePath() + " \"" + file.getAbsolutePath() + "\"";
Sleep is very usefull function :-)
But, if you know better decision please tell...

Categories