从 jar 运行 shell 命令?

发布于 2024-10-10 14:17:06 字数 1396 浏览 0 评论 0原文

从 java 调用 shell 命令的通常方法是这样的:

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

并且通常工作得很好。 但现在我已将项目导出到可执行 jar 文件,并且 callig shell 命令不再起作用。对于这个问题有任何解释、解决方案或解决方法吗?

phineas

--

编辑:

  • 甚至无法识别键盘中断(ctrl+c;ctrl+d)。

  • 杀死java后终端输入将不起作用

--

最小的程序:

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]);
    }
}

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 this 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]);
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

Spring初心 2024-10-17 14:17:06

如果您运行测试程序并使用 ps 或任务管理器,您会注意到 7z 正在运行。您的问题是您没有消耗流程的输出。因此,7z 试图输出存档内容时很快就会被阻止。

如果您在 process.waitFor() 之前添加以下几行,您将获得一个工作程序:

    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));
    }

但是,这只会消耗进程标准输出,您需要对 process.getErrorStream 执行相同的操作()。您可能会发现使用 ProcessBuilder 来启动进程更容易,因为它允许您合并 stderr 和 stdout 流。

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.

岛徒 2024-10-17 14:17:06

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

原谅我要高飞 2024-10-17 14:17:06

我猜您的问题在于执行命令的基本路径。有一种方法可以在调用 exec 时显式设置它。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文