如何使用Java调用Linux系统命令

目录
  • Java调用Linux系统命令
  • java执行Linux命令,支持通配符(*)

Java调用Linux系统命令

有时候,我们在使用Java做一些操作时,可能性能上并不能达到我们满意的效果,就拿最近工作中的遇到的一个场景来说,需要对大量的小文件进行合并成一个大文件。

最开始的想法是使用Java做文件操作,遍历所有小文件然后往一个文件写(可以做成并发写),但是发现操作过程中遇到个问题,写一千多个小文件在本机Windows下需要花费几十秒的时间,即使在Linux环境下高配置的机器也需要将近十秒,这明显对接口的响应时间产生重要影响。这块怎么优化下呢?

我们都知道在Linux下可以进行大文件的分割和合并,分别采用split和cat命令,于是做了个实验,在Linux下对相同的一个1G文件进行切割成1000个小文件,然后对这一千多个小文件进行合并。效果是惊人的!!!竟然瞬间就能合成完成了!这更加让我坚定了应该使用系统命令进行批量小文件进行合并的想法。

我们这里封装一个类,用来调用系统命令,然后得到系统调用的返回结果。

我们先封装了一个返回结果类:

package com.majing.learning.fileupload.common.process;

public class ProcessResult {
 private boolean success = false;
 private String errorMessage;
 private String outputMessage;
 public boolean isSuccess() {
  return success;
 }
 public void setSuccess(boolean success) {
  this.success = success;
 }
 public String getErrorMessage() {
  return errorMessage;
 }
 public void setErrorMessage(String errorMessage) {
  this.errorMessage = errorMessage;
 }
 public String getOutputMessage() {
  return outputMessage;
 }
 public void setOutputMessage(String outputMessage) {
  this.outputMessage = outputMessage;
 }

}

接着我们给出封装的系统调用实现类:

package com.majing.learning.fileupload.common.process;

import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;

import org.apache.commons.lang3.StringUtils;

public class CommandUtils {

 public static ProcessResult runCmdTest(ExecutorService executorService, String command) throws IOException, InterruptedException {
  StringBuilder queryInputResult = new StringBuilder();
  StringBuilder queryErroInputResult = new StringBuilder();
  ProcessResult processResult = new ProcessResult();
  String[] cmd = { "/bin/sh", "-c", command};
  Process pro = Runtime.getRuntime().exec(cmd);
  CountDownLatch lock = new CountDownLatch(2);
  executorService.submit(new ProcessCheckTask(queryInputResult, lock, pro.getInputStream()));
  executorService.submit(new ProcessCheckTask(queryErroInputResult, lock, pro.getErrorStream()));
  boolean done = false;
  while (!done) {
   lock.await();
   done = true;
  }
  processResult.setOutputMessage(queryInputResult.toString());
  processResult.setErrorMessage(queryErroInputResult.toString());
  processResult.setSuccess(StringUtils.isBlank(processResult.getErrorMessage()));
  return processResult;
 }
}

其中ProcessCheckTask类如下:

package com.majing.learning.fileupload.common.process;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.concurrent.CountDownLatch;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.majing.learning.fileupload.common.ConstValues;

public class ProcessCheckTask implements Runnable {

 private static Logger logger = LoggerFactory.getLogger(ProcessCheckTask.class);

 /** 锁 */
 private CountDownLatch lock;

 /** 执行结果输入流 */
 private InputStream inputStream;

 /** 字符拼接 */
 private StringBuilder queryInputResult;

 public ProcessCheckTask(StringBuilder queryInputResult, CountDownLatch lock, InputStream inputStream) {
  super();
  this.lock = lock;
  this.inputStream = inputStream;
  this.queryInputResult = queryInputResult;
 }

 @Override
 public void run() {
  try {
   BufferedReader bf = new BufferedReader(new InputStreamReader(inputStream));
   String line = null;
   while ((line = bf.readLine()) != null && line.length() > 0) {
    queryInputResult.append(line).append("\n");
   }
  } catch (Exception e) {
   logger.error(ConstValues.EXCEPTION_OCCURED, e);
  } finally {
   lock.countDown();
  }
 }
}

