Issue while executing hadoop command from java.lang.Process.
hadoop fs -rm -R -skipTrash pathToFolder
this command directly executed on unixbox is working but when I try to execute it from Process it says '-rm -R' unknown command.
public class Test1 {
public static void main(String[] args) throws IOException {
String[] commandToDelete = new String[]{"hadoop", "fs","-rm -R", "-skipTrash", "hdfs://pathToFolder"};
Process process = Runtime.getRuntime().exec(commandToDelete);
try {
process.waitFor();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(process.exitValue());
BufferedReader errorReader = new BufferedReader(
new InputStreamReader(process.getErrorStream()));
String line = null;
while ((line = errorReader.readLine()) != null) {
System.out.println(line);
}
errorReader.close();
}
}
From same location I am able to delete file but not folder any suggestions please.
From exec(String[] cmdarray)
Executes the specified command and arguments in a separate process.
This is a convenience method. An invocation of the form exec(cmdarray) behaves in exactly the same way as the invocation exec(cmdarray, null, null).
So you below command is run in separate process thats why -rm -R is unknown command:
String[] commandToDelete = new String[]{"hadoop", "fs","-rm -R", "-skipTrash", "hdfs://pathToFolder"};
Run like below:
String command = "hadoop fs -rm -R -skipTrash hdfs://pathToFolder"
Process process = Runtime.getRuntime().exec(command);
A more robust solution (that prevents your subsequent problem with space in the path) is to stay with the String[] form but split the arguments correctly:
String[] commandToDelete = new String[]{"hadoop", "fs", "-rm", "-R", "-skipTrash", "hdfs://pathToFolder"};
Related
I'd like to know whether a certain application is in focus in Linux. Say it is Google Chrome. To do so, I wrote a bash on-liner which does it correctly.
xdotool search --name --class 'google-chrome' | grep $(xdotool getactivewindow)
When this command is run in terminal, it will print the id of the terminal itself. To avoid that, run the following command and select Chrome in the three seconds time span.
sleep 3; xdotool search --name --class 'google-chrome' | grep $(xdotool getactivewindow)
The problem is that when I run the above-mentioned one-liner from Java, it seems to always print nothing. Here's my code:
String cmd = "xdotool search --name --class 'google-chrome' | grep $(xdotool getactivewindow)";
Process p = Runtime.getRuntime().exec(cmd);
String result = getCommandResult(p.getInputStream());
private static String getCommandResult(InputStream stream) throws IOException {
StringBuilder sb = new StringBuilder();
try (InputStreamReader isr = new InputStreamReader(stream);
BufferedReader in = new BufferedReader(isr)) {
String line;
while ((line = in.readLine()) != null) {
sb.append(line);
}
}
return sb.toString().trim();
}
I'm open to different solutions to resolving this problem.
As barti_ddu said, this is not working because of the pipe in the command. You can workaround this by creating one sh process with your command passed as the argument:
String cmd = "xdotool search --name --class 'google-chrome' | grep $(xdotool getactivewindow)";
Process p = new ProcessBuilder("sh", "-c", cmd).start();
String result = getCommandResult(p.getInputStream());
If You are using pipe redirection, then You either have to invoke the shell, or redirect the output from one program to another yourself.
However, IMHO, You do not need grep at all, just:
Enumerate windows of certain class.
Get the active window id and check if the active window list contains it.
Example (q&d, resource/error handling omitted):
private static List<String> exec(String... args) throws IOException {
List<String> result = new ArrayList<>();
String line;
BufferedReader reader = new BufferedReader(
new InputStreamReader(
new ProcessBuilder()
.command(args)
.start()
.getInputStream()));
while ((line = reader.readLine()) != null) {
result.add(line);
}
return result;
}
public static void main(String[] args) {
try {
Thread.sleep(3000);
String windowId = exec("xdotool", "getactivewindow").get(0);
System.out.println(windowId);
List<String> windowList = exec("xdotool", "search", "--name", "--class", "google-chrome");
System.out.println(windowList.contains(windowId));
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
Why are you hard coding the command into your class? Rather put your command in a shell script and call that instead. Then you have the flexibility to change the command without having to re-compile.
Process proc = Runtime.getRuntime().exec("./opt/scripts/myscript.sh");
... depending on your application, it would potentially be even better to pass in the shell script as parameter.
private void runCommandLine(String script) {
try {
Process proc = Runtime.getRuntime().exec(script);
proc.waitFor();
int character;
while((character = proc.getInputStream().read()) != -1) {
System.out.write(character);
}
while((character = proc.getErrorStream().read()) != -1) {
System.err.write(character);
}
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
EDIT:
If you goal is to figure out what window is currently in focus, then instead of trying to execute something via the command line, you could just use the JNA (Java Native Access) libraries to potentially do this.
Find out what application (window) is in focus in Java
Java Native Access (Github)
I'm trying to run some commands on a remote machine and capture the result using Java. I have a shell script called test.sh which has following commands:
sshpass -p 'password' ssh root#host.com echo hostname
I'm running it using below java code:
public void runCommand() throws IOException, InterruptedException {
ProcessBuilder builder = new ProcessBuilder();
boolean isWindows = System.getProperty("os.name").toLowerCase().startsWith("windows");
if (isWindows) {
builder.command("cmd.exe", "/c", "dir");
} else {
builder.command("sh", "-c", "sh test.sh");
}
builder.directory(new File(System.getProperty("user.home")));
Process process;
BufferedReader reader = null;
try {
process = builder.start();
reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
StringBuilder stringBuilder = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
stringBuilder.append(line);
}
String output = stringBuilder.toString();
System.out.println(output);
} finally
{
if (reader != null)
try {
reader.close();
} catch (IOException e) {
}
}
}
The command executes but I'm not getting anything in the output. If I use simple commands like echo, hostname then I'm able to get the result in output. I know of JSch which can solve the problem, but I can't use it.
When starting a Process in Java, you must consume both stdout and stderr to avoid blocking, and you should log or control both (avoid consume-to-discard). There are now easier solutions than what the linked article mentions, using ProcessBuilder.
In this instance you completely ignore error output from your command. You said your process exits with status code 127, so it probably prints on stderr so you will obtain more details about the error by using ProcessBuilder.redirectErrorStream(true).
Probably sshpass not installed, or installed but not in $PATH for your java process.
I am developing a Java application which will execute a console command. What the command actually does is, it will make changes to a file, then will save a copy of it with a different name to a different folder (both of the file and the output folder is specified by the user). And it requires some binary program to do this, which is a local resource of my application.
So my code is something like:
...
public void actionPerformed(ActionEvent e) {
File selectedFile = jFileChooser1.getSelectedFile();
File pathAssigned = jFileChooser2.getSelectedFile();
String file = selectedFile.getAbsolutePath();
String output = pathAssigned.getAbsolutePath();
String name = selectedFile.getName();
// What's next???
}
And the usage/syntax of the command is something like:
"command -options /package/binary.bin "+file+" "+output+"\\"+name+"-changed"
So my question would now be; What will be my next code? Should I use a Runtime? If so, then how?
And about including a local resource path to a command, does my syntax is correct?
I am still a newbie here as well as in Java programming so please be kind to your answers/comments. Thanks!
PS. The command is a platform independent by the way.
I hope the code below can help you. First you have a shell script that takes parameters.
#!/bin/bash
echo "hola"
echo "First arg: $1"
echo "Second arg: $2"
You save it in e.g. /home/dac/proj/javatest2016/src/main/java/myshellScript.sh and then you can pass the parameters from your Java code.
import java.io.*;
public class Main {
public static void main(String[] args) throws Exception {
try {
ProcessBuilder pb = new ProcessBuilder("/home/dac/proj/javatest2016/src/main/java/myshellScript.sh", "myArg1", "myArg2");
pb.directory(new File("/home/dac/proj/javatest2016/src/main/java"));
Process p = pb.start();
StringBuffer output = new StringBuffer();
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
while ((line = reader.readLine())!= null) {
output.append(line + "\n");
}
System.out.println("### " + output);
} catch (Throwable t) {
t.printStackTrace();
}
}
}
Test
### hola
First arg: myArg1
Second arg: myArg2
I tried to use java to run some bash script and store the terminal output in a string. However, there are a lot of commands don't work in this way. It keeps showing command not found, but I can run those commands correctly in terminal, ex node --version, go --version. I guess is the path issue, but have no idea how to fix it.
Another question, when I run "python --version", it shows "Python 2.7.10" but it is in getErrorStream. Can anyone give me some hint?
public static void runscript() throws IOException {
Runtime rt = Runtime.getRuntime();
String[] commands = { "/bin/bash", "-c", "node --version" };
Process proc = null;
try {
proc = rt.exec(commands);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream()));
BufferedReader stdError = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
// read the output from the command
System.out.println("Here is the standard output of the command:\n");
String s = null;
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);
}
}
Reply #VishalKamat comment.
when I tried using the output of "which node" as my path, which is "/usr/local/bin/node". It works!!!
But, does that mean I have to change the path when I need to get different application version info?
I thought I can easily get the info just like I do in terminal.
I try to print $PATH by java in this way
String[] commands = { "/bin/bash","-c", "$PATH" };
The error msg is :
/bin/bash: /usr/bin:/bin:/usr/sbin:/sbin: No such file or directory
I am trying to execute another file using Runtime and Process
try
{
Runtime run = Runtime.getRuntime();
Process pro = run.exec("C:\\Users\\user\\Desktop\\file.exe");
}
catch(Exception a)
{
a.printStackTrace();
}
I can enter this command in either run or cmd and am able to open the file but running it through my program it won't open. There are no errors, it just doesn't open.
To better understand what is going on (and it is actually a requirement of the Process class), you need to redirect the input and error streams of your process - and using a ProcessBuilder is the recommended way to start processes:
public static void main(String[] args) throws Exception {
ProcessBuilder pb = new ProcessBuilder("C:\\Users\\user\\Desktop\\file.exe");
runProcess(pb)
}
private static void runProcess(ProcessBuilder pb) throws IOException {
pb.redirectErrorStream(true);
Process p = pb.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}
You must do
Process pro = run.exec("C:\\Users\\user\\Desktop\\file.exe",null,"C:\\Users\\user\\Desktop\\");
Please see Run .exe file from Java from file location
Try this way:
String []cmdarray = new String[4];
cmdarray[0] = "cmd";
cmdarray[1] = "/c";
cmdarray[2] = "start";
cmdarray[3] = "C:\\Users\\user\\Desktop\\file.exe";
Runtime.getRuntime().exec(cmdarray);
Try this one, create a batch file ,like start_file.bat.
The content like this:
cd C:\Users\user\Desktop ----- Goto this directory
C: ----- This line is very important
file.exe
Both the two approaches work well.
Runtime r = Runtime.getRuntime();
String []cmdarray = new String[4];
cmdarray[0] = "cmd";
cmdarray[1] = "/c";
cmdarray[2] = "start";
cmdarray[3] = "C:/users/desktop/start_file.bat";
r.exec(cmdarray);
And this one:
r.exec("C:/users/desktop/start_file.bat");
You can read the output from this new process.