Problems encountered by java when executing system commands using Runtime

  • 2021-12-09 08:45:02
  • OfStack

Directory Problems Encountered in Executing System Commands Using Runtime Parameter Meaning the following is an example of implementation code java Runtime. exec () execution

Problems encountered in executing system commands using Runtime

java execution system command tool, Runtime. getRuntime (). exec (), this tool inside the pit is still quite a lot, most of the network has been analyzed, I met a not found in the network.

First of all, if there are spaces, tab, line feeds and carriage returns in the contents of parameters in command, the execution will fail, for example, grep "abc def"-r-n./This is because exec method uses StringTokenizer to divide command.

Parameter meaning

command : The command to be executed. envp Set the environment variable, the value is: environment variable name = environment variable value, for example JAVA_HOEM=/usr/lib/java1.8 dir Set the directory where the command executes

    public Process exec(String command, String[] envp, File dir)
        throws IOException {
        if (command.length() == 0)
            throw new IllegalArgumentException("Empty command");
 
        StringTokenizer st = new StringTokenizer(command);
        String[] cmdarray = new String[st.countTokens()];
        for (int i = 0; st.hasMoreTokens(); i++)
            cmdarray[i] = st.nextToken();
        return exec(cmdarray, envp, dir);
    }

In order to solve this problem, I wrote a class that can customize separators.

The second exec in this class can customize the delimiter, but there is also one thing to note

If the separator is " & & "The command to execute reads as follows: grep & & "abc & & def" & & -r & & -n & & ./Execution will also report errors, thinking that there is a space behind grep. It will take grep plus spaces as a whole and execute them as a command, and the command will not be found. However, if you don't pay attention to the error log, it is easy to ignore this space, and you can only be upset. So the correct way is to delete all the default delimiters and just use your own delimiters.

Here's the implementation code


import java.io.File;
import java.io.IOException;
import java.util.StringTokenizer; 
public class GxExec {
    private static GxExec gxExec = new GxExec(); 
    public static GxExec getGxExec() {
        return gxExec;
    }
 
    private GxExec() {} 
    public Process exec(String[] cmdarray, String[] envp, File dir)
            throws IOException {
        return new ProcessBuilder(cmdarray)
                .start();
    }
 
    public Process exec(String command, String delim)
        throws IOException {
        if (command.length() == 0) {
            throw new IllegalArgumentException("Empty command");
        }
 
        StringTokenizer st = new StringTokenizer(command, delim);
        String[] cmdarray = new String[st.countTokens()];
        for (int i = 0; st.hasMoreTokens(); i++) {
            cmdarray[i] = st.nextToken();
            System.out.println(cmdarray[i]);
        }
        return exec(cmdarray, null, null);
    } 
}

java Runtime. exec () execution

Runtime.exec() Is not equivalent to directly executing the command line command! Runtime.exec() Very limited, for some commands can not be directly command line content as String parameters to exec ().

Such as redirect commands.

For example


javap -l xxx > output.txt

In this case, the second overload of exec is used, that is, the input parameter is String []:


Process p = Runtime.getRuntime().exec(new String[]{"/bin/sh","-c","javap -l xxx > output.txt"});
rm -rf name*
Process p = Runtime.getRuntime().exec(new String[]{"/bin/sh","-c","rm -rf name*"});

Related articles: