为什么我会收到 IOException:“无法 运行 程序 ./shellScript.sh 错误 = 2,Java 中没有这样的文件或目录?

Why am I getting IOException : "Cannot run program ./shellScript.sh error = 2, No such file or directory in Java?

以下 Main.java 代码只是尝试模拟以下 linux 命令:

cd /dir1/dir2
./shellScript.sh

仅当可执行文件 Main.jar 位于 /dir1/dir2 之内而不是 /dir1/dir2 之外时,下面的程序才有效。我如何修改下面的程序,以便 Main.jar 可以位于文件系统的任何位置?

public class Main {

    public static String runCmdLineProcess(String commandStr){
        String returnVal = "";
        Runtime r = Runtime.getRuntime();
        
        try {
            Process p = r.exec(commandStr);
            BufferedReader b = new BufferedReader(new InputStreamReader(p.getInputStream()));
            String line = ""; 
            
            while ((line = b.readLine()) != null){
                returnVal += line + "\n";
            }

        }
        catch(IOException ex){
            ex.printStackTrace();
        }
        
        return returnVal;
    }

    public static void runProcessBuilder(String scriptPath){

        String[] cmd = {scriptPath};
        try {
            runCmdLineProcess("cd /dir1/dir2");
            Runtime.getRuntime().exec(cmd);
        }
        catch (IOException ex){
            ex.printStackTrace();
        }
    }
    
    public static void main(String[] args){
        runProcessBuilder("./shellScript.sh"); // <-- works if I run from inside "/dir1/dir2".  
                                               //But if I'm outside "dir2", get an error message 
                                               // saying "Cannot run program "./shellScript.sh": error = 2, No such file or directory
    }

}

您应该使用 ProcessBuilder 启动或 exec 的重载之一。您需要指定脚本的路径名,并将与当前目录相同的路径名传递给 运行 中的脚本:

File pwd = new File("/dir1/dir2");
String shell = new File(pwd, "shellScript.sh").toString();

ProcessBuilder pb = new ProcessBuilder(shell);
// No STDERR => merge to STDOUT - or call redirectError(File)
pb.redirectErrorStream(true);
// Set CWD for the script
pb.directory(pwd);

Process p = pb.start();

// Move STDOUT to the output stream (or original code to save as String)
try(var stdo = p.getInputStream()) {
    stdo.transferTo(stdout);
}

int rc = p.waitFor();