java-调用shell命令和脚本(代码片段)

程序员牧码 程序员牧码     2022-12-25     216

关键词:

介绍

有时候我们在Linux中运行Java程序时,需要调用一些Shell命令和脚本。而Runtime.getRuntime().exec()方法给我们提供了这个功能,而且Runtime.getRuntime()给我们提供了以下几种exec()方法

Process exec(String command) 
在单独的进程中执行指定的字符串命令。
 
Process exec(String[] cmdarray) 
在单独的进程中执行指定命令和变量。 

Process exec(String[] cmdarray, String[] envp) 
在指定环境的独立进程中执行指定命令和变量。 

Process exec(String[] cmdarray, String[] envp, File dir) 
在指定环境和工作目录的独立进程中执行指定的命令和变量。 

Process exec(String command, String[] envp) 
在指定环境的单独进程中执行指定的字符串命令。 

Process exec(String command, String[] envp, File dir) 
在有指定环境和工作目录的独立进程中执行指定的字符串命令。 

其中,其实cmdarray和command差不多,同时如果参数中如果没有envp参数或设为null,表示调用命令将在当前程序执行的环境中执行;如果没有dir参数或设为null,表示调用命令将在当前程序执行的目录中执行,因此调用到其他目录中的文件和脚本最好使用绝对路径。各个参数的含义

  1. cmdarray:包含所调用命令及其参数的数组。 
  2. command:一条指定的系统命令。
  3. envp:字符串数组,其中每个元素的环境变量的设置格式为name=value;如果子进程应该继承当前进程的环境,则该参数为 null。
  4. dir:子进程的工作目录;如果子进程应该继承当前进程的工作目录,则该参数为 null。 

细心的读者会发现,为了执行调用操作,JVM会启一个Process,所以我们可以通过调用Process类的以下方法,得知调用操作是否正确执行

abstract  int waitFor() 
导致当前线程等待,如有必要,一直要等到由该 Process 对象表示的进程已经终止。 

进程的出口值。根据惯例,0 表示正常终止;否则,就表示异常失败。

另外,调用某些Shell命令或脚本时,会有返回值,那么我们如果捕获这些返回值或输出呢?为了解决这个问题,Process类提供了

abstract InputStream  getInputStream() 
获取子进程的输入流。 最好对输入流进行缓冲。

调用Shell命令

这里为了说明问题,我仅用tar命令进行演示。tar命令是一个打包而不进行压缩的命令。同时,为了检查tar的调用是否被正常执行,我将调用waitFor()方法。

private void callCMD(String tarName, String fileName, String... workspace)
	try 
		String cmd = "tar -cf" + tarName + " " + fileName;
//            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's is: " + status);
		
	
	catch (Exception e)
		e.printStackTrace();
	

注意:如果把命令放到一个String[]中时,必须把命令中每个部分作为一个元素存在String[]中,或者是把命令按照空格符分割得到的String[]。

String[] cmd = "tar", "-cf", tarName, fileName; // right
String[] cmd = "tar -cf", tarName, fileName;	  // error

为了说明dir参数的作用,我特地把该Java程序和要打包的目录hive/放在不同的目录

/root/workspace/eclipse/Test/src/edu/wzm/CallShell.java
/root/experiment/hive

如果我不设置dir或设dir为null,那么fileName不得不是相对路径,最好是绝对路径

call.callCMD("/root/experiment/hive.tar", "/root/experiment/hive", null);
// OR
call.callCMD("/root/experiment/hive.tar", "/root/experiment/hive");

如果我设置了dir指向了hive所在的父目录就好办多了

call.callCMD("hive.tar", "hive", "/root/experiment/");

调用Shell脚本

Java调用Shell命令和调用Shell脚本的操作一模一样。我这里介绍另外几个方面

  1. 给脚本传递参数;
  2. 捕获调用的输出结果;
  3. envp的使用。

给脚本传递参数,这个操作很简单,无非是把参数加到调用命令后面组成String,或String[]。

捕获调用输出信息,前面也提到过用Process.getInputStream()。不过,建议最好对输入流进行缓冲

BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream()));

另外,envp是一个String[],并且String[]中的每一个元素的形式是:name=value。如:我的Linux系统中没有以下环境变量,但是我把它们写在Java代码中,作为envp

val=2
call=Bash Shell

我要调用的Shell脚本是:/root/experiment/test.sh

#!/usr/bin/env bash
 
