1. Introduction
Sometimes when we run Java programs on Linux, we need to invoke some shell commands and scripts. The Runtime.getruntime (). Exec () method provides us with this functionality, and Runtime.getruntime () provides us with the following exec () methods:
In fact, Cmdarray and command are similar, and if there is no ENVP parameter or NULL in the parameter, the calling command will execute in the context of the current program execution, and if there is no dir parameter or set to NULL, the calling command will execute in the directory where the current program executes. Therefore, it is best to use absolute paths for files and scripts that are called to other directories. The meaning of each parameter:
- Cmdarray: An array containing the called command and its arguments.
- Command: A specified system command.
- ENVP: A string array in which the environment variable for each element is formatted as Name=value, or null if the child process should inherit the environment of the current process.
- Dir: The working directory of the child process, or null if the child process should inherit the working directory of the current process.
The attentive reader will find that the JVM will start a process in order to perform the invocation, so we can tell if the call operation is executed correctly by invoking the following method of the Process class:
Abstract
The export value of the process. By convention, 0 means normal termination; otherwise, it indicates an exception failure.
Also, when invoking some shell commands or scripts, there is a return value, so what if we capture these return values or outputs? To solve this problem, the Process class provides:
Abstract InputStream getInputStream () gets the input stream of the child process. It is best to buffer the input stream.
2. Call the shell command
To illustrate the problem, I'll just use the tar command to demonstrate. The TAR command is a packaged command that does not compress. At the same time, in order to check if the tar call is being executed properly, I will call the WAITFOR () method.
private void Callcmd (String tarname, String fileName, String ... workspace) {try {String cmd = "TAR-CF" + Tarname + "" + F ilename;// string[] cmd = {"Tar", "-CF", Tarname, fileName}; File dir = null;if (workspace[0]! = null) {dir = new File (workspace[0]); System.out.println (Workspace[0]);} Process = Runtime.getruntime (). EXEC (cmd, null, dir);// Process = Runtime.getruntime (). exec (cmd); int status = Process.waitfor (); if (status! = 0) {System.err.println ("Failed to call Shell's command and the return status ' is:" + statu s);}} catch (Exception e) {e.printstacktrace ();}}
Note: If you place the command in a string[], you must have each part of the command as an element in the string[], or the command is separated by a space character string[].
string[] cmd = {"Tar", "-CF", Tarname, filename};//rightstring[] cmd = {"TAR-CF", Tarname, Filename};//error
In order to illustrate the role of the Dir parameter, I specifically put the Java program and the directory to be packaged hive/in a different directory:
/root/workspace/eclipse/test/src/edu/wzm/callshell.java/root/experiment/hive
If I do not set dir or set Dir to null, then filename has to be a relative path, preferably an absolute path:
Call.callcmd ("/root/experiment/hive.tar", "/root/experiment/hive", null);//Orcall.callcmd ("/root/experiment/ Hive.tar ","/root/experiment/hive ");
If I set dir to point to the parent directory where hive is located, it would be much better:
Call.callcmd ("Hive.tar", "Hive", "/root/experiment/");
3. Invoking the shell script
Java calls the shell command and invokes the shell script in exactly the same operation. Here are a few other things I would describe:
- Passing parameters to the script;
- Capture the output of the call;
- The use of ENVP.
Passing parameters to the script is a simple operation, which simply adds the arguments to the string after the call command, or string[].
The capture call output information is also mentioned earlier with Process.getinputstream (). However, it is advisable to buffer the input stream:
BufferedReader input = new BufferedReader (New InputStreamReader (Process.getinputstream ()));
In addition, ENVP is a string[], and each element in string[] is in the form of: Name=value. such as: My Linux system does not have the following environment variables, but I write them in the Java code, as ENVP:
Val=2call=bash Shell
The shell script I want to invoke is:/root/experiment/test.sh.
#!/usr/bin/env bashargs=1if [$#-eq 1];thenargs=$1echo "The argument is: $args" Fiecho "This is a $call" start= ' date +%s ' s Leep 3send= ' Date +%s ' cost=$ ((($end-$start) * $args * $val)) echo "Cost Time: $cost"
The Java calling code is:
private void Callscript (String script, String args, string ... workspace) {try {String cmd = "sh" + script + "" + args;//< c0/>string[] cmd = {"sh", Script, "4"}; File dir = null;if (workspace[0]! = null) {dir = new File (workspace[0]); System.out.println (Workspace[0]);} String[] Evnp = {"val=2", "Call=bash Shell"};p rocess = Runtime.getruntime (). EXEC (cmd, evnp, dir);// process = Runtime . GetRuntime (). exec (CMD); BufferedReader input = new BufferedReader (New InputStreamReader (Process.getinputstream ())); String line = "", while (line = Input.readline ())! = null) {System.out.println (line);} Input.close ();} catch (Exception e) {e.printstacktrace ();}} public static void Main (string[] args) {//TODO auto-generated method Stubcallshell call = new Callshell (); call.callscript ("Test.sh", "4", "/root/experiment/");}
Output:
/root/experiment/the argument Is:4this is a Bash shellcost time:24
Java calls shell commands and scripts