上面是一个简单实现,但是可能会存在一个问题,那就是执行系统命令的时间如果本身比较长,如果不想一直等待到系统命令执行完,而是在一段时间没有返回就直接认为失败,所以需要增加过期时间的考虑。这里我借助于Future框架,将上面的调用系统命令的方法封装成一个Callable对象。

package com.majing.learning.fileupload.common.process;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;

public class CommandTask implements Callable<ProcessResult>{

 private ExecutorService executorService;

 private String command;

 public CommandTask(ExecutorService executorService, String command){
  this.executorService = executorService;
  this.command = command;
 }

 @Override
 public ProcessResult call() throws Exception {
  return CommandUtils.runCmdTest(executorService, command);
 }

}

然后在上面的CommandUtils的基础上再封装一层变成CommandHelper,具体实现如下:

package com.majing.learning.fileupload.common.process;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.majing.learning.fileupload.common.ConstValues;

 public class CommandHelper {
 private static Logger logger = LoggerFactory.getLogger(CommandHelper.class);
 private static ExecutorService executorService=Executors.newFixedThreadPool(50);
 private static long default_timeout = 8000;
 public static ProcessResult process(String command){
  return process(command, default_timeout, TimeUnit.MILLISECONDS);
 }

 public static ProcessResult process(String command, long timeout, TimeUnit unit){
  CommandTask commandTask = new CommandTask(executorService, command);
  Future<ProcessResult> processResult = executorService.submit(commandTask);
  ProcessResult result = null;
  try{
   result = processResult.get(timeout, unit);
  }catch(Exception e){
   logger.error(ConstValues.EXCEPTION_OCCURED, e);
  }
  return result;
 }
}

至此,我们在需要调用系统命令时直接调用CommandHelper.process(command)就可以了,然后拿到返回结果ProcessResult。我也是自己做个记录,有需要的朋友可以直接拿去用。

顺便说一句,采用封装的这个类在完成上面相同的任务时,时间都在相同的机器上,耗时从原来的10s瞬间减少至200ms以内,由此可见,在适当的场景调用系统命令是多么重要啊。

java执行Linux命令,支持通配符(*)

java执行linux或者windows命令,这个需求比较常见。