args=1
if [ $# -eq 1 ];then
	args=$1
	echo "The argument is: $args"
fi
 
echo "This is a $call"
start=`date +%s`
sleep 3s
end=`date +%s`
cost=$((($end - $start) * $args * $val))
echo "Cost Time: $cost"

Java调用代码是

private void callScript(String script, String args, String... workspace)
	try 
		String cmd = "sh " + script + " " + args;
//        	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";
		process = 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 stub
	CallShell call = new CallShell();
	call.callScript("test.sh", "4", "/root/experiment/");

输出

/root/experiment/
The argument is: 4
This is a Bash Shell
Cost Time: 24

Hutool

  • RutimeUtil 工具类(推荐使用)

java001-java调用shell命令和脚本

...,证书机构提供小工具,执行.sh脚本即可启动服务,本地调用该服务即可获取证书。问题:linux服务器启动该服务,不能关闭。一旦关闭,服务即停止。解决方案:java调用shell命令,利用spring容器启动即执行方案。参考博文:http... 查看详情

java程序执行,调用shell命令和shell脚本

 坑呀!记得在start()之后,waitFor()之前把缓冲区读出来打log,否则是阻塞缓冲区,没有输出的package com.jikexueyuancrm.util;import java.io.BufferedReader;import java.io.DataOutputStream;import java.io.IOException; 查看详情

java调用shell命令及脚本

...序中则是一种快速实现的不错途径本文介绍使用java代码调用并执行shell我在~/bin/目录下写了jbossLogDelivery.sh,有两个功能{./jbossLogDelivery.shlist}作用是输出jboss现有的日志列表,{./jbossLogDelivery.shgetlogName[email&# 查看详情

shell脚本和常用命令(代码片段)

什么是脚本?脚本简单地说就是一条条的文字命令(一些指令的堆积),这些文字命令是可以看到的(如可以用记事本打开查看、编辑)。 常见的脚本:JavaScript(JS,前端),VBScript,ASP,JSP,PHP(后端),SQL(数据库操作... 查看详情

linuxshell脚本被包含是什么意思?.命令和source命令(在脚本中运行脚本,脚本中调用脚本)(脚本包含,父子脚本)(代码片段)

在shell编程中,当一个shell脚本被另一个shell脚本包含,即用.或source命令包含,则被包含的脚本在当前shell进程内执行,并且可以访问当前shell进程的环境变量和函数。此时,$0代表的是主脚本的名称,而$BASH... 查看详情

linuxshell脚本被包含是什么意思?.命令和source命令(在脚本中运行脚本,脚本中调用脚本)(脚本包含,父子脚本)(代码片段)

在shell编程中,当一个shell脚本被另一个shell脚本包含,即用.或source命令包含,则被包含的脚本在当前shell进程内执行,并且可以访问当前shell进程的环境变量和函数。此时,$0代表的是主脚本的名称,而$BASH... 查看详情

shell脚本中实现远程和其他用户的子shell执行(代码片段)

...的子shell执行shell远程用户执行脚本简单执行-单行形式的命令脚本执行-对于命令行太多的采用eof方式支持多行命令shell切换用户执行脚本简单执行脚本执行-对于命令行太多的采用eof方式支持多行命令eof注意点案例shell远程用户执... 查看详情

不知道java如何调用shell脚本?进来教你10行代码搞定(代码片段)

产品与开发的战争       前段时间,产品提了个挺离谱的需求:通过java服务启动自己所需要的数据库和redis。什么意思呢,意思就是我们需要提供一个java服务,但是呢,我们这个java服务用到的mysql和redis没... 查看详情

shell脚本基础和grep使用(代码片段)

shell脚本基础和grep使用一、shell脚本基础(1)、命令hashhash的作用:缓存此前命令的查找结果:key-value数据格式(键值),key:搜索键;value:值hash的使用:直接使用hash,列出缓存的所有命令-d选项,hash-dCOMMAND:表示清空指定命令... 查看详情

shell脚本简介及常用文本编辑命令(代码片段)

什么是脚本?脚本简单地说是一条条的文字命令(一些指令的堆积),这些文字命令是可以看到的,可以通过记事本打开和编辑为什么要学习和使用shellshell属于内置脚本程序开发的效率非常高,依赖于功能强大的命令可以迅速... 查看详情

shell脚本中调用另一个shell脚本的三种方式(代码片段)

...后的内容就不会再执行了source在同一个Shell中执行,在被调用的脚本中声明的变量和环境变量,都可以在主脚本中进行获取和使用,相 查看详情

shell全解析:shell脚本程序(代码片段)

...环2.2.2while循环三、Shell脚本中的函数3.1Shell函数的定义和调用3.2Shell函数内操作实参四、Shell脚本中的输入/输出重定向4.1重定向与重定向命令4.2输出重定向4.3输入重定向4.4三种文件五、Shell脚本中的文件包含六、尾声一、前言本文... 查看详情

python脚本中执行shell命令(代码片段)

system()其中最后一个0是这个命令的返回值,为0表示命令执行成功。使用system无法将执行的结果保存起来。popen()获取命令执行的结果,但是没有命令的执行状态,这样可以将获取的结果保存起来放到list中。commands可以... 查看详情

学习六十三(代码片段)

20.1shell脚本介绍20.2shell脚本结构和执行20.3date命令用法20.4shell脚本中的变量shell脚本介绍shell是一种脚本语言aming_linuxblog.lishiming.net可以使用逻辑判断、循环等语法可以自定义函数shell是系统命令的集合shell脚本可以实现自动化运维... 查看详情

学习六十三(代码片段)

20.1shell脚本介绍20.2shell脚本结构和执行20.3date命令用法20.4shell脚本中的变量shell脚本介绍shell是一种脚本语言可以使用逻辑判断、循环等语法可以自定义函数shell是系统命令的集合shell脚本可以实现自动化运维,能大大增加我们的... 查看详情

shell脚本——make命令和makefile文件(代码片段)

make命令是一个常用的编译命令,尤其在C/C++开发中,make命令通过makefile文件中描述源程序之间的依赖关系进行自动编译;makefile文件是按照规定格式编写,需说明如何编译各个源文件并连接生成可执行文件&#x... 查看详情

shell脚本的调试方法(代码片段)

...一些用于调试脚本的选项,如下所示:-n读一遍脚本中的命令但不执行,用于检查脚本中的语法错误-v一边执行脚本,一边将执行过的脚本命令打印到标准错误输出-x提供跟踪执行信息,将执行的每一条命令和结果依次打印出来使... 查看详情

shel脚本-初步入门之《02什么是shell脚本》(代码片段)

Shel脚本-初步入门-什么是Shell脚本2、什么是Shell脚本当命令或程序语句不在命令行下执行,而是通过一个程序文件来执行时,改程序就被称为Shell脚本。如果在Shell脚本里内置了很多条命令、语句及循环控制,然后将这些命令一次... 查看详情