Curl command through Java works in windows and not in linux - java

I am trying to execute a curl command using Java using the code below
String myUrl= "https://someIp:somePort";
String username = "someusername";
String password = "somepassword";
String command = "curl -k -d \"client_id=someId\" -d \"username="+username+"\" -d \"password="+password+"\" -d \"grant_type=password\" -d \"client_secret=\" \""+myUrl+"/myauth/openid-connect/token\"";
Process process = Runtime.getRuntime().exec(command);
ByteArrayOutputStream result = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int length;
while ((length = process.getInputStream().read(buffer)) != -1) {
result.write(buffer, 0, length);
}
String response = result.toString(StandardCharsets.UTF_8.name());
This works on windows machine but not on linux. Is there any difference between linux and windows in the way curl command is executed using exec method ?
Both execution are done using same JRE. On windows I get the token successfully but in Linux I get the following response :
Response = {"error":"invalid_request","error_description":"Missing form parameter: grant_type"}
Thank you

After investigation it seems that when someone executes this java code in linux enviroment the curl command is not properly constructed.
I used the following code and everything worked fine :
String cUrlToKeyCloak = "curl -k -d \"client_id=someId\" -d \"username="+username+"\" -d \"password="+password+"\" -d \"grant_type=password\" "+keyCloakUrl+"/auth/realms/master/protocol/openid-connect/token";
ProcessBuilder processBuilder = new ProcessBuilder();
if(!System.getProperty("os.name").contains("Windows"))
processBuilder.command("bash", "-c", cUrlToKeyCloak );
else
processBuilder.command("cmd.exe", "/c", cUrlToKeyCloak );
String cKeyResponse = "";
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) {
LOGGER.info("Curl command to keyCloak requested ...");
LOGGER.info("cKey response = "+output);
cKeyResponse = output.toString();
} else {
LOGGER.error("Curl command to keyCloak executed with error ...");
LOGGER.info("cKey response = "+output);
return false;
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}

Related

Sending 'exec' commands to Docker container using 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.

Java.io.Exception: Working Directory: null Environment: null

I am trying to run a shell command from my application directory and I am getting "working directory null and environment null.
I have looked at several posts here but I'm not quite sure where to go from here.
Error:
Error running exec(). Command: [/data/user/0/com.netscout.iperf3_clientls] Working Directory: null Environment: null
public void startApp() {
StringBuffer output = new StringBuffer();
Process process = null;
String appFileDir = getApplicationInfo().dataDir;
// String commandLine = appFileDir + "/iperf3 -c 129.196.197.116 --forceflush -O3 -Z -P2";
String commandLine = appFileDir + "ls";
try {
process = Runtime.getRuntime().exec(commandLine, null, null);
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = "";
while ((line = reader.readLine())!= null) {
// output.append(line + "/n");
Log.e("Line", String.valueOf(line));
Log.e("output", String.valueOf(output));
}
} catch (IOException e) {
e.printStackTrace();
Log.i("Output", String.valueOf(e));
}
}
Try setting a working directory for the script to run from. Also I would suggest to use a ProcessBuilder for doing your job:
https://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html

java and wmctrl to resize windows

I'm writing a library to cover WMctrl shell program. I have problem with resizing windows:
String command = "wmctrl -r \"Calculator\" -e 0,100,100,500,500";
System.out.println(command);
String output = this.bashCommandExecutor.execute(command);
System.out.println(output);
This doesn't work - output variable is empty. But when I copy-paste wmctrl -r "Calculator" -e 0,100,100,500,500 to the Terminal it works properly.
Other commands like "wmctrl -d" and "wmctrl -l" work in this.bashCommandExecutor.execute() method.
This method looks like this:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class BashCommandExecutor
{
String execute(String bashCommand)
{
Process p = null;
try {
p = Runtime.getRuntime().exec(bashCommand);
p.waitFor();
}
catch (InterruptedException | IOException e) {
e.printStackTrace();
}
BufferedReader reader = new BufferedReader(
new InputStreamReader(p.getInputStream())
);
String line = "";
StringBuilder sb = new StringBuilder();
try {
while ((line = reader.readLine())!= null) {
sb.append(line + "\n");
}
} catch (IOException e) {
e.printStackTrace();
}
return sb.toString();
}
}
Why does resizing work in command line, but doesn't work in Java app?
I have found that using the ProcessBuilder class rather than Runtime.exec() works to run the wmctrl command you described.
So rather than:
String bashCommand = "wmctrl -r \"Calculator\" -e 0,100,100,500,500";
Process p = Runtime.getRuntime().exec(bashCommand);
You can try:
String bashCommand = "wmctrl -r \"Calculator\" -e 0,100,100,500,500";
ProcessBuilder pb = new ProcessBuilder("bash", "-c", bashCommand);
Process p = pb.start();
Here is a link to another post explaining the different between Runtime.exec() and using ProcessBuilder.

