Hot questions for Using Ubuntu in shell

Question:

I am trying to execute redirection in shell using java, but I am getting an empty file1.txt for the command: ls -all > file1.txt. Although ls -all is executed properly.

commandLine is of type String and has the command that I would want to execute. for example String commandLine = "ls -all";

Code Snippet(This is the relevant section of the code) :

   StringBuilder output = new StringBuilder();
   Runtime runtime = Runtime.getRuntime();
    Process process = runtime.exec(new String[]{"/bin/sh", "-c", commandLine});
    process.waitFor();

    try {
         BufferedReader reader = 
           new BufferedReader(new InputStreamReader(process.getInputStream()));

          String line;          
          line = "";
          while ((line = reader.readLine())!= null) {
              output.append(line);
              output.append("\n");
          }
    } 
    catch(Exception ex) {
      ex.printStackTrace();
    } 
    finally {
      process.destroy();
    }

Finally I am processing the output from the instance output. Also, I want to execute the command similar to curl -v http://www.centos.org > /dev/null but this gives me an empty response too !


Answer:

Short answer

You are reading stdout, which is empty because you redirected stdout to /dev/null. Use getErrorStream() instead of getInputStream() to get stderr.

stdout and stderr

There are 2 output streams of every process, stdout and stderr. In the case of the mentioned curl -v http://www.centos.org, the 2 output streams would be the following streams:

stdout:

<html>
<head><title>301 Moved Permanently</title></head>
<body bgcolor="white">
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx/1.6.3</center>
</body>
</html>

stderr:

