I have been trying to get the following code to work.
package com.compressor;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
public class JSCompressor {
public static void main(String[] args) {
try {
String currentDir = System.getProperty("user.dir");
String[] commands = { "java", "-jar","yuicompressor.jar"};
ProcessBuilder pb = new ProcessBuilder(commands);
pb.directory(new File(currentDir));
Process p = pb.start();
BufferedReader output = new BufferedReader(new InputStreamReader(p.getInputStream()));
System.out.println("Result : " + output.readLine());
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
My project directory looks like what is shown in the image below :
But still when I run the program inside eclipse it gives me null output like given below :
Result : null
I have tried googling several options without any success. Could anyone please point out what I am doing wrong here ?.
I the jar I am testing is indeed runnable and gives an output when run normally in the command line. But I need to be able to run this jar programetically. Could anyone please help ?.
I think you want to change
String[] commands = { "java", "-jar","yuicompressor.jar"};
to
String[] commands = { "java", "-jar", jarPath};
Since that's the path to your yuicompressor.jar. Also, you should use another thread to read the process output - and wait for the process to complete.
final Process p = pb.start();
// then start a thread to read the output.
new Thread(new Runnable() {
public void run() {
BufferedReader output = new BufferedReader(
new InputStreamReader(p.getInputStream()));
String line;
System.out.print("Result : ");
while ((line = output.readLine()) != null) {
System.out.println(line);
}
}
}).start();
p.waitFor();
Related
I am using Java to call powershell script. The powershell script is built with function and the function will write values to console. I need to capture those values in java.
my poweshell script is as below
$TokenCSV="M:\work\Powershell\TokenExtractedFromDB_Spec.csv"
$TokenXlPath="M:\work\Powershell\TokenListconverted.xlsx"
$Switch="Token"
Write-Host "Inside ConvertCSVtoEXL2 calling fuc :"
$x=ConverToExlFile $TokenCSV $TokenXlPath $Switch
###Function
function ConverToExlFile
{
Param ([string]$TokenCSV,
[string]$TokenXlPath,
[string]$Switch)
Write-Output "Inside ConverToExlFile Function :"| Out-Null
for($row = 2;$row -lt 10;$row++)
{
Write-Output "Inside for loop :$row"| Out-Null
}
return
}
while calling above code through java i m not getting values in while loop as given below. it just finishes once powershell script executes.
Process proc = runtime.exec("cmd.exe /c powershell.exe M:\\work\\Powershell\\V2\\ConvertCSVtoEXL2.ps1");
System.out.println("2...");
InputStream is = proc.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader reader = new BufferedReader(isr);
String line;
System.out.println("3");
while ((line = reader.readLine()) != null)
{
System.out.println(line);
//System.out.println(reader.readLine());
System.out.println("4");
}
IT would be great if any one can help me with this.
You don't need cmd.exe. You can directly run powershell.exe.
Your PowerShell script is sending output to Out-Null so obviously nothing will be written to standard output.
powershell.exe accepts a -File parameter which you can use to run your script.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class PrcBldTs {
public static void main(String[] args) throws IOException, InterruptedException {
ProcessBuilder pb = new ProcessBuilder("powershell.exe", "-File", "M:\\work\\Powershell\\V2\\ConvertCSVtoEXL2.ps1");
Process p = pb.start();
try (InputStreamReader isr = new InputStreamReader(p.getInputStream());
BufferedReader br = new BufferedReader(isr)) {
String line = br.readLine();
while (line != null) {
System.out.println(line);
line = br.readLine();
}
}
int exitStatus = p.waitFor();
System.out.println("exit status = " + exitStatus);
}
}
Note that you must call method waitFor() so that your java code will wait until the PowerShell script terminates.
Remember that ProcessBuilder does not emulate a Windows command prompt. In the ProcessBuilder constructor you need to split the command that you pass into a list of words.
Of-course, if all you want to do is print the PowerShell script output, you can simply call method redirectIO() of class ProcessBuilder. Then the above code becomes:
import java.io.IOException;
public class PrcBldTs {
public static void main(String[] args) throws IOException, InterruptedException {
ProcessBuilder pb = new ProcessBuilder("powershell.exe", "-File", "M:\\work\\Powershell\\V2\\ConvertCSVtoEXL2.ps1");
pb.inheritIO();
Process p = pb.start();
int exitStatus = p.waitFor();
System.out.println("exit status = " + exitStatus);
}
}
you can use proc.waitFor(); before getting input stream from proc
I'm currently working on a Plugin which also can execute commands in the Linux shell. I've setup some commands that I will need later. Killing screens is already working but now I want to start some screen's through my Plugin. But this isn't working.
I've tried to change from Runtime.getRuntime.exec(cmd); to a ProcessBuilder worked for killing screens.
My method to execute commands
public static void shellExecuteBuilder(String[] command, Player p, boolean bool, String Wrapper) {
ProcessBuilder prb;
try {
prb = new ProcessBuilder(command);
prb.redirectErrorStream(true);
Process pro = prb.start();
BufferedReader r = new BufferedReader(new InputStreamReader(pro.getInputStream()));
String line;
while (prb.redirectErrorStream() == true) {
line = r.readLine();
if (line != null) {
System.out.println(line);
}
}
if (bool == true) {
p.sendMessage("§aDer Wrapper §e" + Wrapper + " §awurde angehalten!");
} else {
p.sendMessage("§aDer Wrapper §e" + Wrapper + " §awurde gestartet!");
}
} catch (IOException e) {
if (bool == true) {
p.sendMessage("§cDer Wrapper §e" + Wrapper + " §ckonnte nicht angehalten werden!");
} else {
p.sendMessage("§cDer Wrapper §e" + Wrapper + " §ckonnte nicht gestartet werden!");
}
e.printStackTrace();
}
}
How I setup this in another method
String[] command = new String[] {"/bin/sh", "-c", "cd /path/to/my/script/", "./start.sh"};
shellExecuteBuilder(command, p, false, Wrapper);
I expected that my method will startup a new screen but it actually does not do anything.
/bin/sh can accept a sequence of commands, but formatted differently than you have it. Try this instead:
String[] command = new String[] {"/bin/sh", "-c", "cd /path/to/my/script/; ./start.sh"};
Also, the way you process the output from the process will never end. The while loop should be testing the returned output from the process, not the redirection setting (which will never change). Here's a modified version that properly reads the output and wait for the subshell to exit. Note that I removed some of your app's variables (bool, Wrapper, Player) to simplify the example:
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.BufferedReader;
public class TestPB {
public static void shellExecuteBuilder(String[] command) {
ProcessBuilder prb;
try {
prb = new ProcessBuilder(command);
prb.redirectErrorStream(true);
Process pro = prb.start();
BufferedReader r = new BufferedReader(new InputStreamReader(pro.getInputStream()));
String line;
while( (line = r.readLine()) != null) {
System.out.println(line);
}
pro.waitFor();
} catch (Exception e) {
e.printStackTrace();
}
}
public static final void main(String[] args) {
TestPB tpb = new TestPB();
String[] command = new String[] {"/bin/sh", "-c", "cd /path/to/my/script/; ./start.sh"};
TestPB.shellExecuteBuilder(command);
}
}
Alternatively, instead of telling the shell to change directory ProcessBuilder can do it, although not with the way you currently have your program 'factored':
ProcessBuilder prb = new ProcessBuilder ("/bin/sh", "-c", "./startsh");
prb.directory("/path/to/my/script");
prb.redirectErrorStream(true);
Process pro = prb.start();
or using 'fluent' style all in one statement:
Process pro = new ProcessBuilder ("/bin/sh", "-c", "./startsh")
.directory("/path/to/my/script").redirectErrorStream(true).start();
I want to communicate with the linux terminal with java code. I want to store the output and work with it. I implemented the code below following the instructions in given link.
I would expect the complete terminal output of help. But neither for the standard commands, nor for the mosquitto commands I get anything from the input stream. Where is the mistake? Or are you supposed to do it completely differnt?
Stackoverflow link: how to run a command at terminal from java program?
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class LinuxInputStream
{
public static void main(String[] args)
{
// Linux Terminal
String prefix = "/bin/bash";
String terminalCommand = "help";
String mosquittoCommand = "mosquitto --help";
ProcessBuilder pb1 = new ProcessBuilder(
new String[] {prefix, terminalCommand});
ProcessBuilder pb2 = new ProcessBuilder(
new String[] {prefix, mosquittoCommand});
try
{
executeCommand(pb1);
}
catch (IOException e)
{
System.out.println("IO Error in Terminal Command execution!");
e.printStackTrace();
}
try
{
executeCommand(pb2);
}
catch (IOException e)
{
System.out.println("IO Error in Mosquitto Command execution!");
e.printStackTrace();
}
}
private static void executeCommand(ProcessBuilder pb) throws IOException
{
Process terminalCommandProcess = pb.start();
InputStream inputStream = terminalCommandProcess.getInputStream();
BufferedReader br = new BufferedReader(
new InputStreamReader(inputStream));
String line;
int i = 0;
while ((line = br.readLine()) != null)
{
System.out.println("Line: " + line);
i++;
}
if (i == 0) System.out.println("Nothing read from input stream");
}
}
Output:
Nothing read from input stream Nothing read from input stream
Just found the solution immidiatly after the post: The "-c" part is missing. Correct code snippet is:
// Linux Terminal
String prefix = "/bin/bash";
String c = "-c";
String terminalCommand = "help";
String mosquittoCommand = "mosquitto --help";
ProcessBuilder pb1 = new ProcessBuilder(
new String[] {prefix, c, terminalCommand});
ProcessBuilder pb2 = new ProcessBuilder(
new String[] {prefix, c, mosquittoCommand});
I have made a cross compiler using gcc. Now I want the compile and run commands to be executed in a terminal through java program. Here is the code that I am using for this :
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class Runterminal {
public static void main(String[] args) {
Process proc;
Process procRun;
String compileCommand = "aarch64-linux-g++ -std=c++14 test.cpp";
String runCommand = "aarch64-linux-objdump -d a.out";
try{
proc = Runtime.getRuntime().exec(compileCommand);
procRun = Runtime.getRuntime().exec(runCommand);
// 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();
BufferedReader readero =
new BufferedReader(new InputStreamReader(procRun.getInputStream()));
String lineo = "";
while((lineo = readero.readLine()) != null) {
System.out.print(lineo + "\n");
}
procRun.waitFor();
}
catch(Exception e)
{
System.out.println("Exception occurred "+e);
}
}
}
Now my first command is executing since I could see the a.out file being generated. The second command should dump the memory contents of file and it should print in in terminal but I am not seeing any output. Can anyone tell where I am going wrong?
Is there a way to get an output from a shell script program into a variable in Java program(not into the output file). The output of my shell script is the database query execution time and I need to assign that time value to a Java variable. (I am calling that shell script from Java program). And then I will need to do some other calculations on those values in Java.
Update to old question
Since Java 7 there is a new class which can easily deal with OS procecces: ProcessBuilder
.Let's assume we need to store the output of ip_conf.bat into a java String. Contents of c:\tmp\ip_conf.bat
#echo off
REM will go to standard output
ipconfig
REM will go to stadnard error
hey there!
You can read the input streams connected to the standard and error outputs of the subprocess:
ProcessBuilder pb = new ProcessBuilder("C:\\tmp\\ip_conf.bat");
Process p = pb.start();
String pOut = "";
try (InputStream stdOut = p.getInputStream();
BufferedInputStream bufferedStdOut = new BufferedInputStream(stdOut);
ByteArrayOutputStream result = new ByteArrayOutputStream()) {
int bytes = 0;
while ((bytes = bufferedStdOut.read()) != -1) {
result.write(bytes);
}
pOut = result.toString(Charset.defaultCharset().toString());
}
System.out.println(pOut);
InputStream stdErr = p.getErrorStream();
// same with the error stream ...
int exit = p.waitFor();
System.out.println("Subprocess exited with " + exit);
Below is the program that will help you store the full output of any script or any command into String object.
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class ExecuteShellComand {
public static void main(String[] args) {
ExecuteShellComand obj = new ExecuteShellComand();
String output = obj.executeCommand("sh /opt/yourScriptLocation/Script.sh");
System.out.println(output);
}
private String executeCommand(String command) {
StringBuffer output = new StringBuffer();
Process p;
try {
p = Runtime.getRuntime().exec(command);
p.waitFor();
BufferedReader reader =
new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
while ((line = reader.readLine())!= null) {
output.append(line + "\n");
}
} catch (Exception e) {
e.printStackTrace();
}
return output.toString();
}
}
I just google it and there is a nice tutorial, full of examples here : http://www.mkyong.com/java/how-to-execute-shell-command-from-java/
I know people prefere copy/paste but let's respect other people's work and go on their website :p