开发者

Run shell command from jar?

开发者 https://www.devze.com 2023-02-03 03:21 出处:网络
The usual way to call a shell command from java is something like that: Process process = Runtime.getRuntime().exec(command);

The usual way to call a shell command from java is something like that:

Process process = Runtime.getRuntime().exec(command);

and works usually fine. But now I've exported my project to an executable jar file and callig shell commands doesn't work any more. Are there any explanations, solutions or workarounds for t开发者_StackOverflow社区his problem?

phineas

--

edit:

  • even keyboard interrupts (ctrl+c; ctrl+d) aren't recognized.

  • terminal input won't work after killing java

--

Smallest programm:

import java.io.BufferedWriter;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.IOException;

public class Test {
    public static String fileName = "";

    /** test if you can open a 7z archive file with a given password */
    public static boolean test(String password)
        throws IOException, InterruptedException {
        String command = "7z l "+fileName;

        Process process = Runtime.getRuntime().exec(command);

        OutputStream out = process.getOutputStream();
        OutputStreamWriter w = new OutputStreamWriter(out);
        BufferedWriter writer = new BufferedWriter(w);
        writer.write(password+"\n");
        writer.close();
        w.close();
        out.close();

        if(process.waitFor() == 0) {
            return true;
        }
        else {
            return false;
        }
    }

    public static void main(String[] args) throws IOException, InterruptedException {
        fileName = args[0];
        test(args[1]);
    }
}


If you run your test program and use ps or the task manager you will notice that 7z is running. Your issue is that you are not consuming the output of the Process. So 7z is quickly blocked trying to output your archive's contents.

If you add just before the process.waitFor() the following lines you'll get a working program:

    InputStream in = process.getInputStream();
    byte[] buf = new byte[256];
    while (true) {
        int c = in.read(buf);
        if (c == -1)
            break;
        System.out.println(new String(buf));
    }

However this will only consume the process stdout you need to do the same with process.getErrorStream(). You may find it easier to use ProcessBuilder to launch your process as it allows you to merge the stderr and stdout streams.


You should read this excellent JavaWorld article on the pitfalls of running external processes from Java.


I would guess that your issue is with the base path from which the command is executed. There is a way to set it explicitly when invoking exec.

0

精彩评论

暂无评论...
验证码 换一张
取 消