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!
Related
Hello I am trying to push a docker image via shell command programming to AWS EC2 Container Service. But I am having trouble doing that and I am getting the following error messages:
error getting credentials - err: exec: "docker-credential-osxkeychain": executable file not found in $PATH, out: ``
no basic auth credentials
This error message is returned from my java class. If I start the shell script form the terminal i am having no problems only if I start it form my java class. I created an config.js file an added osxkeychain to it because i thought this might save the problem.
This is my Dockerfile:
FROM java:7
COPY . /Users/betzenben/Desktop/OGC/Projects/Getting_started/Docker/Directory
WORKDIR /Users/betzenben/Desktop/OGC/Projects/Getting_started/Docker/Directory
RUN javac Time_app.java
CMD ["java", "Time_app"]
Run : ~/Users/betzenben/Desktop/OGC/Projects/Getting_started/Docker/Directory/config.json
And this my config.json file
{
"apps": [
{
"credsStore": "osxkeychain"
}
]
}
And just in case it is needed my shell script code and my java class that calls the shell script.
#!/bin/sh
echo “test1”
getLoginKey="/usr/local/bin/"
getLoginKey+="$(/usr/local/bin/aws ecr get-login --no-include-email --region us-west-2)"
echo “test2”
echo "${getLoginKey}"
executeLoginKey="$(eval $getLoginKey)"
echo “test3”
sleep 2
echo "${executeLoginKey}"
tagImage="$(/usr/local/bin/docker tag time_app:latest .....id......dkr.ecr.us-west-2.amazonaws.com/time_a:latest)"
pushImage="$(/usr/local/bin/docker push .....id.......dkr.ecr.us-west-2.amazonaws.com/time_a:latest)"
wait
echo “test4”
sleep 5
echo "${pushImage}"
echo "Image Pushed"
Java Code:
import java.io.*;
public class Main {
public static void main(String[] args) throws InterruptedException, IOException {
Process p1 = Runtime.getRuntime().exec("chmod +x /Users/betzenben/Desktop/tag_push_image_AWS.sh");
BufferedReader stdInput1 = new BufferedReader(new InputStreamReader(p1.getInputStream()));
BufferedReader stdError1 = new BufferedReader(new InputStreamReader(p1.getErrorStream()));
System.out.println("STDOUT:\n");
String s1 = null;
while ((s1 = stdInput1.readLine()) != null) {
System.out.println(s1);
}
System.out.println("STDERR:\n");
while ((s1 = stdError1.readLine()) != null) {
System.out.println(s1);
}
Process p = Runtime.getRuntime().exec("/Users/betzenben/Desktop/tag_push_image_AWS.sh");
BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
System.out.println("STDOUT:\n");
String s = null;
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
System.out.println("STDERR:\n");
while ((s = stdError.readLine()) != null) {
System.out.println(s);
}
}
}
In your tag_push_image_AWS.sh file change
#!/bin/sh
to
#!/bin/bash
If that doesn't work then try below code in java
Runtime.getRuntime().exec(new String[]{"/bin/bash","-lc", "/Users/betzenben/Desktop/tag_push_image_AWS.sh"});
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 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.
I have a shell script which is sending output to console
ID=$PPID
echo the process id of the parent of this script is $ID
#fetch the parent of the program which executed this shell
read PID < <(exec ps -o ppid= "$ID")
echo the grand parent id of the script is $PID
read GPID < <(exec ps -o ppid= "$PID")
echo the grand parent id of the script is $GPID
while read -u 4 P; do
top -c -n 1 -p "$P"
done 4< <(exec pgrep -P "$PID") >&1
I am calling this script from java program and trying to display the output on console but only the output of echo is appearing. The output of top command is not appearing on the java console.
Here is my java program
import java.io.BufferedReader;
public class InformationFetcher {
public InformationFetcher() {
}
public static void main(String[] args) {
InformationFetcher informationFetcher = new InformationFetcher();
try {
Process process = Runtime.getRuntime().exec(
informationFetcher.getFilePath());
InputStream in = process.getInputStream();
printInputStream(in);
} catch (IOException e) {
e.printStackTrace();
}
}
private static void printInputStream(InputStream in) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
StringBuffer outBuffer = new StringBuffer();
String newLine = System.getProperty("line.separator");
String line;
while ((line = reader.readLine()) != null) {
outBuffer.append(line);
outBuffer.append(newLine);
}
System.out.println(outBuffer.toString());
}
public String getFilePath() {
return this.getClass().getResource("/idFetcher.sh").getPath();
}
}
output is
the process id of the parent of this script is 3721
the grand parent id of the script is 3241
the grand parent id of the script is 3240
but it should also display output of top command. Any help would be greatly appreciated.
I'm not quite sure about that how top outputs, but it seems that top doesn't send its result to STDOUT in a normal way.
However, if you want top to send its result to STDOUT in a normal way, give it the -b option:
top -b -n 1
# -b means in batch mode, which outputs to `STDOUT` normally
I got stuck while trying to run bfgminer.exe -o bla.bla.com -u <nick> -p <passwd> -S auto -d all
I tried a number of ways to run this executable, but I can't get it to work:
public static void runCmd(){
try{
ProcessBuilder builder = new ProcessBuilder("cmd.exe","/c", "cd \"C:\\Users\\pawisoon\\bfgminer-3.10.0-win64\" && bfgminer.exe -o bla.bla.com -u <user> -p
<pswd> -S auto -d all");
builder.redirectErrorStream(true);
Process pd = builder.start();
BufferedReader r = new BufferedReader(new InputStreamReader(pd.getInputStream()));
String line;
while (true) {
line = r.readLine();
if (line == null) { break; }
System.out.println(line);
}
}
catch(IOException e){
}
}
This is what I got from console in Eclipse:
'bfgminer.exe' is not recognized as an internal or external command,
operable program or batch file.
Please help me how to solve this problem :/
Thanks a lot for your answers ! I combined your advises and it worked. Here is code :
public static void runCmd(){
File f = new File("C:\\Users\\pawisoon\\bfgminer-3.10.0-win64");
try{
ProcessBuilder builder = new ProcessBuilder("cmd.exe","/c","start","bfgminer.exe", "-o", "bla.bala.com", "-u", "user", "-p", "lelelel", "-S", "auto", "-d", "all");
builder.directory(f);
builder.redirectErrorStream(true);
Process pd = builder.start();
BufferedReader r = new BufferedReader(new InputStreamReader(pd.getInputStream()));
String line;
while (true) {
line = r.readLine();
if (line == null) { break; }
System.out.println(line);
}
}
catch(IOException e){
}
}
From what I see, you try to execute
cd C:\Users\pawisoon\bfgminer-3.10.0-win64\
And then
bfgminer.exe -o bla.bla.com -u -p -S auto -d all
because I imagine bfgminer.exe is in the suppposed actual repertory (C:\Users\pawisoon\bfgminer-3.10.0-win64)
But actually I'm not sure your two cmd commands are correctly executed (I mean: I'm not sure the repertory is kept as a reference for the execution of the second command)
So why don't just try to execute
C:\Users\pawisoon\bfgminer-3.10.0-win64\bfgminer.exe -o bla.bla.com -u -p -S auto -d all
(no cd and full path to the executable)
Or check out #ginz comment and try to launch the executable directly (not using cmd) if you don't especially want to use cmd.exe