How can I call a shell script from a Java program? - java

I use ubuntu 10.04 with eclipse. I created a shell script, exam.sh:
#!/bin/bash
echo "Hello World"
with chmod 755 exam.sh
On the command line, I can execute ./exam.sh // ok command showing me Hello World
I want to call this exam.sh with java code, this is my java code:
public static void main(String[] args) {
Runtime r = Runtime.getRuntime();
Process p = null;
String cmd[] = {"/bin/bash","cd","/home/erdi/Desktop", ".","/","exam.sh"};
try {
p = r.exec(cmd);
System.out.println("testing...");//ok
} catch (Exception e) {
e.printStackTrace();
}
}
This doesn't function, where did I make a mistake?
Yes I know i can search by google but I didn't find an answer to my problem. It gives howTos and tutorials about this feature but I didn't find an answer.

Try this instead:
cmd[] = {"/bin/bash", "/home/ercan/Desktop/exam.sh"};
You can just invoke bash on the shell script directly. To run a command string (like cd) you would need to use the -c switch.
If you need the working directory of the script to be your Desktop, you can use another overload of Runtime.exec:
Process proc = Runtime.getRuntime().exec(cmd, new String[0], new File("/home/ercan/Desktop"));
Alternatively, the ProcessBuilder class makes executing processes a bit nicer.

Related

Back to back commands in mac terminal via java Runtime

Basically I have 2 commands I need to execute via a java program the way you would if you were just typing it into terminal.
so like
cd /Users/nameOfUser/Desktop/someFolder/someSubFolder
and then another command I want to execute within that directory. Currently I am doing this:
Process navigate = Runtime.getRuntime().exec("cd /Users/nameOfUser/Desktop/someFolder/someSubFolder");
Process doSomething = Runtime.getRuntime().exec("commandInThatDirectory");
Which doesn't work, it doesn't throw an exception but the second process doesn't seem to take place in the directory specified before it. I am new to processes and runtimes so please bear with me :P.
Is their a way to execute the commands back to back within the same instance of terminal or at least a format for 1 command where you can specify the directory for another command to take place in? I'm a linux user so I don't know mac terminal very well sorry.
It can be done something like this. you can run any command by by placing a semicolon between the commands.
public class Main {
public static void main(String[] args) throws IOException {
ProcessBuilder pb1 = new ProcessBuilder(
"bash",
"-c",
"cd /Users/nameOfUser/Desktop/someFolder/someSubFolder;commandInThatDirectory");
pb1.redirectErrorStream(true);
Process p = pb1.start();
}
}

Run a compound shell command from Java/Groovy

I got stuck trying to run a compound shell command from a Groovy script. It was one of those commands where you separate with "&&" so that the 2nd command never runs if the 1st one fails. For whatever reason I couldn't get it to work. I was using:
println "custom-cmd -a https://someurl/path && other-cmd -f parameter".execute([], new File('/some/dir')).text
The shell kept misinterpreting the command throwing errors like "custom-cmd -f invalid option" It was like it was ignoring the "&&" in between. I tried using a semi-colon as well but was not lucky. I tried using straight Java APIs Runtime.getRuntime().exec() and splitting the command into an array. I tried wrapping the command in single quotes and giving it to '/bin/sh -c' but nothing works.
How do you run a compound shell command from Java? I know I've done this in the past but I cannot figure it out today.
With groovy, the list form of execute should work:
def out = ['bash', '-c', "custom-cmd -a https://someurl/path && other-cmd -f parameter"].execute([], new File('/some/dir')).text
Of course you may want to use the consumeProcessOutput method on process, as if the output is too large, calling text may block
Try something like:
Runtime.getRuntime().exec("cmd /c \"start somefile.bat && start other.bat && cd C:\\test && test.exe\"");
Runtime.getRuntime().exec() can be used without splitting the commands into an array.
see https://stackoverflow.com/a/18867097/1410671
EDIT:
Have you tried using a ProcessBuilder? This seems to work on my OSX box:
public static void main(String[] args) throws IOException {
ProcessBuilder builder = new ProcessBuilder( "/bin/sh", "-c", "echo '123' && ls" );
Process p=null;
try {
p = builder.start();
}
catch (IOException e) {
System.out.println(e);
}
Scanner s = new Scanner( p.getInputStream() );
while (s.hasNext())
{
System.out.println( s.next() );
}
s.close();
}

firing a command in terminal from java program