* Rebuilt URL to: http://www.centos.org/
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0*   Trying 85.12.30.226...
* Connected to www.centos.org (85.12.30.226) port 80 (#0)
> GET / HTTP/1.1
> Host: www.centos.org
> User-Agent: curl/7.43.0
> Accept: */*
> 
< HTTP/1.1 301 Moved Permanently
< Server: nginx/1.6.3
< Date: Thu, 19 May 2016 15:31:03 GMT
< Content-Type: text/html
< Content-Length: 184
< Connection: keep-alive
< Location: https://www.centos.org/
< 
{ [184 bytes data]
100   184  100   184    0     0   1184      0 --:--:-- --:--:-- --:--:--  1187
* Connection #0 to host www.centos.org left intact

The > operator will redirect only stdout, but stderr will be untouched.

Execution in the terminal

In terminals you usually see stdout and stderr mixed. So if you execute curl -v http://www.centos.org > /dev/null, then stdout will be redirected to /dev/null, but you will still see the output of stderr. That's what you observe, when you say that "running the same command on bash gives [...] an output."

Execution from Java

Execution of a command from Java, on the other hand, will keep the two streams separated. The stream stdout can be obtained using process.getInputStream(), and stderr can be obtained using process.getErrorStream().

You are using the former (stdout), but since stdout is redirected to /dev/null in your example (curl -v http://www.centos.org), it doesn't come as a surprise that you don't see any output.

The only output you could obtain would be stderr. For that you would have to replace process.getInputStream() by process.getErrorStream().

Empty file1.txt

You are stating in the comments that the file file1.txt is empty after executing some command like this ls -all > file1.txt from Java.

The most likely reason for this is that the execution of ls actually failed, but you don't see the error message because it is printed to stderr - which you never read. You state that the same command works fine in the terminal, but execution environments are different (different environment variables, different working directory, etc.), which can make the same command fail. So read stderr to get the error message.

Another possible reason for an empty file1.txt is that you check a different file because the working directory is unknown to you. Happened to me more than once that I checked the wrong file! Check the timestamp to make sure that it's the correct file.

Question:


Answer:

Using

java -jar app.jar /somearg /anotherarg

instead of

myapp /somearg /anotherarg

saves you only 2 words, so not that much. Anyway if you run your application frequently it is a good idea to provide an alias. If you are using bash shell (echo $SHELL shows something like /bin/bash) then here's the command you can paste in your terminal:

alias myapp="java -jar /path/to/your/app/app.jar"

After that you can use

myapp /somearg /anotherarg

It is important to provide the whole path to your app.jar file if you run it from different locations. Also if you want that your alias is permament (i.e. it is always after you log in) just add the same line at the end of ~/.bashrc file, using for example:

pico ~/.bashrc

PS. You don't need slash symbol to provide parameters. In unix systems it is more common to use "-" to set argument options.

PSS. Unix systems are case sensitive and it is typical that command line programs are all written in lowercase.

Question:

I'm going to execute a shell command from java and i need to pass arguments to the output stream while executing the command..

following is the shell command

./darknet detect cfg/yolo-voc.2.0.cfg backup/yolo-voc_20000.weights

when executing this command it is yielding for the path of the image file in the terminal i can provide the path of the image as follows

Loading weights from backup/yolo-voc_21000.weights...Done!
Enter Image Path:

when executing from the terminal i can provide the path there.

I managed to execute this command withing the java process and also i can get an output when i provide an image uri with the command. here is the code

     public static void execCommand(String command) {
    try {

        Process proc = Runtime.getRuntime().exec(command);
        // Read the output
        BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream()));

        String line = "";
         //reader.readLine();
        while ((line = reader.readLine()) != null) {
            System.out.print(line + "\n");
            s.add(line);
        }
//            proc.waitFor();
    } catch (IOException e) {
        System.out.println("exception thrown: " + e.getMessage());
    } 
}

but what I want is provide the image path at the runtime not beginning of the execution of the command.. tried with writing to the output stream as below still no luck

public static void execCommand(String command) {
    try {
        Process proc = Runtime.getRuntime().exec(command);
        // Read the output
        BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream()));

        String line = "";
                    BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(proc.getOutputStream()));
             writer.append("data/test2.jpg");
          writer.newLine();
         //reader.readLine();
        while ((line = reader.readLine()) != null) {
            System.out.print(line + "\n");
            s.add(line);
        }
//            proc.waitFor();
    } catch (IOException e) {
        System.out.println("exception thrown: " + e.getMessage());
    } 
}

Answer:

You need to call writer.flush() in order to actually output something to the underlining InputStream

Therefore your code should look like:

public static void execCommand(String command) {
    try {
        Process proc = Runtime.getRuntime().exec(command);

        // Read the output
        BufferedReader reader = new BufferedReader(new 
            InputStreamReader(proc.getInputStream()));

        String line = "";
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(proc.getOutputStream()));
        writer.append("data/test2.jpg");
        writer.newLine();
        // **** add flush here ****
        writer.flush();
        // and remember to close your resource too
        writer.close();
        //reader.readLine();
        while ((line = reader.readLine()) != null) {
            System.out.print(line + "\n");
            s.add(line);
        }
        // ***** close your reader also ****
        reader.close();
        //            proc.waitFor();
    } catch (IOException e) {
        System.out.println("exception thrown: " + e.getMessage());
    } 
}

Question:

My requirement is to start a c++ application which runs some shell scripts in a certain folder. the c++ app is started with java. The scripts its trying to run have being given chmod 777 access as well as the jar is started with sudo and the util is started with sudo from within the jar.

My problem is the scripts fail to run soemtimes saying script failed to run returned: 512 (the script is just an echo) I am running all command line function in java using getRuntime.exec (I tried process builder too) TLDR: jar starts c++ app c++ app tries to run shell script script fails sometimes Anyone got any suggestions or faces similar situation ?

EDIT 1 I should also mention that the scripts are being downloaded first via java. and then only passed on to the c++ app. The c++ utility works fine with scripts which are already there.I am using apache http client


Answer:

I Managed To Solve this there was a output stream that was still open while the c++ app was trying to access the scripts.

Question:

I'm trying to do it like this:

file_name=$1
#Clear log file
echo > nohup.out 
for PID in $(ps aux | grep service_name | awk {'print $2'}); do
    kill -9 $PID;
done
echo "Killed old process"
nohup java -Xms256m -Xmx256m -XX:MaxMetaspaceSize=256m -jar $file_name &
echo "Started new process"

But it's just printing "Killed" and doesn't start it again. If I do all this stuff separately - it's working, but for all together - not...

Допоможіть хто зможе...


Answer:

The script from which you execute it, does it contain "service_name" in its name? Then it obviously fulfills the criteria for begin killed by your for loop and commits suicide.

If it does not, then still the grep service_name remains which fulfills the kill criteria (has service_name in its cmd line) - for fixed strings in grep I usually write them grep "s[e]rvice_name", other prefer to put another |grep -v grep into the pipe before the awk

Question:


Answer:

The answer for 3) should be yes in reference to this answer.

import java.io.*;
public class Test {

        public static void main(String[] args) throws Exception {
                try {
                        String target = new String("Shell script");
                        Runtime rt = Runtime.getRuntime();
                        Process proc = rt.exec(target);
                        proc.waitFor();
                        StringBuffer output = new StringBuffer();
                        BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream()));
                        String line = "";                       
                        while ((line = reader.readLine())!= null) {
                                output.append(line + "\n");
                        }
                        System.out.println("### " + output);
                } catch (Throwable t) {
                        t.printStackTrace();
                }
        }
}

Question:


Answer:

this is a simple sceranio like this. i run my program in D: and i want to go to a folder in C:\Users\erdemk\Desktop\directory and run a dir command on it. you can use this code:

public static void main(String[] args) throws IOException {
  ProcessBuilder builder = new ProcessBuilder("cmd.exe", "/c", "c: && cd \"C:\\Users\\erdemk\\Desktop\\directory\" && dir");
  builder.redirectErrorStream(true);
  Process p = builder.start();
    BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream()));
    String line;
    while (true) {
        line = r.readLine();
        if (line == null) { break; }
        System.out.println(line);
    }
}