Search code examples
javacoldfusionprocessbuildercfmlrailo

Execute shell commands with arguments with `java.lang.ProcessBuilder`


I have the following script that executes a shell command with Java's java.lang.ProcessBuilder that works ok if I don't use arguments:

<cfif IsDefined("FORM.cmd")>
  <cfif Server.OS.Name CONTAINS "Mac" or Server.OS.Name CONTAINS "Linux" or Server.OS.Name IS "UNIX">
    <cfset cmd = "sh -c #FORM.cmd#">
  <cfelseif Server.OS.Name CONTAINS "Windows">
    <cfset cmd = "cmd.exe /c #FORM.cmd#">
  <cfelse>
    <cfset cmd = "sh -c #FORM.cmd#">
  </cfif>

  <cfscript>
    str = htmleditformat(REReplace(cmd,"""","'","ALL"));
    exec = str.split(" ");
    pb = createObject("java","java.lang.ProcessBuilder").init(exec);
    pb.redirectErrorStream(true);
    proc = pb.start();
    proc.waitFor();
    isr = createObject("java","java.io.InputStreamReader").init(proc.getInputStream());
    br = createObject("java","java.io.BufferedReader").init(isr);
    line = br.readLine();
    while (isDefined("line")) {
     writeoutput(line & '<br>');
     line = br.readLine();
    }
    br.close();
    isr.close();
  </cfscript>
</cfif>

If my #FORM.cmd# is uname, the output is as I expect:

Linux

but if my #FORM.cmd# is uname -a the scripts executes only uname leaving outside the -a argument. So I thought I would use a java array to add arguments:

  <cfscript>
    args = createObject("java", "java.util.ArrayList").init();
    args.add("sh");
    args.add("-c");
    args.add("uname");
    args.add("-a");
    pb = createObject("java","java.lang.ProcessBuilder").init(args);
    pb.redirectErrorStream(true);
    proc = pb.start();
    proc.waitFor();
    isr = createObject("java","java.io.InputStreamReader").init(proc.getInputStream());
    br = createObject("java","java.io.BufferedReader").init(isr);
    line = br.readLine();
    while (isDefined("line")) {
     writeoutput(line & '<br>');
     line = br.readLine();
    }
    br.close();
    isr.close();
  </cfscript>

Same problem. What am I doing wrong?


Solution

  • "-a" is being passed in as an argument to sh, not to uname. You need to put "uname -a" within the same arg, ie:

    args.add("sh");
    args.add("-c");
    args.add("uname -a");
    

    If it helps clarify, to do this directly from the command line, you would want to type:

    sh -c "uname -a"