一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - 如何使用Java調用Linux系統命令

如何使用Java調用Linux系統命令

2022-03-09 13:13DreamMakers Java教程

這篇文章主要介紹了如何使用Java調用Linux系統命令,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

Java調用Linux系統命令

有時候,我們在使用Java做一些操作時,可能性能上并不能達到我們滿意的效果,就拿最近工作中的遇到的一個場景來說,需要對大量的小文件進行合并成一個大文件。

最開始的想法是使用Java做文件操作,遍歷所有小文件然后往一個文件寫(可以做成并發寫),但是發現操作過程中遇到個問題,寫一千多個小文件在本機Windows下需要花費幾十秒的時間,即使在Linux環境下高配置的機器也需要將近十秒,這明顯對接口的響應時間產生重要影響。這塊怎么優化下呢?

我們都知道在Linux下可以進行大文件的分割和合并,分別采用split和cat命令,于是做了個實驗,在Linux下對相同的一個1G文件進行切割成1000個小文件,然后對這一千多個小文件進行合并。效果是驚人的!!!竟然瞬間就能合成完成了!這更加讓我堅定了應該使用系統命令進行批量小文件進行合并的想法。

我們這里封裝一個類,用來調用系統命令,然后得到系統調用的返回結果。

我們先封裝了一個返回結果類:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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;
 }
 
}

接著我們給出封裝的系統調用實現類:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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類如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
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對象。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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,具體實現如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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

可用如下方式執行:

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

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持服務器之家。

原文鏈接:https://majing.blog.csdn.net/article/details/88773993

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 无限在线观看视频大全免费高清 | 国产精品啪啪 | 精品欧美一区二区精品久久 | 极致堕落(高h) | 欧洲肥女大肥臀tv | 色婷婷狠狠 | 丝瓜草莓香蕉绿巨人幸福宝 | ts人妖国产一区 | 亚洲欧洲日产v特级毛片 | 亚洲国产在线 | 国产在线观看一区 | 日本亚欧乱色视频在线观看 | xxx黑人又大粗又长 xxxx性欧美极品另类 | 亚洲国产第一区二区三区 | 免费yjsp妖精com | 俄罗斯一级在线播放 | 成人久久18免费网站入口 | 二次元美女互摸隐私互扒 | 精品无码久久久久久久动漫 | 亚洲邪恶天堂影院在线观看 | 韩国女主播一区二区视频 | 日韩在线视频二区 | 动漫女性扒开尿口羞羞漫画 | 亚洲福利区 | 午夜无码片在线观看影院 | 九九在线精品视频 | 日本人做受全过程视频 | 精品久久99麻豆蜜桃666 | 高清国产激情视频在线观看 | 国产1区2区三区不卡 | 红杏网| 91视频破解 | 韩国丽卡三级作品 | 国产91精品在线观看 | 成人性用品 | 我将她侵犯1~6樱花动漫在线看 | 欧美一区二区三区综合色视频 | 深夜在线 | 国产男女乱淫真视频全程播放 | 欧美 变态 另类 人妖班 | 日日视频|