I was recently trying to restart/shutdown the pc, using a cmd command in java, but get a CreateProcess error=2.
I'm using a StringBuilder cause I need to use the "" in the cmd command.
public class CMDTest {
public static void main(String[] args) throws IOException {
startCmd();
}
public static void startCmd() throws IOException {
String a = "shutdown -s -t 120 -c ";
String b = "\"Your computer will restart. Cause something .\"";
String g = "";
StringBuilder sbuilder = new StringBuilder();
sbuilder.append(a);
sbuilder.append(b);
String finall = sbuilder.toString();
System.out.println(finall);
Runtime.getRuntime().exec(new String[]{finall, g});
System.out.println(g);
Process p = Runtime.getRuntime().exec(new String[]{finall, g});
InputStream s = p.getInputStream();
BufferedReader in = new BufferedReader(new InputStreamReader(s));
String t;
while ((t = in.readLine()) != null) {
System.out.println(t);
}
}
}
All you need is this code:
String command = "shutdown -s -t 120 -c \"Your computer will restart. Cause something.\"";
Runtime.getRuntime().exec(command);
Works perfectly, at least on Windows-Systems.
The reason why your code is not working is the new String[]{finall, g}. If you pass an array, it will use the first index as the command and the others as params. This will cause into the following:
Command: shutdown -s -t 120 -c
Parameter: \"Your computer will restart. Cause something.\"
Instead if you pass a string, this will happen:
Command: shutdown
Parameters: -s, -t, 120, -c, \"Your computer will restart. Cause something.\"
Only the second command can be found, only the standalone shutdown command exists.
Related
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"};
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
I am using ProcessBuilder to execute a mysqldump from java code
and this is my code
public static void executeCommant(String... command) throws Exception {
ProcessBuilder processBuilder = null;
processBuilder = new ProcessBuilder(command);
processBuilder.redirectErrorStream(true);
Process process = processBuilder.start();
int resultCode = process.waitFor();
if (resultCode != 0) {
throw new Exception("" + readCommandOutput(process.getInputStream()));
}
}
private static String readCommandOutput(InputStream inputStream) throws IOException {
StringBuilder sb = new StringBuilder();
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(inputStream));
String line = null;
while ((line = br.readLine()) != null) {
sb.append(line + System.getProperty("line.separator"));
}
} finally {
br.close();
}
return sb.toString();
}
public static void main(String[] args) throws Exception {
executeCommant("mysqldump -u root -P 3316 -h localhost > G:\\test.sql");
}
Problem is i get the following exception even though when i run the same command from cmd i dont get any problem, and i just cannot figure out why it cannot find the specified file!!
PS: i tried with giving the full path for the mysqldump.exe and got the same result
Exception in thread "main" java.io.IOException: Cannot run program "mysqldump -u root -P 3316 -h localhost > G:\test.sql": CreateProcess error=2, The system cannot find the file specified
at java.lang.ProcessBuilder.start(ProcessBuilder.java:470)
at com.etq.e2mc.platform.windows.WindowsProcess.executeCommant(WindowsProcess.java:46)
at com.etq.e2mc.platform.windows.WindowsProcess.main(WindowsProcess.java:67)
Caused by: java.io.IOException: CreateProcess error=2, The system cannot find the file specified
at java.lang.ProcessImpl.create(Native Method)
at java.lang.ProcessImpl.<init>(ProcessImpl.java:177)
at java.lang.ProcessImpl.start(ProcessImpl.java:28)
at java.lang.ProcessBuilder.start(ProcessBuilder.java:452)
... 2 more
First, your are calling the ProcessBuilder(String... command) with an array, meaning that the first value of the array is the program. However, you are sending the entire string "mysqldump -u root -P 3316 -h localhost > G:\\test.sql", and that is not a program. Only mysqldump is the program.
Second, when capturing output using getInputStream(), you need to do that before calling waitFor(), otherwise your risk the output buffer running full, halting execution of the program you're running, essentially causing a deadlock between your program waiting for the command to exit and the command waiting for you to read the output. If you need the stream, you generally need to read it in a separate thread.
Third, you can't redirect output using > in the command string. That is something cmd.exe does, and you're not invoking cmd.exe. Since you want to redirect to a file, do that directly using the ProcessBuilder.
ProcessBuilder processBuilder = new ProcessBuilder(
"mysqldump", "-u", "root", "-P", "3316", "-h", "localhost");
processBuilder.redirectErrorStream(true);
processBuilder.redirectOutput(new File("G:\\test.sql"));
Process process = processBuilder.start();
int resultCode = process.waitFor();
if (resultCode != 0) {
throw new Exception("Program failed with error " + resultCode);
}
I'd like to execute multiple commands with ProcessBuilder. I want to avoid using script files, only hardcoded strings in Java.
This is the current file that I'd like to execute.
#!/bin/sh
if [ -e /tmp/pipe ]
then
rm /tmp/pipe
fi
mkfifo /tmp/pipe
tail -f /dev/null >/tmp/pipe & # keep pipe alive
cat /tmp/pipe | omxplayer $1 -r &
Now, this is my current code.
private static final String[][] commands = {
{"rm", "-f", "/tmp/airpi_pipe"},
{"mkfifo", "/tmp/airpi_pipe"},
{"tail", "-f", "/dev/null", ">", "/tmp/airpi_pipe"}
};
public static void main(String[] args) throws IOException {
for (String[] str : commands) {
ProcessBuilder pb = new ProcessBuilder(str);
pb.redirectErrorStream(true);
Process process = pb.start();
InputStream is = process.getInputStream();
BufferedReader in = new BufferedReader(new InputStreamReader(is));
String inputLine;
while ((inputLine = in.readLine()) != null) {
System.out.println(inputLine);
}
System.err.println("next one");
}
}
Obviously, the tail command doesn't work in my ProcessBuilder. I haven't even tried with cat /tmp/pipe | omxplayer $1 -r &.
So, my question is, how could I manage to execute the content of my sh script with ProcessBuilder, but only with hardcoded commands (no script file), as I'm trying to do?
Thank you.
UPDATE
I had to use new ProcessBuilder("/bin/sh", "-c", "<commands>"); to make it work!
I'm tearing my hair out trying to work out why the command I'm executing via Java using a ProcessBuilder & Process is not working. I run the "same" command at the Windows command line and it works as expected. It must be that they're not the same but I can't for the life of me work out why.
The command is this:
ccm start -nogui -m -q -n ccm_admin -r developer -d /path/to/db/databasename -s http://hostname:8400 -pw Passw0rd789$
The output is should be a single line string that I need to grab and set as an environment variable (hence the v. basic use of the BufferedReader).
My Java code, which when it runs the command gets an application error, looks like this with entry point being startCCMAndGetCCMAddress():
private static String ccmAddress = "";
private static final String DATABASE_PATH = "/path/to/db/databasename";
private static final String SYNERGY_URL = "http://hostname:8400";
private static final String USERNAME = "ccm_admin";
private static final String PASSWORD = "Passw0rd789$";
private static final String USER_ROLE = "developer";
public static List<String> getCCMStartCommand() {
List<String> command = new ArrayList<String>();
command.add("cmd.exe");
command.add("/C");
command.add("ccm");
command.add("start");
command.add("-nogui");
command.add("-m");
command.add("-q");
command.add("-n "+USERNAME);
command.add("-r "+USER_ROLE);
command.add("-d "+DATABASE_PATH);
command.add("-s "+SYNERGY_URL);
command.add("-pw "+PASSWORD);
return command;
}
private static String startCCMAndGetCCMAddress() throws IOException, CCMCommandException {
int processExitValue = 0;
List<String> command = getCCMStartCommand();
System.err.println("Will run: "+command);
ProcessBuilder procBuilder = new ProcessBuilder(command);
procBuilder.redirectErrorStream(true);
Process proc = procBuilder.start();
BufferedReader outputBr = new BufferedReader(new InputStreamReader(proc.getInputStream()));
try {
proc.waitFor();
} catch (InterruptedException e) {
processExitValue = proc.exitValue();
}
String outputLine = outputBr.readLine();
outputBr.close();
if (processExitValue != 0) {
throw new CCMCommandException("Command failed with output: " + outputLine);
}
if (outputLine == null) {
throw new CCMCommandException("Command returned zero but there was no output");
}
return outputLine;
}
The output of the System.err.println(...) is:
Will run: [cmd.exe, /C, ccm, start, -nogui, -m, -q, -n ccm_admin, -r developer, -d /path/to/db/databasename, -s http://hostname:8400, -pw Passw0rd789$]
I think you need to provide each argument separately, and without leading/trailing spaces, rather than concatenating select ones e.g "-pw PASSWORD". That way you'll invoke the process with the correct argument set (as it would see from the command line)