如何在调用(当前)Shell 中使用Java运行shell命令

huangapple go评论78阅读模式
英文:

How to run a shell command in the calling (current) shell with Java

问题

假设有类似这样的情况:

execInCurrentShell("cd /")
System.out.println("Ran command: cd /")

MyClassmain()函数中,

这样当我运行这个类时,我会cd/目录

user@comp [~] pwd
/Users/user
user@comp [~] java MyClass
Ran command: cd /
user@comp [/] pwd
/

通常运行Shell命令的方式是通过Runtime类:

Runtime.getRuntime().exec("cd /")

在这里行不通,因为它不会在当前的Shell中运行命令,而是在一个新的Shell中运行。

那么,一个实际工作的execInCurrentShell()函数会是什么样子呢?

英文:

Suppose something like this:

execInCurrentShell("cd /")
System.out.println("Ran command : cd /")

is in the main() function of MyClass

So that when I run the class, I cd into the / directory

user@comp [~] pwd
/Users/user
user@comp [~] java MyClass
Ran command : cd /
user@comp [/] pwd
/

The usual way to run shell commands, that is, through the Runtime class:

Runtime.getRuntime().exec("cd /")

Won't work here because it doesn't run the command in the current shell but in a new shell.

What would the execInCurrentShell() function (the one that actually works) look like?

答案1

得分: 1

你将无法运行影响当前调用Shell的命令,只能从Java作为子进程运行命令行bash/cmd,并按以下方式发送命令。我不建议使用这种方法:

String[] cmd = new String[] { "/bin/bash" }; // "CMD.EXE"
ProcessBuilder pb = new ProcessBuilder(cmd);

Path out = Path.of(cmd[0] + "-stdout.log");
Path err = Path.of(cmd[0] + "-stderr.log");
pb.redirectOutput(out.toFile());
pb.redirectError(err.toFile());

Process p = pb.start();
String lineSep = System.lineSeparator();

try (PrintStream stdin = new PrintStream(p.getOutputStream(), true)) {
    stdin.print("pwd");
    stdin.print(lineSep);
    stdin.print("cd ..");
    stdin.print(lineSep);
    stdin.print("pwd");
    stdin.print(lineSep);
}
p.waitFor();
System.out.println("OUTPUT:" + Files.readString(out));
System.out.println("ERROR WAS: " + Files.readString(err));

对于Windows上的CMD.EXE,这也适用(使用不同的命令)。要捕获每个命令的响应,您应该将pb.redirectOutput()的使用替换为使用pb.getInputStream()读取的代码,如果您确实需要逐行获取响应,而不是作为一个文件获取。

英文:

You won't be able to run commands that affect the current invoking shell, only to run command line bash/cmd as sub-process from Java and send them commands as follows. I would not recommend this approach:

String[] cmd = new String[] { "/bin/bash" }; // "CMD.EXE"
ProcessBuilder pb = new ProcessBuilder(cmd);

Path out = Path.of(cmd[0]+"-stdout.log");
Path err = Path.of(cmd[0]+"-stderr.log");
pb.redirectOutput(out.toFile());
pb.redirectError(err.toFile());

Process p = pb.start();
String lineSep = System.lineSeparator(); 

try(PrintStream stdin = new PrintStream(p.getOutputStream(), true))
{
    stdin.print("pwd");
    stdin.print(lineSep);
    stdin.print("cd ..");
    stdin.print(lineSep);
    stdin.print("pwd");
    stdin.print(lineSep);
};
p.waitFor();
System.out.println("OUTPUT:"+Files.readString(out));
System.out.println("ERROR WAS: "+Files.readString(err));

}

This also works for CMD.EXE on Windows (with different commands). To capture the response per command you should replace use of pb.redirectOutput() with code to read pb.getInputStream() if you really need the responses per line rather than as one file.

答案2

得分: -1

在Windows上,要从Java程序启动命令行 shell,你可以按照以下方式进行:

import java.io.IOException;

public class Command {
    public static void main(String[] args) {
        try {
            Runtime.getRuntime().exec("cmd.exe /c start");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在Linux上,你需要使用相同的方法。

英文:

On Windows to start a command shell from Java program, you can do it as follows:

import java.io.IOException;

public class Command {
    public static void main(String[] args) {
        try {
            Runtime.getRuntime().exec("cmd.exe /c start");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

You need to use the same approach for Linux.

huangapple
  • 本文由 发表于 2020年7月25日 17:09:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/63086504.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定