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.
Related
I'm trying to execute one sh file that run postgres commands, but it never ends.
The sh file is that:
#!/bin/bash
echo "My ARGUMENTS $1 $2 $3 $4";
psql -h $1 -p $2 -U $3 -d template1 -c "drop database IF EXISTS $4";
psql -h $1 -p $2 -U $3 -d template1 -c "create database $4";
echo "OPERATION COMPLETED";
And my java method is the following:
public void createDB() {
try{
ProcessBuilder builder = new ProcessBuilder();
builder.command("sh", "-c", "ls");
ProcessBuilder pb = new ProcessBuilder("/tmp/test.sh", "localhost", "5432", "postgres", "newDB");
Process p = pb.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = null;
while ((line = reader.readLine()) != null)
{
System.out.println(line);
}
}catch (Exception e) {
System.out.println("ERORR");
}
}
the output is:
My ARGUMENTS localhost 5432 postgres newDB
But never execute the second psql statement, can someone help me please.
The soluction was the following:
public void createDB() {
try{
ProcessBuilder builder = new ProcessBuilder();
builder.command("sh", "-c", "ls");
ProcessBuilder pb = new ProcessBuilder("/tmp/test.sh", "localhost", "5432", "postgres", "newDB");
// set environment variable password
env.put("PGPASSWORD", "123456");
Process p = pb.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = null;
while ((line = reader.readLine()) != null)
{
System.out.println(line);
}
}catch (Exception e) {
System.out.println("ERORR");
}
}
I pass the password by enviroment variable. Thanks to all!
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();
}
I am trying to execute the following curl command from Java, but the answer I get is incorrect, since it always returns the status 401.
curl -k -v -u "admin2:0xdRv63RKq2MtA326BNGQAI6yA1QNGO09enamGxI" -d "{"username":"test","token_code":"246212"}" -H "Content-Type: application/json" https://192.168.101.59/api/v1/auth/
I am sending correctly the user "admin2" with his password for the authentication. I think the problem is the use of character (") in my code.
String[] command = {"curl", "-k", "-v", "-u","admin2:0xdRv63RKq2MtA326BNGQAI6yA1QNGO09enamGxI",
"-d", "{\"username\":\"test\",\"token_code\":\"246212\"}","-H", "Content-Type: application/json", "https://192.168.101.59/api/v1/auth/"};
ProcessBuilder builder = new ProcessBuilder(command);
builder.redirectErrorStream(true);
String curlResult = "";
String line = "";
try {
Process process = builder.start();
BufferedReader r = new BufferedReader(new InputStreamReader(process.getInputStream()));
while (true) {
line = r.readLine();
if (line == null) {
break;
}
curlResult = curlResult + line;
}
} catch (Exception e) {
e.printStackTrace();
}
In 'command', try removing the single quotes from
"'admin2:0xdRv63RKq2MtA326BNGQAI6yA1QNGO09enamGxI'"
so that it becomes
"admin2:0xdRv63RKq2MtA326BNGQAI6yA1QNGO09enamGxI"
and see if that helps. It might be considering them as part of the actual username and password.
I think the issue is the Json in this case and I think you are right then that the double quotes are the issue. Try putting the Json in a file and use curl to send the file contents as the body of your message.
String[] command = {"curl", "-k", "-v", "-u","admin2:0xdRv63RKq2MtA326BNGQAI6yA1QNGO09enamGxI",
"-d", "#/path/to/filename.json", "-H", "Content-Type: application/json", "https://192.168.101.59/api/v1/auth/"};
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"
I'm currently using ProcessBuilder to run some file like test.out.
Here is some of my code
ArrayList cmd = new ArrayList();
cmd.add("sudo");
cmd.add("./test.out");
String s = "";
try{
ProcessBuilder pb = new ProcessBuilder(cmd);
pb.directory(new File("/myPath"));
pb.redircErrorStream(true);
Process p = pb.start();
InputStream is = p.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferReader br = new BufferReader(isr);
String line = "";
while((line = br.readLine()) !=null)
{
s+=line;
}
System.out.println(s);
}
I output the path which is correct("/myPath").
when I remove line
`cmd.add("sudo")`
the output will give me a String:
oneoflib:must be root. Did you forgot sudo?
But once I add
cmd.add("sudo");
there is nothing output.
Is there anyone whats wrong with it?
I can run sudo ./test.out from terminal which works fine.
I'm using eclipse BTW.
Thank you very much.
I guess that getting the error stream from the process could be beneficial here to help debug the problem.
This should help, consider the following bash script and let's call it yourExecutable. Let's also assume that it has all the proper permissions:
if [ "$EUID" -ne 0 ]
then echo "Please run as root"
exit
fi
echo "You are running as root"
When run without sudo it prints "Please run as root" other wise it prints "You are running as root"
The command, ie first argument in your list should be bash, if that is the shell you are using. The first argument should be -c so the commands will be read from the following string. The string should be echo <password> | sudo -S ./yourExecutable. This isn't exactly the best way to send the password to sudo, but I don't think that is the point here. The -S to sudo will prompt for the password which is written to stdout and piped over to sudo.
public static void main(String[] args) throws IOException {
Process process = new ProcessBuilder("bash", "-c", "echo <password> | sudo -S ./yourExecutable").start();
BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
String string;
while((string = errorReader.readLine()) != null){
System.out.println(string);
}
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
while((string = reader.readLine()) != null){
System.out.println(string);
}
}
Output on my machine looks like:
Password:
You are running as root