java executing shell commands - java

I am writing a java program that needs to execute shell commands, so I wrote a function that would take the command to execute as a string (ie: "mkdir ~/Folder1") and execute that command with the shell. Here is the function:
private static void shell(String cmd)
{
try
{
Runtime run = Runtime.getRuntime();
Process pr = run.exec(cmd);
pr.waitFor();
BufferedReader buf = new BufferedReader(new InputStreamReader(pr.getInputStream()));
String line = "";
while ((line = buf.readLine()) != null) {
System.err.println(line); // show any errors returned by the command executed on the error console
}
} catch (Exception ee) {}
}
for some weird reason this function is not executing any commands. Did I do this wrong? It seems like a simple thing to execute shell commands, but it is not working.

I think you are passing the command string as some mkdir command like ,
"mkdir C:\some\folder\path".
mkdir is not some binary in Windows path, it's a parameter to command line.
Use the command string as "cmd.exe /c mkdir C:\some\folder\path"
Then it should work fine.

Related

Using ADB pull command in a Java program

I can't get the ADB command to work in Java. The adb command works when inputting it directly to the command line. But when running it in Java, I get error
Cannot run program "adb -s shell": CreateProcess error=2,file not found
What is the proper syntax for running Windows Command line from Java?
The adb command "adb devices" works in the Java application. The command I'm trying to run is "adb pull sdcard/Download/symmetri.txt C:/Users/myUsername/Downloads/Sources", which works in the command prompt, but not from within the Java application. My code is:
public void FilePush() {
try{
String androidFilePath = "sdcard/Download/symmetri.txt ";
String windowsFilePath = "C:\\Users\\myUsername\\Downloads\\Sources\"";
List<String> cmd = new LinkedList<>();
cmd.add("adb -s shell");
cmd.add("adb");
cmd.add("pull");
cmd.add(androidFilePath);
cmd.add(windowsFilePath);
ProcessBuilder builder = new ProcessBuilder(cmd);
builder.redirectErrorStream(true);
Process p = builder.start();
}
catch (IOException e) {
e.printStackTrace();
}
}
I also tried without adb -s shell" and with
String androidFilePath = "\"/storage/sdcard0/Download/symmetri.txt\"";
String windowsFilePath = "\"C:\\Users\\myUsername\\Downloads\\Sources\\"";
But got the same error
Remove the line
cmd.add("adb -s shell");
as you don't want shell but pull.
Thx to the helpful people here, I finally got it to work! I first needed to run adb.exe as a command, before I could run any adb commands. I needed to remove ("adb -s shell") from my list of commands. I was trying to acces a file in the external storage instead of the internal one which needs root access
(Although I have no clue why I can acces the exact same file in a Command prompt window without permitting root acces). If you want to access external files, add root access with
adb root
Full code that works for anyone who might face the same issue :
public void FilePush() {
try{
String androidFilePath = "/storage/emulated/0/Android/data/com.example.myapp/files/myfile.txt";
String windowsFilePath = "C:\\Users\\myUsername\\Downloads\\Sources";
List<String> cmd = new LinkedList<>();
cmd.add("C:\\Users\\myUsername\\AppData\\Local\\Android\\Sdk\\platform-tools\\adb.exe");
cmd.add("pull");
cmd.add(androidFilePath);
cmd.add(windowsFilePath);
ProcessBuilder pb = new ProcessBuilder(cmd);
pb.redirectErrorStream(true);
String line = "null";
pb.redirectErrorStream(true); // can use these 2 line if you want to see output or errors in file.
pb.redirectOutput(new File("C:\\Users\\myUsername\\Downloads\\Sources\\logs.txt"));
Process p = pb.start();
while(p == null)
Thread.sleep(1000);
BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
Pattern pattern = Pattern.compile("^([a-zA-Z0-9\\-]+)(\\s+)(device)");
Matcher matcher;
while ((line = in.readLine()) != null) {
if (line.matches(pattern.pattern())) {
matcher = pattern.matcher(line);
if (matcher.find()) ;
}
}
}
catch (Exception e) {
e.printStackTrace();
}
}

psql: command not found when running bash script in eclipse

