首页 > 系统相关 >Java执行操作系统命令-Process抽象类(2)(Linux)

Java执行操作系统命令-Process抽象类(2)(Linux)

时间:2022-12-21 19:33:24浏览次数:64  
标签:bin ben exec Process 博客园 ls Linux Java bash

Java 8

20.04.1-Ubuntu

Eclipse Version: 2022-09 (4.25.0)

--

 

前一篇是在Windows上执行命令,本篇介绍在Linux系统中执行命令。

测试命令:

ls、cd、pwd

 

测试代码

ProcessController.java:提供接口 /api/process/executeCmd;

ExecuteCmdDTO.java:接收参数,仅一个 cmd 字符串;

@RestController
@RequestMapping(value = "/api/process")
@Slf4j
public class ProcessController {

	@PostMapping(value = "/executeCmd")
	public Boolean executeCmd(@RequestBody ExecuteCmdDTO dto) {
		log.info("ExecuteCmdDTO dto={}", dto);
		
		if (StringUtils.isEmpty(dto.getCmd())) {
			return false;
		}
		
		ProcessLinuxMain.test2(dto.getCmd());
		
		return Boolean.TRUE;
	}
}

@Data
public class ExecuteCmdDTO {

	/**
	 * 命令
	 */
	private String cmd;
	
}

 ProcessLinuxMain.java:使用 Runtime.getRuntime().exec(cmd) 执行命令

