1. In Linux systems, there is no / c and / k, only one / bin/bash -c it and direct / The difference between bin/bash is that the "- c" command allows bash to execute a string as a complete command, which can extend the influence of sudo to the whole command.
As you can see, / bin/bash -c Followed by command , and / bin/bash Followed by Script to execute.
2. Source code analysis of Java executing Linux commands:
Start directly from the start() method of the ProcessBuilder object. The start() method of the ProcessBuilder object returns processimpl.start (cmdarray, environment, dir, redirects, redirecterrorstream) (the same as the windows system). The ProcessImpl.start() method returns new UNIXProcess (tocstring (cmdarray [0]), argblock, args.length, envblock, Envc [0], tocstring (DIR) , std_fds, redirecterrorstream), you can see that the execution of the command finally returns a UNIXProcess object. The constructor defined by the UNIXProcess class is as follows:
UNIXProcess(final byte[] prog, final byte[] argBlock, final int argc, final byte[] envBlock, final int envc, final byte[] dir, final int[] fds, final boolean redirectErrorStream) throws IOException { pid = forkAndExec(launchMechanism.ordinal() + 1, helperpath, prog, argBlock, argc, envBlock, envc, dir, fds, redirectErrorStream); try { doPrivileged((PrivilegedExceptionAction<Void>) () -> { initStreams(fds); return null; }); } catch (PrivilegedActionException ex) { throw (IOException) ex.getException(); } }
In the constructor of UNIXProcess, use the forkAndExec() method to create a process and return the pid of the process:
Create a process. according to mode Flag, which is accomplished through one of the following mechanisms: 1 - fork(2) and exec(2) 2 - posix_spawn(3P) 3 - vfork(2) and exec(2) (4 - clone(2) and exec(2) - obsolete and currently disabled in native code) Formal parameters: fds – An array of three file descriptors. Indexes 0, 1, and 2 correspond to standard input, standard output, and standard error, respectively. When entering, the value -1 Represents the creation of a pipeline to connect child processes and parent processes. When outputting, non -1 The value of is the parent pipe corresponding to the created pipe fd. The elements of this array are -1 Not if and only if it is output-1 Time. Return value: Of child processes pid private native int forkAndExec(int mode, byte[] helperpath, byte[] prog, byte[] argBlock, int argc, byte[] envBlock, int envc, byte[] dir, int[] fds, boolean redirectErrorStream)
The fork and exec process under Linux consumes a lot of resources. Here I will just briefly say:
As like as two peas, the parent process generates a identical sub process through fork, and the copied sub processes are executed in exec mode to become the process of a sub process.
Picture from Process control -- fork and exec, system, wait Kramer and matrix blog Park , to fully understand the fork and exec process, this blog post is very detailed.
3. Since the fork and exec creation process consumes a lot of resources, it is not recommended to create a process by executing one command. Will there be a windows like problem when opening a process to execute multiple commands on Linux? The answer is no!!! (ecstatic!!!)
In the Linux system, although the process.getInputStream().read(bytes) method is still blocked in the dead loop reading, the data results generated by executing multiple linux commands are clearly divided and end with - 1. Therefore, we can distinguish and analyze the execution results well. If they all end with - 1, then we use read() The method does not need to use an endless loop. The demonstration is as follows:
try { Process process = new ProcessBuilder() .command("/bin/bash") .start(); PrintWriter printWriter = new PrintWriter(new BufferedWriter(new OutputStreamWriter(process.getOutputStream())), true); printWriter.println("ls"); printWriter.println("ls -l"); byte[] bytes = new byte[1024]; //Read the execution result of the first command int len = process.getInputStream().read(bytes); System.out.println(new String(bytes, 0, len)); //Read the execution result of the second command len = process.getInputStream().read(bytes); System.out.println(new String(bytes, 0, len)); //Blocking, waiting for new data to be generated len = process.getInputStream().read(bytes); } catch (IOException e) { e.printStackTrace(); }
Although incomplete command execution may lead to Java process blocking, or incomplete stream reading results (these are unavoidable), the problem of command execution and the division of command execution results have been perfectly solved. Therefore, it is feasible to use java to execute system commands and analyze the results. So far, the theoretical exploration is over, The next article is direct practice.