I'm writing a Java method to run a local bash script using Eclipse. The code is showing as below:
public static void setUp() throws IOException, InterruptedException {
Runtime rt = Runtime.getRuntime();
Process p;
String filePath = new File("").getAbsolutePath();
filePath = filePath.concat("/path/to/the/script");
String command = String.format("sh %s/setUp.sh", filePath);
System.out.println(command);
try {
p = rt.exec(command);
final int errorValue = p.waitFor();
if (errorValue != 0) {
System.out.println("error detected!");
InputStream error = p.getErrorStream();
BufferedReader br = new BufferedReader(new InputStreamReader(error));
String line = "";
while ((line = br.readLine()) != null) {
System.out.println(line);
}
p.destroy();
}
} catch (Exception e) {
e.printStackTrace();
}
}
AND the bash file is very simple:
#!/bin/bash
#create a local db and import some data
createdb -U dummy -O dummy -h localhost dbname
psql -h localhost -d dbname --file $1
The issue is
line 4: createdb: command not found
line 5: psql: command not found
I can run the script in terminal and I can copy line4 and line5 in terminal, and I can run mvn exec command in the terminal to run the method. All works.
Only thing not working is it was executed in eclipse.
I'm open to any opinion or advices, please let me know if you need more information.
Thanks for all the helps in advance!
I suspect that the Runtime that is used to execute the script won't have the paths set correctly. Try using full paths for the commands in the script, and see if that works (you can find the full paths by running which createdb and which psql in the terminal).

getting error from java

