Sending 'exec' commands to Docker container using Java - java

I'm trying to send docker commands using Java Runtime.
Commands like docker cp works very nice with the below method as well as typing directly from the terminal.
First problem is that the docker exec command works only from the terminal, not with the Java Runtime. Other docker commands like docker cp works as expected. The only problem is that I can't run commands on the container, like echoing on the container's terminal.
Also the 2nd problem is that the System.out.println(...)method in the below method, doesn't actually print anything.
private static void runCommand() throws IOException, InterruptedException {
Process proc = Runtime.getRuntime().exec(
new String[]{"/bin/sh",
"-c",
"docker exec -u 0 -it <CONTAINER_NAME> echo", "'abc'"});
BufferedReader reader =
new BufferedReader(new InputStreamReader(proc.getInputStream()));
String line = "";
while ((line = reader.readLine()) != null) {
System.out.print(line + "\n");
}
proc.waitFor();
}

There is no need to run docker inside a shell. You can start the process directly.
As of Java 1.7 you can also use ProcessBuilder.inheritIO() to redirect the standard I/O of the subprocess
Below a working example that prints the output of the echo command:
ProcessBuilder processBuilder = new ProcessBuilder();
processBuilder.command("docker", "exec" , "-it", "<CONTAINER_NAME_OR_ID>", "echo", "abc").inheritIO();
try {
Process process = processBuilder.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
int exitCode = process.waitFor();
System.out.println("\nExited with error code : " + exitCode);
} catch (Exception e) {
e.printStackTrace();
}
Hope this helps.

Related

Run shell script with Angular CLI commands from Java

I'm trying to run a shell script from Java (using Runtime.getRuntime().exec(cmd)). All commands in the script file seem to be running normally except the angular-cli (ng) commands.
My Java File:
System.out.println("Executing Script...");
final String[] cmd = new String[]{"/bin/bash", "test.sh"};
final Process process = Runtime.getRuntime().exec(cmd);
process.waitFor();
final BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String s;
while ((s = reader.readLine()) != null) {
System.out.println("Script output: " + s);
}
process.destroy();
System.out.println("Script Executed.");
test.sh:
#!/bin/bash
cd ~/ &&
ng new newAngularProject &&
Outout:
Executing Script...
Script Executed.
No errors are thrown. All other commands work but for some reason, I'm unable to run ng commands. Also, I've tested the file w/o running it from Java - When I run the same script directly on the console, it works perfectly and all commands (including ng commands) work neatly. I'm running on MacOS in case you wanted to know.
Also print the error stream. You will get the error message, if it is there.
final BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
while ((s = errorReader.readLine()) != null) {
System.out.println("error: " + s);
}
Also you can try to use absolute path of ng in your test.sh e.g. /home/my/install/node-vxxx/ng, since the process spawn by java to run your command might not get the environment variable you set in your .bashrc /.bash_aliases

How to execute cmd line of psexec and log to text file in a single line using JAVA?

I am trying to execute the following line in java(with escaped characters):
"psexec -i -d \\\\computerName -u user -p pass calc 2>
somePath\\psexecOut.txt"
I use the following method to execute cmd lines:
private static String executeCommand(String command) {
StringBuffer output = new StringBuffer();
System.out.println("command is = \n"+command);
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();
}
The line is executed and calc is starting , but the log part doesn't work. The log file psexecOut.txt is not created.
When I run the command normally (without excaped characters) in cmd it runs fine and the log file is created, but using java it doesn't create the log file.
I suspect that > needs to be escaped but as I read it's already escaped as it is.
How can I execute the psexec with log to text file in a single cmd line using java like I can do manually in windows console ?
Solved:
As lit suggested in the comments: cmd.exe /c works.
So the corrected method is:
private static String executeCommand(String command) {
StringBuffer output = new StringBuffer();
System.out.println("command is = \n"+command);
Process p;
try {
p = Runtime.getRuntime().exec("cmd.exe /c "+command); // <-correction done here
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();
}
Try putting cmd.exe /C at the beginning of the command? It is cmd.exe that interprets the > redirection.
"cmd.exe /C psexec -i -d \\\\computerName -u user -p pass calc 2> somePath\\psexecOut.txt"

ssh to remote host using sshpass and fetch results using java

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.

java run bash script, command not found

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

execute pig command in Java program

I used to write PHP code to execute pig command, it worked well,
Now I switch to Java but seems it won't work, here is my code:
String pigCommand = "pig -x local -p ouput=/tmp my_pig_script.pig";
Runtime r = Runtime.getRuntime();
Process p;
int exitVal;
try {
p = r.exec(pigCommand);
exitVal = p.waitFor();
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = null;
while((line = br.readLine()) != null) {
System.out.println(line);
}
br.close();
System.out.println("exitVal: " + exitVal);
System.out.println("Done");
If I run the that pig command in console directly, it works, if I replace
that Pig command with other shell command say 'ping www.yahoo.com', and run the
java Program, it works too. So what might be the problem? thanks
You should use PigServer to execute pig scripts from java programs. It is more foolproof and more portable.
Also see this answer: https://stackoverflow.com/a/11299259/373151

Categories

Resources