【问题标题】:bash unix processbuilder from java not running来自java的bash unix processbuilder没有运行
【发布时间】:2013-02-05 08:44:02
【问题描述】:

我想从我的 Java servlet 中执行一个简单的 Unix 命令:我需要做的是一个简单的回显写入文件,如下所示:

echo HELLO > myfile.txt

我在我的 servlet 中所做的是:

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ServletAutorecovery extends HttpServlet {
    protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        try {
            ProcessBuilder pb = new ProcessBuilder("/usr/bin/bash", "-c", "echo HELLO > ../webapps/test/myfile.txt");
            pb.start();
        } finally { 
        out.close();
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        processRequest(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        processRequest(request, response);
    }
}

我的问题是:这个代码部分没有给我任何错误,但没有任何反应。在我执行了我的 servlet 之后,文件并没有被创建,当然,里面也没有写任何东西。

我做错了什么?

EDIT1:添加了 pb 命令的完整路径。

EDIT2:bash 在路径 /usr/bin/bash 中,100% 确定。

EDIT3:添加了 SSCCE。

【问题讨论】:

  • 您希望 myfile.txt 在哪里?你在哪里看/搜索?尝试将文件写入您知道的路径。例如 /tmp/myfile.txt
  • 我其实是写在我的项目文件夹../webapps/test/myfile.txt.
  • 您尝试过 Runtime 吗? Runtime.getRuntime().exec("echo HELLO > myfile.txt");
  • 试过这个:ProcessBuilder pb = new ProcessBuilder("bash", "-c", "echo HELLO > myfile.txt");
  • 如需尽快获得更好的帮助,请发帖SSCCE

标签: java bash unix servlets processbuilder


【解决方案1】:

首先,你确定 bash 肯定在 /usr/bin 吗?其次,您可能需要告诉 ProcessBuilder 在运行进程时它应该使用哪个目录作为 cwd,否则它将尝试在 servlet 容器的当前目录中创建 myfile.txt,通常是在您没有写入的地方使用权。第三,当你从java运行一个进程时,进程的输出通过进程对象上的输入流传递回java,它不会直接进入stdout,所以你需要读取流来查看结果

ProcessBuilder pb = new ProcessBuilder("/usr/bin/bash", "-c", "echo HELLO > myfile.txt");
pb.directory(...);
pb.redirectErrorStream(true);
Process p = pb.start();
IOUtils.copy(p.getInputStream(), System.out);
p.waitFor();

【讨论】:

  • 对不起,我应该在pb.directory(...) 写什么目录?输出之一,我希望myfile.txt 在哪里?我也有使用IOUtils 的问题,即使我添加了import java.lang.Object;
  • .. 4) 您也可以将"echo HELLO > myfile.txt" 分解为单独的参数。 5) 我听说通过 Java 使用管道时,管道的工作方式不同。
  • @abierto 您希望成为 bash 进程的当前目录的目录,这是您重定向中的相对路径将被解析的目录。 IOUtils 是 Apache commons-io 的一部分,我将其用作将输入流复制到输出流的便捷方式,但如果您愿意,也可以手动完成。
  • @AndrewThompson 在这种情况下不,您确实希望将整个 echo-and-redirect 作为一个参数,因为它旨在由 bash 解释,而不是由 Java。如果没有 bash,您将无法使用 > 进行重定向,但在 Java 7 中,至少您可以使用 7 中添加到 ProcessBuilder 的新方法将输出直接发送到文件。
  • @IanRoberts 如果我使用 Tomcat 会怎样?有问题吗?
【解决方案2】:
String echo = "echo 'hello' > myfile.txt";
ProcessBuilder pb = new ProcessBuilder("/usr/bin/bash", "-c", echo);
pb.start();

【讨论】:

    【解决方案3】:

    检查您的错误处理;你可能在某个地方吞下了一个异常,因为/usr/bin 中没有bash,所以你得到一个“找不到文件”异常(或类似的)。

    改用"/bin/bash"。其余的应该可以工作。

    另请注意,在您部署应用程序后,相对路径将不起作用,因为它将与运行 Java VM 的进程相关,这不是您所期望、想要或无法使用的。向您的ServletContext 询问getRealPath() 的路径

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-10-04
      • 2010-09-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多