How can I call a shell script through java code?
I have writtent the below code.
I am getting the process exit code as 127.
But it seems my shell script in unix machine is never called.
String scriptName = "/xyz/downloads/Report/Mail.sh";
String[] commands = {scriptName,emailid,subject,body};
Runtime rt = Runtime.getRuntime();
Process process = null;
try{
process = rt.exec(commands);
process.waitFor();
int x = process.exitValue();
System.out.println("exitCode "+x);
}catch(Exception e){
e.printStackTrace();
}
From this post here 127 Return code from $?
You get the error code if a command is not found within the PATH or the script has no +x mode.
You can have the code below to print out the exact output
BufferedReader stdInput = new BufferedReader(new InputStreamReader(process.getInputStream()));
String s= null;
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
BufferedReader stdOut = new BufferedReader(new InputStreamReader(process. getErrorStream()));
String s= null;
while ((s = stdOut.readLine()) != null) {
System.out.println(s);
}
If you are getting an exit code, then your script is executed. There is a command that you are running inside of "Mail.sh", which is not succeccfully executed and returning a status code of 127.
There could be some paths that are explicitly set in your shell, but is not available to the script, when executed outside of the shell.
Try this...
Check if you are able to run /xyz/downloads/Report/Mail.sh in a shell terminal. Fix the errors if you have any.
If there are no errors when you run this in a terminal, then try running the command using a shell in your java program.
String[] commands = {"/bin/sh", "-c", scriptName,emailid,subject,body};
(Check #John Muiruri's answer to get the complete output of your command. You can see where exactly your script is failing, if you add those lines of code)

Run Shell Commands using Java provides problems

public class RunBashCommand {
public synchronized boolean RunInBash(String command) {
System.out.println("CMD: "+command);
/*String s; not working this code also
Process p;
try {
Process p = Runtime.getRuntime().exec(command);
BufferedReader br = new BufferedReader(
new InputStreamReader(p.getInputStream()));
while ((s = br.readLine()) != null)
System.out.println("line: " + s);
p.waitFor();
System.out.println ("exit: " + p.exitValue());
PrintBufferReader(getError(p));
p.destroy();
} catch (Exception e) {
e.printStackTrace();
}*/
try {
Process p = new ProcessBuilder("/bin/sh", command).start();
/*Process p = new ProcessBuilder("/bin/bash", command).start();*/
PrintBufferReader(getError(p));
/*p.destroy();*/
} catch (IOException e) {
e.printStackTrace();
}
return true;
}
private static BufferedReader getOutput(Process p) {
return new BufferedReader(new InputStreamReader(p.getInputStream()));
}
private static BufferedReader getError(Process p) {
return new BufferedReader(new InputStreamReader(p.getErrorStream()));
}
private void PrintBufferReader(BufferedReader br) throws IOException {
int value = 0;
String s = "";
while((value = br.read()) != -1)
{
char c = (char)value;
s = s+c;
}
System.out.println("EEEE: "+s);
}
}
I tried this code, but it did not work.
following output came:
CMD: cd /home/jeevan/workspace/apb_proj/; source init.csh
EEEE: /bin/sh: cd /home/jeevan/workspace/apb_proj/; source init.csh: No such file or directory
CMD: cd /home/jeevan/workspace/apb_proj/verif/compile/; make clean; make compile; make elab
EEEE: /bin/sh: cd /home/jeevan/workspace/apb_proj/verif/compile/; make clean; make compile; make elab: No such file or directory
CMD: sh /home/jeevan/workspace/apb_proj/verif/test_lib/src/apb_test31/runme.csh
EEEE: /bin/sh: sh /home/jeevan/workspace/apb_proj/verif/test_lib/src/apb_test31/runme.csh: No such file or directory
can some one help?
You're effectively running:
/bin/sh "cd /home/jeevan/workspace/apb_proj/; source init.csh"
When you run /bin/sh this way, it treats its first argument as the name of a file to execute as a shell script. Of course, there's no file named "cd /home/jeevan/workspace/apb_proj/; source init.csh", so you get an error message.
The correct way to invoke sh with a command as an argument is like this:
/bin/sh -c "cd /home/jeevan/workspace/apb_proj/; source init.csh"
Using process builder, you'd do:
Process p = new ProcessBuilder("/bin/sh", "-c", command).start();
The next problem that you're likely to run into is that it appears that the command you're trying to invoke is a csh command, not an sh command. "source" is a csh command, and the file you're trying to source is called "init.csh". So maybe you want to invoke csh instead of sh:
Process p = new ProcessBuilder("/bin/csh", "-c", command).start();
You need to split command arguments into separate parameters: not ProcessBuilder("bin/sh", "cd foo/bar") but ProcessBuilder("bin/sh", "cd", "foo/bar").
You can't use shell metacharacters (like ";") too. To run multiple commands, you have to start multiple processes.
Put all your commands into a List and pass it as the argument to the ProcessBuilder. As an alternative you can start the shell process, get it's OutputStream and write commands into this stream to execute them.

how to launch a shell script in a new gnome terminal, from a java program

I'm trying to run a shell script (say myscript.sh) from a java program.
when i run the script from terminal, like this :
./myscript.sh
it works fine.
But when i call it from the java program, with the following code :
try
{
ProcessBuilder pb = new ProcessBuilder("/bin/bash","./myScript.sh",someParam);
pb.environment().put("PATH", "OtherPath");
Process p = pb.start();
InputStreamReader isr = new InputStreamReader(p.getInputStream());
BufferedReader br = new BufferedReader(isr);
String line ;
while((line = br.readLine()) != null)
System.out.println(line);
int exitVal = p.waitFor();
}catch(Exception e)
{ e.printStackTrace(); }
}
It doesnt goes the same way.
Several shell commands (like sed, awk and similar commands) get skipped and donot give any output at all.
Question : Is there some way to launch this script in a new terminal using java.
PS : i've found that "gnome-terminal" command launches a new terminal in shell,
But, i'm unable to figure out, how to use the same in a java code.
i'm quite new to using shell scripting. Please help
Thanks in advance
In java:
import java.lang.Runtime;
class CLI {
public static void main(String args[]) {
String command[] = {"/bin/sh", "-c",
"gnome-terminal --execute ./myscript.sh"};
Runtime rt = Runtime.getRuntime();
try {
rt.exec(command);
} catch(Exception ex) {
// handle ex
}
}
}
And the contents of the script are:
#!/bin/bash
echo 'hello!'
bash
Notes:
You'll do this in a background thread or a worker
The last command, in the shell script, is bash; otherwise execution completes and the terminal is closed.
The shell script is located in the same path as the calling Java class.
Don't overrwrite your entire PATH...
pb.environment().put("PATH", "OtherPath"); // This drops the existing PATH... ouch.
Try this instead
pb.environment().put("PATH", "OtherPath:" + pb.environment().get("PATH"));
Or, use the full directories to your commands in your script file.
You must set your shell script file as executable first and then add the below code,
shellScriptFile.setExecutable(true);
//Running sh file
Process exec = Runtime.getRuntime().exec(PATH_OF_PARENT_FOLDER_OF_SHELL_SCRIPT_FILE+File.separator+shellScriptFile.getName());
byte []buf = new byte[300];
InputStream errorStream = exec.getErrorStream();
errorStream.read(buf);
logger.debug(new String(buf));
int waitFor = exec.waitFor();
if(waitFor==0) {
System.out.println("Shell script executed properly");
}
This worked for me on Ubuntu and Java 8
Process pr =new ProcessBuilder("gnome-terminal", "-e",
"./progrm").directory(new File("/directory/for/the/program/to/be/executed/from")).start();
The previous code creates a new terminal in a specificied directory and executes a command
script.sh Must have executable permissions
public class ShellFileInNewTerminalFromJava {
public static void main(String[] arg) {
try{
Process pr =new ProcessBuilder("gnome-terminal", "-e", "pathToScript/script.sh").start();
}catch(Exception e){
e.printStackTrace();
}
}
}

Categories