public class ProcessLinuxMain {
	/**
	 * 测试:Runtime.getRuntime().exec(...)
	 */
	public static void test2(String cmd) {
		cs.accept("start test2..cmd=" + cmd);
		try {
			Process ps = Runtime.getRuntime().exec(cmd);

			cs.accept("1、InputStream:");
			processIs(ps.getInputStream());
			cs.accept("2、ErrorStream:");
			processIs(ps.getErrorStream());
			cs.accept("3、----END----");
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 输出InputStream的内容:字符集 GB2312
	 * @param is
	 * @throws IOException
	 */
	private static void processIs(InputStream is) throws IOException {
		final int size = 1024;
		byte[] buffer = new byte[size];

		Charset cset = Charset.forName("GB2312");
		cs.accept("cset=" + cset);
		
		StringBuffer sb = new StringBuffer();
		
		int ret = 0;
		int total = 0;
		while ((ret = is.read(buffer, 0, size)) > 0) {
			total += ret;
			String chunk = new String(buffer, 0, ret, cset);
			
			sb.append(chunk);
		}

		cs.accept("ret=" + ret + ", total=" + total);
		cs.accept("sb=" + sb.length() + ", content=" + sb);
		
		is.close();
	}
}

ben发布于博客园

测试方式:

 

测试目录:

/home/ben/javaProcess

ben@ben-u:~/javaProcess$ pwd
/home/ben/javaProcess
ben@ben-u:~/javaProcess$ ls
sshdemo-0.0.1-SNAPSHOT.jar

ben发布于博客园

执行:ls /

结果:成功

结果1
 ExecuteCmdDTO dto=ExecuteCmdDTO(cmd=ls /)
start test2..cmd=ls /
1、InputStream:
cset=GB2312
ret=-1, total=134
sb=134, content=bin
boot
cdrom
dev
etc
home
lib
lib32
lib64
libx32
lost+found
media
mnt
opt
proc
repo
root
run
sbin
snap
srv
swapfile
sys
tmp
usr
var

2、ErrorStream:
cset=GB2312
ret=-1, total=0
sb=0, content=
3、----END----

 

执行:cd /home/ben/javaProcess

结果:失败。

提示:java.io.IOException: Cannot run program "cd": error=2, No such file or directory

解决:

前面添加 /bin/bash -c

注意,是小写的 c。ben发布于博客园

 

执行:/bin/bash -c cd /home/ben/javaProcess

结果:成功。

不过,InputStream、ErrorStream 没有数据。

 

执行:/bin/bash -c cd /home/ben/javaProcess | ls

结果:失败——没有收到 ls 命令的结果。ben发布于博客园

解决:

下文使用。

 

执行:pwd

结果:成功。

 

执行:/bin/bash -c ls /

结果:失败。

执行 ls 命令时,显示了 当前目录,而不是 预期的根目录。ben发布于博客园

 

小结(1)

ls 命令前 不加 /bin/bash -c;

cd 命令前 加 /bin/bash -c;

pwd 命令前 可加 可不加,都行。ben发布于博客园

 

为什么呢?TODO

 

Runtime#exec函数分析

上面测试的函数 都使用的下面的函数:ben发布于博客园

public class Runtime {
    public Process exec(String command) throws IOException {
        return exec(command, null, null);
    }
}

底层调用:

    public Process exec(String command, String[] envp, File dir)
        throws IOException {
        //...
        return exec(cmdarray, envp, dir);
    }
    // 再调用
    public Process exec(String[] cmdarray, String[] envp, File dir)
        throws IOException {
        return new ProcessBuilder(cmdarray)
            .environment(envp)
            .directory(dir)
            .start();
    }

从Runtime类的源码来看,其exec最终是执行 ProcessBuilder 的 start()

疑问:

参数 envp、dir 有什么用呢?TODOben发布于博客园

 

测试:Runtime#exec(String cmdarray[]) 函数

入参 为字符串数组了。

执行:ls

入参:

[
    "ls"
]

成功。ben发布于博客园

 

执行:pwd

入参:

[
    "pwd"
]

成功。

 

执行:ls /

入参:

[
    "ls /"
]

失败。

 

执行:["ls","/"]

成功。

 

执行多条命令:ls、grep

终端执行效果:

 

入参:

[
    "ls",
    "/",
    "|",
    "grep",
    "lib"
]

失败:grep的结果没出来,因为识别不了 竖线。ben发布于博客园

 

加上前缀:/bin/bash -c

入参:

[
    "/bin/bash",
    "-c",
    "ls",
    "/",
    "|",
    "grep",
    "lib"
]

失败:和终端执行结果不同。ben发布于博客园

 

再次测试

入参:

[
    "/bin/bash",
    "-c",
    "ls / | grep lib"
]

成功:输出结果为最终结果。ben发布于博客园

更进一步:成功。ben发布于博客园

 

小结(2)

执行带管道的多条命令,得使用 exec(String cmdarray[]) 函数,还得加上 /bin/bash, -c 两个字符串。

如果将  /bin/bash, -c 合并为一个字符串,则执行失败:

 

在本文的Ubuntu中,除了 /bin/bash,还可以使用 /bin/sh、/bin/dash。

其中,sh 指向 dash。ben发布于博客园

 

下一步:

还需要对命令执行的原理做深入了解才是。

 

本文链接:

https://www.cnblogs.com/luo630/p/16994832.html

 

参考资料

1、Java调用Linux命令(cd的处理)ben发布于博客园

https://www.cnblogs.com/yoyotl/p/6914096.html

posted @ 2017-05-30 22:17  一沙世界

2、

 

ben发布于博客园

 

标签:bin,ben,exec,Process,博客园,ls,Linux,Java,bash
From: https://www.cnblogs.com/luo630/p/16994832.html

相关文章

  • 基于Linux Kernel 4.8的Ubuntu 16.10 即将发布
    今天早些时候,我们惊讶的发现Ubuntu16.10(YakketyYak)已经基于Linux Kernel4.8分支了,Linux4.8分支目前还在研发状态,最终版本将于今年10月2日正式上线。此前Ubuntu16.10......
  • java的类和对象
    什么是类?类是一类事物的描述,一类事物的模板,一类事物的分类。什么是对象?对象是一类事物的具体描述,在生活中能够看的见,摸得着的实体,对象是类的具体的实例。什么是属......
  • JAVA数组
    数组是什么?数组是相同类型的,用一个标识符名称封装到一起的一个对象序列或基本类型数据序列。简单来讲就是一组相同类型元素的集合。为什么使用数组?当需要存储大量数据,例......
  • 【Java自动化测试】-TestNG操作详解
    一、 TestNG使用流程1.1TestNG安装本文以IDEA+Maven为例介绍TestNG,IntelliJIDEA版本为IntelliJIDEA。IntelliJIDEA中默认集成了TestNG,点击File->Settings,如下图:......
  • Zabbix通过proxy的被动模式代理来跨网段监控Linux主机
      上篇文章使用zabbixproxy实现主动代理跨网段分布式监控(https://blog.51cto.com/u_15105742/5956857),我们已经配置完架构图中的主动模式的监控部分,在这篇文章中我们就......
  • java两个list取交集
    直接上代码List<Integer>list1=newArrayList<>();list1.add(1);list1.add(2);list1.add(3);List<Integer>list2=......
  • 20个Linux命令
    1查看目录以及权限在windows中,使用dir查看当前目录中文件。在Linux中使用ls(list)查看当前目录文件。windows中的dir,如下图所示在Linux中,通常使用ls-l列出,其中可......
  • R语言和Python用泊松过程扩展:霍克斯过程Hawkes Processes分析比特币交易数据订单到达
    全文下载链接:http://tecdat.cn/?p=25880 最近我们被客户要求撰写关于泊松过程的研究报告,包括一些图形和统计输出。本文描述了一个模型,该模型解释了交易的聚集到达,并展示......
  • Java并发原理
    //并发产生的底层原理,从三个维度进行说明://1.内存维度,cpu内存有主存,缓存,寄存器,一般我们操作数据在寄存器上操作是最快的,但是直接在寄存器上操作的话,会造成,每个线程自己的......
  • java -jar 参数前后位置说明
    springboot项目启动的时候可以直接使用java-jarxxx.jar这样。下面说说参数的一些讲究1.-DpropName=propValue的形式携带,要放在-jar参数前面eg:java-Dxxx=test-Dp......