通过Java无法运行source命令

5

从昨天开始,我一直在尝试使用JAVA在终端(MAC)上执行命令,但无论我做什么都不起作用。

我要执行以下2个命令,并在JAVA中获得输出结果。

source activate abc_env
python example.py

到目前为止,我已经尝试了以下方法,但没有任何输出。
String[] command = new String[] { "source activate abc_env", "python example.py"};
String result = executeCommands(command);

这是我的executeCommands方法

private static String executeCommands(String[] command) {

        StringBuffer output = new StringBuffer();

        Process p;
        try {
            for(int i=0; i< command.length;i++)
            {
                p = Runtime.getRuntime().exec(command[i]);
                p.waitFor();
                BufferedReader reader = 
                                new BufferedReader(new InputStreamReader(p.getInputStream()));

                String line = "";           
                while ((line = reader.readLine())!= null) {
                    output.append(line + "\n");
                }
                System.out.println("Error output: " + p.exitValue());
                System.out.println("Output:" + output);

            }
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("Here");
        }
        return output.toString();
    }

这给我带来了以下异常

无法运行程序“source”:错误=2,没有这样的文件或目录

我在网上搜索,人们说source不会像这样工作,我应该将命令更改为
String[] command = new String[] { "bash -c 'source activate abc_env'", "python example.py"};

现在,我没有收到异常,但是命令仍然无法正常工作,并且返回exitValue()为'2'

然后我尝试将命令作为脚本执行

#!/bin/bash
source activate abc_env
python example.py

当我将.sh文件读取为字符串并将其传递给命令时,会出现以下异常:
无法运行程序“#!/bin/bash”:错误=2,没有那个文件或目录
因此,我的问题是如何通过Java正确地运行源命令后跟python命令?我的最终目标是从Java执行一些python。
编辑1: 如果我尝试以下命令并打印输出流...
String[] command = {
                "/bin/bash",
                "-c",
                "source activate cvxpy_env"
        };

executeCommand(command));

输出流:

返回值:1

错误输出:/bin/bash:activate:没有这个文件或目录

如果我使用单引号将'source activate abc_env'括起来执行同样的命令,则会得到以下输出

返回值:127

错误输出:/bin/bash:source activate cvxpy_env:未找到命令

解决方案:

String[] command = {
                "/bin/bash",
                "-c",
                "source /Users/pc_name/my_python_library/bin/activate abc_env;python example.py"
        };

为了更加清晰明了,Linux中的"/Users/pc_name/my_python_library/bin/activate/"可以被翻译成Anaconda安装路径,例如:"/opt/anaconda/bin/activate"。因此,如果abc_env是您的环境名称,则可以使用以下命令: source /opt/anaconda/bin/activate abc_env - Ioannis Koumarelas
2个回答

4
根据 Javadoc,Runtime.exec(String) 方法将使用 StringTokenizer 将命令分解为命令参数列表,这可能会使您的命令被分解为:
bash
-c
'source
activate
abc_env'

显然这不是你想要的。你应该使用接受准备好的参数列表的Runtime.exec (String [])版本,将new String [] {"bash","-c","source activate abc_env"}传递给它。
现在,为了了解它为什么不起作用,你不仅应该从它的stdout读取,还应该从p.getErrorStream()读取stderr。只需打印出你所读到的内容,这将是一个很好的调试工具。
关于你的编辑问题。现在看起来它在Java和bash方面都运行良好。输出"activate: No such file or directory"可能是源命令成功运行的输出。只是source找不到activate文件。它在工作目录中吗?如果不是,你可能应该有"cd /wherever/your/files/are; source activate cvxpy_env"。哦,如果你的python脚本依赖于源命令具有的任何副作用,则可能必须在同一个实例中执行它:
String[] command = {
                "/bin/bash",
                "-c",
                "cd /wherever/your/files/are && source activate cvxpy_env && python example.py"
        };

或者更好的方法是将所有内容都打包成一个单独的shell脚本,然后只需使用 Runtime.exec("./my_script.sh") (不要忘记给它授予chmod +x权限)。

我尝试了你提到的事情,但我仍然有一个错误。我已经更新了我的问题,请查看EDIT1。 - Behroz Sikander
好的,非常感谢。我会尝试您的新答案并尽快更新您。现在要去开会了。 - Behroz Sikander
太好了,我搞定了。我只是包含了激活脚本的路径,它就正常工作了。谢谢。 - Behroz Sikander

1
尝试。
String[] command = {
                "/bin/bash",
                "-c",
                "source activate abc_env; " + "python example.py"
        };

我尝试了你提到的方法,但仍然出现错误。 - Behroz Sikander
@Behroz,您可能需要指定'activate'和'abc_env'脚本以及'example.py'的完整路径。错误提示无法找到该文件。 - Javide
/bin/bash <---- 这是我在 whereis 查询后得到的 - Behroz Sikander
String[] cmd = { "/bin/bash" , "-c", "cd /zookeeper/bin" + "./zkCli.sh"}; Runtime run = Runtime.getRuntime(); Process pr = run.exec(cmd); pr.waitFor();BufferedReader buf = new BufferedReader(new InputStreamReader(pr.getInputStream())); String line = ""; while ((line=buf.readLine())!=null) { System.out.println(line); }这段代码有什么问题? - aΨVaN

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接