但是若使用 Runtime.getRuntime().exec(cmd); 会发现,若cmd中含有通配符,则无法执行,如cp /dira/*.txt /dirb

可用如下方式执行:

String[] cmdArr = new String[3];
        cmdArr[0] = "/bin/sh";
        cmdArr[1] = "-c";
        cmdArr[2] = command;
process = Runtime.getRuntime().exec(cmdArr);

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • Java调用linux shell脚本的方法

    首先,我们需要增加用户对该脚本的执行权限,即 复制代码 代码如下: String cmdstring = "chmod a+x test.sh";  Process proc = Runtime.getRuntime().exec(cmdstring);  proc.waitFor(); //阻塞,直到上述命令执行完  cmdstring = "bash test.sh"; //这里也可以是ksh等  proc = Runtime.getRuntime().exec

  • java执行Linux命令的方法

    本文实例讲述了java执行Linux命令的方法.分享给大家供大家参考.具体实现方法如下: 复制代码 代码如下: public class StreamGobbler extends Thread {            InputStream is;      String type;        public StreamGobbler(InputStream is, String type) {          this.is = is;          this.type = ty

  • Java代码执行shell命令的实现

    本文描述两种方式使用java代码执行shell命令,首先使用Runtime类调用exce方法,其次使用ProcessBuilder实例实现更灵活的方式. 1. 环境准备 执行shell命令之前,我们需要获取jvm底层操作系统,同时定义通用消费流的类. 1.1. 操作系统依赖 在创建进场执行shell命令之前,我们需要获取jvm运行在具体哪个操作系统之上.因为Windows执行shell命令是cmd.exe,而其他操作系统发布标准shell是sh: boolean isWindows = Syst

  • 如何使用Java调用Linux系统命令

    目录 Java调用Linux系统命令 java执行Linux命令,支持通配符(*) Java调用Linux系统命令 有时候,我们在使用Java做一些操作时,可能性能上并不能达到我们满意的效果,就拿最近工作中的遇到的一个场景来说,需要对大量的小文件进行合并成一个大文件. 最开始的想法是使用Java做文件操作,遍历所有小文件然后往一个文件写(可以做成并发写),但是发现操作过程中遇到个问题,写一千多个小文件在本机Windows下需要花费几十秒的时间,即使在Linux环境下高配置的机器也需要将近十秒,这

  • 利用Python+Java调用Shell脚本时的死锁陷阱详解

    前言 最近有一项需求,要定时判断任务执行条件是否满足并触发 Spark 任务,平时编写 Spark 任务时都是封装为一个 Jar 包,然后采用 Shell 脚本形式传入所需参数执行,考虑到本次判断条件逻辑复杂,只用 Shell 脚本完成不利于开发测试,所以调研使用了 Python 和 Java 分别调用 Spark 脚本的方法. 使用版本为 Python 3.6.4 及 JDK 8 Python 主要使用 subprocess 库.Python 的 API 变动比较频繁,在 3.5 之后新增了

  • Java调用Shell命令和脚本的实现

    1.介绍 有时候我们在Linux中运行Java程序时,需要调用一些Shell命令和脚本.而Runtime.getRuntime().exec()方法给我们提供了这个功能,而且Runtime.getRuntime()给我们提供了以下几种exec()方法: Process exec(String command) 在单独的进程中执行指定的字符串命令. Process exec(String[] cmdarray) 在单独的进程中执行指定命令和变量. Process exec(String[] cmd

  • 详解java调用ffmpeg转换视频格式为flv

    详解java调用ffmpeg转换视频格式为flv 注意:下面的程序是在Linux下运行的,如果在windows下rmvb转换成avi会出现问题,想成功需要下载下个drv43260.dll东西放到C:WindowsSystem32下面 这几天在写一个视频管理系统,遇到一个很大的问题就是如果把不同格式转换为flv,格式!经过网上的一番搜索,自己在总结,整理,整理,终于整出来了!实现了视频进行转换的同时还能够进行视频截图和删除原文件的功能! 格式转换主要原理就是先用java调用ffmpeg的exe文件

  • PHP执行linux系统命令的常用函数使用说明

    system函数 说明:执行外部程序并显示输出资料. 语法:string system(string command, int [return_var]); 返回值: 字符串 详细介绍: 本函数就像是 C 语中的函数 system(),用来执行指令,并输出结果.若是 return_var 参数存在,则执行 command 之后的状态会填入 return_var 中.同样值得注意的是若需要处理用户输入的资料,而又要防止用户耍花招破解系统,则可以使用 EscapeShellCmd().若 PHP 以

  • Linux 系统命令精通指南

    在"Linux 文件命令精通指南"中,我们讨论了利用最基础和最常用 Linux 文件命令所需的基本信息.在本文中,我将对 Linux 系统命令作同样的讨论. 我们在前一篇文章中了解到,在 Linux/UNIX 世界中,一切都被看作文件,包括系统管理命令.单独对于组织而言,我们在本系列的第一部分中讨论了文件命令,并将在本文中提供最有用的系统诊断和维护命令. 对于文件命令,我们在此处详尽讨论了某些相当简单和直观的管理命令.而只描述了其他较复杂命令的功能,以便在您需要使用时,知道存在这些命令

  • Python如何调用外部系统命令

     前言 利用Python调用外部系统命令的方法可以提高编码效率.调用外部系统命令完成后可以通过获取命令执行返回结果码.执行的输出结果进行进一步的处理.本文主要描述Python常见的调用外部系统命令的方法,包括os.system().os.popen().subprocess.Popen()等. 本文分析python调用外部系统命令主要从两个方面考虑:1.是不是可以返回命令执行结果码,因为大部分场景都需要通过判断调用命令是执行成功还是失败.2.是不是可以获取命令执行结果.某些场景调用外部命令就是为

  • Python代码一键转Jar包及Java调用Python新姿势

    需求背景 进击的Python 随着人工智能的兴起,Python这门曾经小众的编程语言可谓是焕发了第二春. 以tensorflow.pytorch等为主的机器学习/深度学习的开发框架大行其道,助推了python这门曾经以爬虫见长(python粉别生气)的编程语言在TIOBE编程语言排行榜上一路披荆斩棘,坐上前三甲的宝座,仅次于Java和C,将C++.JavaScript.PHP.C#等一众劲敌斩落马下. 当然,轩辕君向来是不提倡编程语言之间的竞争对比,每一门语言都有自己的优势和劣势,有自己应用的领

随机推荐