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

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

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

服務器之家 - 編程語言 - Java教程 - Java中如何執行多條shell/bat命令

Java中如何執行多條shell/bat命令

2021-11-13 13:15qq342643414 Java教程

這篇文章主要介紹了Java中如何執行多條shell/bat命令的方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

java調用process執行命令

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class ShellUtil {
    public static String runShell (String shStr) throws Exception {
        Process process;
        process = Runtime.getRuntime().exec( new String[]{ "/bin/sh" , "-c" ,shStr});
        process.waitFor();
        BufferedReader read = new BufferedReader( new InputStreamReader(process.getInputStream()));
        String line = null ;
        String result = "" ;
        while ((line = read.readLine())!= null ){
            result+=line;
        }
        return result;
    }
}

注意:如果是windows操作系統要改為

?
1
Runtime.getRuntime().exec(new String[]{"**cmd** exe","-c","command"});

1.當要執行多條時且不依賴事務,可以分開多次調用

?
1
2
3
4
5
6
7
8
9
10
public class ExecuteShell {
    public static void main (String[] args){
        String command1 = "some command" ;
        String command2 = "some command" ;
        String message1 = ShellUtil.runShell(command1);
        String message2 = ShellUtil.runShell(command2);
        System. out .println(message1);
        System. out .println(message2);
    }
}

2.但是當命令之間有事務依賴時

比如一條命令是登錄數據庫,第二條執行查詢語句,上面分開多次調用的方式就不行。需要做改動如下

?
1
2
3
4
5
6
7
8
9
public class ExecuteShell {
    public static void main (String[] args){
        String command1 = "some command" ;
        String command2 = "some command" ;
        String command = command1 + " && " + command2;
        String message = ShellUtil.runShell(command);
        System. out .println(message);
    }
}

Java執行shell遇到的各種問題

1、判斷子進程是否執行結束

有的時候我們用java調用shell之后,之后的操作要在Process子進程正常執行結束的情況下才可以繼續,所以我們需要判斷Process進程什么時候終止。

Process類提供了waitFor()方法。該方法導致當前線程等待,直到Process線程終止。

Process.waitFor()是有一個int類型返回值的,當返回值為0的時候表Process進程正常終止。否則一般是腳本執行出錯了(我遇到的一般是這種情況)。

2、Process.waitFor()導致當前線程阻塞

有的時候我們發現調用waitFor()方法后,java主線程會一直阻塞在waitFor()處,阻塞的原因是什么呢?

分析一下:

Java在執行Runtime.getRuntime().exec(jyName)之后,Linux會創建一個進程,該進程與JVM進程建立三個管道連接,標準輸入流、標準輸出流、標準錯誤流,假設linux進程不斷向標準輸出流和標準錯誤流寫數據,而JVM卻不讀取,數據會暫存在linux緩存區,當緩存區存滿之后導致該進程無法繼續寫數據,會僵死,導致java進程會卡死在waitFor()處,永遠無法結束。

解決辦法:

java進程在waitFor()前不斷讀取標準輸出流和標準錯誤流:

?
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
//jyName  解壓腳本路徑
 String fileName=fileList.get(0).toString().substring(fileList.get(0).toString().lastIndexOf(File.separator)+1);
 String  jyName="/etc/zxvf.sh "+fileName;
 try {
  Process p0 = Runtime.getRuntime().exec(jyName);
  //讀取標準輸出流
  BufferedReader bufferedReader =new BufferedReader(new InputStreamReader(p0.getInputStream()));
  String line;
  while ((line=bufferedReader.readLine()) != null) {
      System.out.println(line);
  }
  //讀取標準錯誤流
  BufferedReader brError = new BufferedReader(new InputStreamReader(p0.getErrorStream(), "gb2312"));
  String errline = null;
  while ((errline = brError.readLine()) != null) {
    System.out.println(errline);
  }
  //waitFor()判斷Process進程是否終止,通過返回值判斷是否正常終止。0代表正常終止
  int c=p0.waitFor();
  if(c!=0){
   baseRes.put("desc", "軟件升級失敗:執行zxvf.sh異常終止");
   baseRes.setReturnFlag(false);
   return baseRes;
  }
 } catch (IOException e1) {
  baseRes.put("desc", "軟件升級失敗:文件解壓失敗");
  baseRes.setReturnFlag(false);
  return baseRes;
 } catch (InterruptedException e1) {
  baseRes.put("desc", "軟件升級失敗:文件解壓失敗");
  baseRes.setReturnFlag(false);
  return baseRes;
 }

也可以在執行Runtime.getRuntime().exec(jyName)之后另外再啟動兩個線程分別讀取標準錯誤流和標準輸出流

?
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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
 
public class ExcuteThread extends Thread {
 private String name;
 public ExcuteThread(String name) {
  this.name = name;
 }
 @Override
 public void run() {
  try {
   Process p = Runtime.getRuntime().exec(name);
   InputStream fis = p.getInputStream();
   final BufferedReader brError = new BufferedReader(
     new InputStreamReader(p.getErrorStream(), "gb2312"));
   InputStreamReader isr = new InputStreamReader(fis, "gb2312");
   final BufferedReader br = new BufferedReader(isr);
   Thread t1 = new Thread() {
    public void run() {
     String line = null;
     try {
      while ((line = brError.readLine()) != null) {
       // System.out.println(line);
      }
     } catch (IOException e) {
      e.printStackTrace();
     } finally {
      try {
       if (brError != null)
        brError.close();
      } catch (IOException e) {
       e.printStackTrace();
      }
     }
    }
   };
   Thread t2 = new Thread() {
    public void run() {
     String line = null;
     try {
      while ((line = br.readLine()) != null) {
       // System.out.println(line);
      }
     } catch (IOException e) {
      e.printStackTrace();
     } finally {
      try {
       if (br != null)
        br.close();
      } catch (IOException e) {
       // TODO Auto-generated catch block
       e.printStackTrace();
      }
     }
    }
   };
   t1.start();
   t2.start();
 
  } catch (IOException e1) {
   // TODO Auto-generated catch block
   e1.printStackTrace();
  } finally {
  }
 }
}