How to get processbuilder command before execution

I want to know the command that will be executed before it happens.
String cmd[] = {"curl",
"-X",
"POST",
"https://api.renam.cl/medicion/insert?access-token={Yoq3UGQqDKP4D1L3Y6xIYp-Lb6fyvavpF3Lm-8cD}",
"-H",
"content-type: application/json",
"-d",
json.toString()};
ProcessBuilder pb = new ProcessBuilder(cmd);
Log.debug("COMANDO.TOSTRING " + pb.command().toString());
Process p = pb.start();
Log.debug(p.getOutputStream().toString());
p.waitFor();
BufferedReader reader
= new BufferedReader(new InputStreamReader(p.getInputStream()));
String readline;
while ((readline = reader.readLine()) != null) {
Log.debug(readline);
}
With the readline I have the server answer output but I don't know hot to get the curl command I have exectuted with the processbuilder.
EDIT 1:
I just need to send this command by using the linux console:
curl -X POST 'https://api.com/data/insert?access-token=Yoq3UGQqDKP4D1L3Y6xIYp-Lb6fyvavpF3Lm-8cD' -H 'content-type: application/json' -d '{ "pm25":2, "timestamp":1495077872, "dispositivo_mac": "12:34:56:78:90:12" }'
Basically I need to print the cmd array processed by the ProcessBuilder object to see it before the star method execution.
I had success with this code:
ProcessBuilder pb = new ProcessBuilder(command);
logger.debug(String.join(" ",pb.command().toArray(new String[0])));
Here is code for printing the runnable command:
private String getRunnableCommand(ProcessBuilder processBuilder)
{
List<String> commandsList = processBuilder.command();
StringBuilder runnableCommandBuilder = new StringBuilder();
int commandIndex = 0;
for (String command : commandsList)
{
if (command.contains(" "))
{
runnableCommandBuilder.append("\"");
}
runnableCommandBuilder.append(command);
if (command.contains(" "))
{
runnableCommandBuilder.append("\"");
}
if (commandIndex != commandsList.size() - 1)
{
runnableCommandBuilder.append(" ");
}
commandIndex++;
}
return runnableCommandBuilder.toString();
}
It will surround arguments containing spaces properly with quotation marks.

Running executable from java fails

I am trying to run mdb-export on a file I know exist in that directory. But it does not seem to execute. "ls-l" will so I am sure that the java code is working. The command will execute perfectly from bash.
The failing command is
/usr/bin/mdb-export -Q -d ';' -D '%Y-%m-%d %H:%M:%S' /home/jocke/viking.mdb resultat >> resultat.csv
private void runCommand() {
try {
String workingdirectory=System.getProperty("user.dir");
Runtime runtime = Runtime.getRuntime();
//Process process = runtime.exec("/usr/bin/mdb-export -Q -d ';' -D '%Y-%m-%d %H:%M:%S' /home/jocke/viking.mdb resultat >> resultat.csv");
Process process = runtime.exec("/usr/bin/mdb-export /home/jocke/viking.mdb resultat >> resultat.csv");
//
process.waitFor();
InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
}
catch (Exception e) {
e.printStackTrace();
}
}
You cannot use output redirection this way. Use a ProcessBuilder instead:
ProcessBuilder pb = new ProcessBuilder("/usr/bin/mdb-export", "/home/jocke/viking.mdb", "resultat");
File csv = new File("resultat.csv");
pb.redirectOutput(Redirect.appendTo(csv);
Process p = pb.start();

Categories

Resources