bash unix processbuilder from java not running

abierto picture abierto · Feb 5, 2013 · Viewed 15.8k times · Source

I want to execute a simple Unix command from my Java servlet: what I need to do is a simple echo write to file like this one:

echo HELLO > myfile.txt

What I'm doing in my servlet is:

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

My problem is: this code section is not giving me any errors, but nothing happens. After I executed my servlet, the file has not being created, and of course, nothing is written in it.

What am I doing wrong?

EDIT1: added full path to pb command.

EDIT2: bash is in the path /usr/bin/bash, 100% sure of it.

EDIT3: added SSCCE.

Answer

Ian Roberts picture Ian Roberts · Feb 5, 2013

First, are you sure bash is definitely at /usr/bin? Second, you probably need to tell the ProcessBuilder what directory it should use as the cwd when running the process, otherwise it will try and create myfile.txt in whatever is the current directory of the servlet container, typically somewhere you don't have write access. And thirdly, when you run a process from java the output of the process is passed back to java via input streams on the process object, it doesn't go straight to stdout, so you need to read the streams to see the result

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