3、shell腳本中有關聯腳本,注意路徑

就是shell腳本中還要執行其他腳本,這時候就是注意一個路徑的問題,這個問題也是我找了好長時間的一個問題。

?
1
Process p=Runtime.getRuntime().exec(“/etc/a.sh”)

在Test.java類調用了etc目錄下的a.sh腳本, a.sh腳本中執行etc目錄下的b.sh腳本,原來我在a.sh腳本中寫的是./b.sh。

其實這樣linux是找不到b.sh的,因為我們執行是在Test.class目錄下調用的/etc/a.sh 所以當a.sh中執行./b.sh的時候他會在Test.class目錄下尋找,所以找不到,所以a.sh中要寫成/etc/b.sh

4、java連續調用多個腳本

?
1
2
3
String[] cmd = { "/bin/sh", "-c", "rm -rf /installation/upgrade/ ; mkdir /installation/upgrade/" };
Process p = Runtime.getRuntime().exec(cmd);
p.waitFor();

就是這種數組的方式。

5、java執行.sh腳本文件的時候直接寫目錄就行

例如這樣:

?
1
Runtime.getRuntime().exec(“/etc/a.sh”)

java 直接執行語句的時候需要加上"/bin/sh" 例如這樣:

?
1
2
String name="/bin/sh cd /installation/upgrade/ip89_install_packet";
Process p = Runtime.getRuntime().exec(name);

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

原文鏈接:https://blog.csdn.net/qq342643414/article/details/77880692

延伸 · 閱讀

精彩推薦
  • Java教程Java8中Stream使用的一個注意事項

    Java8中Stream使用的一個注意事項

    最近在工作中發現了對于集合操作轉換的神器,java8新特性 stream,但在使用中遇到了一個非常重要的注意點,所以這篇文章主要給大家介紹了關于Java8中S...

    阿杜7482021-02-04
  • Java教程Java BufferWriter寫文件寫不進去或缺失數據的解決

    Java BufferWriter寫文件寫不進去或缺失數據的解決

    這篇文章主要介紹了Java BufferWriter寫文件寫不進去或缺失數據的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望...

    spcoder14552021-10-18
  • Java教程xml與Java對象的轉換詳解

    xml與Java對象的轉換詳解

    這篇文章主要介紹了xml與Java對象的轉換詳解的相關資料,需要的朋友可以參考下...

    Java教程網2942020-09-17
  • Java教程升級IDEA后Lombok不能使用的解決方法

    升級IDEA后Lombok不能使用的解決方法

    最近看到提示IDEA提示升級,尋思已經有好久沒有升過級了。升級完畢重啟之后,突然發現好多錯誤,本文就來介紹一下如何解決,感興趣的可以了解一下...

    程序猿DD9332021-10-08
  • Java教程小米推送Java代碼

    小米推送Java代碼

    今天小編就為大家分享一篇關于小米推送Java代碼,小編覺得內容挺不錯的,現在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧...

    富貴穩中求8032021-07-12
  • Java教程20個非常實用的Java程序代碼片段

    20個非常實用的Java程序代碼片段

    這篇文章主要為大家分享了20個非常實用的Java程序片段,對java開發項目有所幫助,感興趣的小伙伴們可以參考一下 ...

    lijiao5352020-04-06
  • Java教程Java實現搶紅包功能

    Java實現搶紅包功能

    這篇文章主要為大家詳細介紹了Java實現搶紅包功能,采用多線程模擬多人同時搶紅包,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙...

    littleschemer13532021-05-16
  • Java教程Java使用SAX解析xml的示例

    Java使用SAX解析xml的示例

    這篇文章主要介紹了Java使用SAX解析xml的示例,幫助大家更好的理解和學習使用Java,感興趣的朋友可以了解下...

    大行者10067412021-08-30
主站蜘蛛池模板: 亚洲国产精品日韩高清秒播 | 色婷婷综合缴情综六月 | 国产免费色视频 | www.俺去| 色婷婷天天综合在线 | 四虎影在线永久免费观看 | 精品国产乱码久久久久久人妻 | 四虎影院在线免费 | 色婷在线 | 双子母性本能在线 | 成人女人天堂午夜视频 | 强制高h| 歪歪视频在线播放无遮挡 | 欧美一区二区三区成人看不卡 | 日本草草视频在线观看 | 天堂网在线.www天堂在线资源 | 边摸边吃奶又黄激烈视频韩国 | 国产一区二区视频免费 | 久久国内精品 | 久久久96| 四虎影在线永久免费观看 | 魔法满屋免费观看完整版中文 | 亚洲日本aⅴ片在线观看香蕉 | 欧美日韩亚洲成人 | 丁香久久婷婷 | 激情六月丁香婷婷四房播 | 亚洲国产精品第一区二区三区 | chinese老太grandma| 精品精品久久宅男的天堂 | 超级碰在线视频 | 春光乍泄在线 | 免费理伦片在线观看全网站 | 欧美精品久久一区二区三区 | 第一福利在线观看永久视频 | 嗯啊好大好粗 | 男人的影院 | 吉泽明步高清无码中文 | 高清国产精品久久 | 亚洲视频中文 | 免费永久观看美女视频网站网址 | 亚洲AV国产国产久青草 |