Java with shell Script - java

I am writing a Java program from which I am executing a shell script. The shell script is calling another shell script. I am trying to print output returned by child script to parent shell script.
Below is my code.
public class App
{
public static void main( String[] args ) throws IOException, InterruptedException
{
String command = new String("/home/Test.sh");
Runtime rt = Runtime.getRuntime();
Process process = rt.exec(command);
process.waitFor(1, TimeUnit.MINUTES);
BufferedReader reader = new BufferedReader(new InputStreamReader(
process.getInputStream()));
String s;
while ((s = reader.readLine()) != null) {
System.out.println("Script output: " + s);
}
Shell Script: Test.sh
#!/bin/bash
result=$( bash myscript.sh )
echo "$result"
myscript.sh
#!/bin/bash
echo "50"
I am getting empty output. I initial thought it might be because the Java process is not waiting for the shell script to finish. So added waitFor() but still no use. Can some one kindly help.

try this; this is not waiting problem.
#!/bin/bash
result=$( bash /home/myscript.sh ) # full path of myscript
echo "$result"
Also handle bash error as below;
public static void main(String[] args) throws IOException {
String command = new String("/tmp/1/Test.sh");
Runtime rt = Runtime.getRuntime();
Process process = rt.exec(command);
BufferedReader reader = new BufferedReader(new InputStreamReader(
process.getInputStream()));
String s;
while ((s = reader.readLine()) != null) {
System.out.println("Script output: " + s);
}
BufferedReader stdError = new BufferedReader(new
InputStreamReader(process.getErrorStream()));
System.out.println("Here is the standard error\n");
while ((s = stdError.readLine()) != null) {
System.out.println(s);
}
}
adduser tests;
1-
myscript.sh:
#!/bin/bash
adduser test
echo "50"
java console output;
Script output: 50
Here is the standard error of the command (if any):
adduser: Only root may add a user or group to the system.
2-
myscript.sh:
#!/bin/bash
sudo adduser test
echo "50"
java console output;
Script output: 50
Here is the standard error of the command (if any):
sudo: no tty present and no askpass program specified
3-
myscript.sh:
#!/bin/bash
echo -e "YOURPASSWORD=\n" | sudo -S adduser -shell /bin/bash --home /home/test test
echo -e "YOURPASSWORD\n" | sudo deluser --remove-home test
echo "OK"
java console output;
Script output: Adding user `test' ...
Script output: Adding new group `test' (1002) ...
Script output: Adding new user `test' (1001) with group `test' ...
Script output: Creating home directory `/home/test' ...
Script output: Copying files from `/etc/skel' ...
Script output: Try again? [y/N] Changing the user information for test
Script output: Enter the new value, or press ENTER for the default
Script output: Full Name []: Room Number []: Work Phone []: Home Phone []: Other []: Is the information correct? [Y/n] Looking for files to backup/remove ...
Script output: Removing files ...
Script output: Removing user `test' ...
Script output: Warning: group `test' has no more members.
Script output: Done.
Script output: OK
Here is the standard error of the command (if any):
[sudo] password for ..: Enter new UNIX password: Retype new UNIX password: passwd: Authentication token manipulation error
passwd: password unchanged
Use of uninitialized value $answer in chop at /usr/sbin/adduser line 563.
Use of uninitialized value $answer in pattern match (m//) at /usr/sbin/adduser line 564.
Use of uninitialized value $answer in chop at /usr/sbin/adduser line 589.
Use of uninitialized value $answer in pattern match (m//) at /usr/sbin/adduser line 590.

Related

How to use Java ProcessBuilder to execute ./filename in linux

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

Why the following code doesn't work? [duplicate]

This question already has answers here:
Runtime's exec() method is not redirecting the output
(2 answers)
Closed 7 years ago.
i'm trying to run shell command in linux via java. most of the commands work, but when i run the following command i get an execption, although it works in the shell:
String command = "cat b.jpg f1.zip > pic2.jpg";
String s = null;
try {
Process p = Runtime.getRuntime().exec(command);
BufferedReader stdInput = new BufferedReader(new
InputStreamReader(p.getInputStream()));
BufferedReader stdError = new BufferedReader(new
InputStreamReader(p.getErrorStream()));
System.out.println("Here is the standard output of the command:\n");
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
System.out.println("Here is the standard error of the command (if any):\n");
while ((s = stdError.readLine()) != null) {
System.out.println(s);
}
System.exit(0);
}
catch (IOException e) {
System.out.println("exception happened - here's what I know: ");
e.printStackTrace();
System.exit(-1);
}
i am getting the error in the console:
cat: >: No such file or directory
cat: pic2.jpg: No such file or directory
The problem is the redirection.
cat: >: No such file or directory
The way to interpret this error message:
the program cat is trying to tell you about a problem
the problem is that there is no file named >
Indeed, > is not a file. It's not intended as a file, at all. It's a shell operator to redirect output.
You need to use ProcessBuilder to redirect:
ProcessBuilder builder = new ProcessBuilder("cat", "b.jpg", "f1.zip");
builder.redirectOutput(new File("pic2.jpg"));
Process p = builder.start();
When you run a command it doesn't start a shell like bash unless you do this explicitly. This means you are running cat with four arguments b.jpg f1.zip > pic2.jpg The last two files names don't exist so you get an error.
What you are likely to have intended was the following.
String command = "sh -c 'cat b.jpg f1.zip > pic2.jpg'";
This will run sh which in sees > as a special character which redirects the output.
Because you need to start a shell (e.g. /bin/bash) which will execute your shell command, replace:
String command = "cat b.jpg f1.zip > pic2.jpg";
with
String command = "bash -c 'cat b.jpg f1.zip > pic2.jpg'";

How to update "history" by other program

On ubuntu server, I can press up arrow to show the last command line which I used, and we can modify it by history -r , for example
$>history
... some command here
...
$> history -r hello.file
$>cat hello.file
aa
$>history
... some command here
...
aa
Of course, when I press up arrow at this time, the command line will give me "aa",
So that, I want some program to help me to do that
my Java sample code is
Runtime r = Runtime.getRuntime();
Process p = r.exec("/bin/bash history -r hello.file");
p.waitFor();
BufferedReader b = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
while ((line = b.readLine()) != null) {
System.out.println(line);
}
b.close();
but it not work, and java didn't print any exception.
I also test by a simple bash file
my bash file:
#!/bin/bash
history -r hello.file
and my test follow is
$>history
... some command here
...
$>sh my_bash_file.sh
$>history
... some command here
...
it still not working...
How can I update the "history" by a program?
Is it impossible?

Executing shell script which contains a while loop from Java

I am having a critical trouble to execute a shell script which contains a while loop. Here is my shell script:
echo Here 1
sleep 0.05
echo Here 2
sleep 0.05
echo Here 3
ic=70
while [ $ic -ge 40 ]
do
#sleep 0.05
ic=$[$ic-1]
echo Here $ic
done
When I am executing the script normally from the terminal as /home/pi/tbe/testSleep.sh it is working. and printing all the echos.
Now I have written this java method to execute the file:
public static void main(String[] args) throws IOException, InterruptedException {
String command = "/home/pi/tbe/testSleep.sh";
System.out.println("Executing command: " + command);
Process process = new ProcessBuilder(command).start();
BufferedReader reader = new BufferedReader(new InputStreamReader(
process.getInputStream()));
String line = null;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
process.waitFor();
int exitValue = process.exitValue();
System.out.println("Command executed. Exit value: " + exitValue);
process.destroy();
}
And when I am executing it I can only see the following output:
Executing command: /home/pi/tbe/testSleep.sh
Here 1
Here 2
Here 3
Here $[70-1]
Command executed. Exit value: 0
This is really weird. Any pointer would be very helpful to me.
It seems that the shell executing the command is not same as that you are using to run the script on command line. Specify the shell as bash.
Add shebang in the script (as first line). It is always a good practice to be specific about the shell in the script
#!/bin/bash
You could also specify the shell you want to use for the shell script
String[] command = {"/bin/bash", "/home/pi/tbe/testSleep.sh"};
I ran your script in Ubuntu:
$ sh script.sh
Here 1
Here 2
Here 3
Here $[70-1]
script.sh: 8: [: Illegal number: $[70-1]
Apparently $[70-1] is not being evaluated but simply treated as a literal...
I saw the comments after I saved. They are correct. Using bash (I was lazy) gives the correct results.

Java: Run multiple shell commands?

OK. I've been looking everywhere on how to execute multiple commands on a single command prompt from java. What i need to do is this, but not in command line, in code.
Execute:
cd C:/Android/SDK/platform-tools
adb install superuser.apk
..Basically i want to run adb commands from a program!!! Here is my java code so far:
MainProgram.java
public class MainProgram {
public static void main(String[] args) {
CMD shell = new CMD();
shell.execute("cmd /K cd C:/Android/SDK/platform-tools"); //command 1
shell.execute("cmd /C adb install vending.apk"); // command 2
}
}
CMD.java
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class CMD {
CMD() {
}
// THIS METHOD IS WHERE THE PROBLEM IS
void execute(String command) {
try
{
Process p = Runtime.getRuntime().exec(command);
BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
// read the output from the command
String s = null;
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
while ((s = stdError.readLine()) != null) {
System.out.println(s);
}
}
catch(Exception e){
e.printStackTrace();
}
}
}
So what happens is...i can run the first command, but that cmd terminates and when i execute the 2nd command, a new cmd is created, hence i get an error because im not in the right directory. I tried a single string command "cmd /C cd C:/blablabla /C adb remount", but that just froze up...
Essentially, command 1 is executed and terminated, then command 2 is executed and terminated. I want it to be like this: command 1 executed, command 2 executed, terminated.
Basically i'm asking how can i run both of these commands in a row on a single command prompt???
My final target is to have a JFrame with a bunch of buttons which execute different adb commands when clicked on.
Easiest way is to make a batch file then call that from program
of course you could just say
C:/Android/SDK/platform-tools/adb install superuser.apk
there's no need to cd to a file if you name it directly
although what you are looking for is already made in ddms.bat which provides a complete visual link to adb
Create file as something.bat and set the contents to:
cd C:/Android/SDK/platform-tools
adb install superuser.apk
Then call:
Process p = Runtime.getRuntime().exec("something.bat");
all commands in the bat file are executed.

Categories

Resources