I need to write a java program which when executed pushes a command into the terminal
I tried using runtime.exec(); but not working fine for me
what i want is "/home/raj/Desktop/java -jar test.jar" to be executed in terminal
Can any one help me to sort it out.
If you want to actually start a terminal window (rather than just executing the java process) you will need to launch xterm (or something similar) and tell xterm to run java for example
String command= "/usr/bin/xterm -e /home/raj/Desktop/java -jar test.jar";
Runtime rt = Runtime.getRuntime();
Process pr = rt.exec(command);
Please refer following example .with list of arguments to java program.
Process proc = null;
try {
String cmd[] = {"gnome-terminal", "-x", "bash", "-c", "ls; echo '<enter>'; read" };
proc = Runtime.getRuntime().exec(cmd, null, wd);
} catch (IOException e) {
e.printStackTrace();
}
You can use full path of the jar file as an argument to "java"
String command= "java -jar /home/raj/Desktop/test.jar";
Runtime rt = Runtime.getRuntime();
Process pr = rt.exec(command);

Execute Unix system command from JAVA problem

I am facing a weird issue with executing a system command from JAVA code.
Actually i want to get the Mac OSX system information from my JAVA App.
For that im using
Runtime.getRuntime().exec("system_profiler -detailLevel full");
This is working fine.If i print the output,it is cool.
But i want to write this information to a plist file for future use.For that im using the -xml argument of system_profiler.like,
String cmd = "system_profiler -detailLevel full -xml > "+System.getProperty( "user.home" )+"/sysinfo.plist";
Process p = Runtime.getRuntime().exec(cmd);
Basically this should create a plist file in the current users home directory.
But this seems to be not writing anything to file.
Am i missing something here ?
My Java is more than rusty, so please be gentle. ;-)
Runtime.exec() does not automatically use the shell to execute the command you passed, so the IO redirection is not doing anything.
If you just use:
"/bin/sh -c system_profiler -detailLevel full > path/file.plist"
Then the string will be tokenized into:
{ "/bin/sh", "-c", "system_profiler", "-detailLevel", "full", ">", "path/file.plist" }
Which also wouldn't work, because -c only expects a single argument.
Try this instead:
String[] cmd = { "/bin/sh", "-c", "system_profiler -detailLevel full > path/file.plist" };
Process p = Runtime.getRuntime.exec(cmd);
Of course, you could also just read the output of your Process instance using Process.getInputStream() and write that into the file you want; thus skip the shell, IO redirection, etc. altogether.
Christian.K is absolutely correct. Here is a complete example:
public class Hello {
static public void main (String[] args) {
try {
String[] cmds = {
"/bin/sh", "-c", "ls -l *.java | tee tmp.out"};
Process p = Runtime.getRuntime().exec (cmds);
p.waitFor ();
System.out.println ("Done.");
}
catch (Exception e) {
System.out.println ("Err: " + e.getMessage());
}
}
}
If you weren't using a pipe (|) or redirect (>), then you'd be OK with String cmd = "ls -l *.java", as in your original command.
If you actually wanted to see any of the output in your Java console window, then you'd ALSO need to call Process.getInputStream().
Here's a good link:
Running system commands in Java applications

Invoking an external process with a different user in java

We have a java application running as a windows service. A particular functionality needs to execute a binary but with a different user then which started the application.
Is there any way by which we can invoke an exe with 'Run as a different user' style.
I checked API of ProcessBuilder but didn't found anything related to user. Is there any 3rd party tool to achieve this.
You can use PSExec to execute processes as a different user. The command line looks like:
psexec.exe -u username -p password mybinary.exe
You can then use ProcessBuilder to build the command around this.
Edit: here is an example of how you can do it:
public int startProcess(String username, String password,
String executable, String... args) throws IOException {
final String psexec = "C:\\PsTools\\psexec.exe"; //psexec location
//Build the command line
List<String> command = new LinkedList<String>();
command.add(psexec);
if(username != null) {
command.add("-u");
command.add(username);
command.add("-p");
command.add(password);
}
command.add(executable);
command.addAll(Arrays.asList(args));
ProcessBuilder builder = new ProcessBuilder(command);
Process process = builder.start();
int returnCode;
try {
returnCode = process.waitFor();
} catch (InterruptedException e) {
returnCode = 1;
}
return returnCode;
}
You can then use it like this:
startProcess("Bob", "Password", "Notepad.exe", "C:\\myfile.txt");
I believe you can use the runas DOS command in a pinch, if you can't find something else. (Type runas in a dos prompt for usage info.)
Edit: Unfortunately, according to a note here this apparently won't work from a service. :/ You might be able to create a small separate wrapper app that you could invoke which would then invoke the binary with runas, though.

Categories

Resources