欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java調(diào)用shell命令涉及管道、重定向時(shí)不生效問(wèn)題及解決

 更新時(shí)間:2022年12月23日 16:01:48   作者:chao09_01  
這篇文章主要介紹了Java調(diào)用shell命令涉及管道、重定向時(shí)不生效問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

Java調(diào)用shell命令涉及管道、重定向時(shí)不生效

近日,因項(xiàng)目需求需要用java調(diào)用shell命令實(shí)現(xiàn)清理過(guò)時(shí)圖片任務(wù),發(fā)現(xiàn)代碼生成出來(lái)的shell命令在linux系統(tǒng)后臺(tái)直接執(zhí)行,可以實(shí)現(xiàn)效果,但是,經(jīng)過(guò)java代碼運(yùn)行,則達(dá)不到預(yù)期效果。

經(jīng)研究發(fā)現(xiàn),因?yàn)樵搒hell命令涉及了管道,這情況就有點(diǎn)不一樣了,下面是針對(duì)Java調(diào)用shell命令涉及管道、重定向時(shí)不生效問(wèn)題的解決方法

參考代碼如下:

public class Test
{
        /**
         * @param args
         * @throws IOException
         * @throws InterruptedException
         */
        public static void main(String[] args) throws IOException, InterruptedException
        {
                Process p;
                String command = "find /opt/Img/ \"2019-11-22-*.jpg\" | xargs rm -rf"};
                // 必須加上sh -c
                p = Runtime.getRuntime().exec(new String[]{"sh","-c",command});
                if(0==p.waitFor())
                {
                        System.out.println("Command execute result is OK!");
                }
                else
                {
                        System.out.println("Command execute result is fail......");
                }
        }
}

Java執(zhí)行shell遇到的各種問(wèn)題

1、判斷子進(jìn)程是否執(zhí)行結(jié)束

有的時(shí)候我們用java調(diào)用shell之后,之后的操作要在Process子進(jìn)程正常執(zhí)行結(jié)束的情況下才可以繼續(xù),所以我們需要判斷Process進(jìn)程什么時(shí)候終止。

Process類(lèi)提供了waitFor()方法。該方法導(dǎo)致當(dāng)前線程等待,直到Process線程終止。

Process.waitFor()是有一個(gè)int類(lèi)型返回值的,當(dāng)返回值為0的時(shí)候表Process進(jìn)程正常終止。否則一般是腳本執(zhí)行出錯(cuò)了(我遇到的一般是這種情況)。

2、Process.waitFor()導(dǎo)致當(dāng)前線程阻塞

有的時(shí)候我們發(fā)現(xiàn)調(diào)用waitFor()方法后,java主線程會(huì)一直阻塞在waitFor()處,阻塞的原因是什么呢?分析一下:

Java在執(zhí)行Runtime.getRuntime().exec(jyName)之后,Linux會(huì)創(chuàng)建一個(gè)進(jìn)程,該進(jìn)程與JVM進(jìn)程建立三個(gè)管道連接,標(biāo)準(zhǔn)輸入流、標(biāo)準(zhǔn)輸出流、標(biāo)準(zhǔn)錯(cuò)誤流,假設(shè)linux進(jìn)程不斷

向標(biāo)準(zhǔn)輸出流和標(biāo)準(zhǔn)錯(cuò)誤流寫(xiě)數(shù)據(jù),而JVM卻不讀取,數(shù)據(jù)會(huì)暫存在linux緩存區(qū),當(dāng)緩存區(qū)存滿之后導(dǎo)致該進(jìn)程無(wú)法繼續(xù)寫(xiě)數(shù)據(jù),會(huì)僵死,導(dǎo)致java進(jìn)程會(huì)卡死在waitFor()處,

永遠(yuǎn)無(wú)法結(jié)束。

解決辦法:java進(jìn)程在waitFor()前不斷讀取標(biāo)準(zhǔn)輸出流和標(biāo)準(zhǔn)錯(cuò)誤流:

?? ??? ?//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);
?? ??? ??? ?//讀取標(biāo)準(zhǔn)輸出流
?? ??? ??? ?BufferedReader bufferedReader =new BufferedReader(new InputStreamReader(p0.getInputStream()));
?? ??? ??? ?String line;
?? ??? ??? ?while ((line=bufferedReader.readLine()) != null) {
?? ??? ??? ? ? ?System.out.println(line);
?? ??? ??? ?}?? ?
?? ??? ??? ?//讀取標(biāo)準(zhǔn)錯(cuò)誤流
?? ??? ??? ?BufferedReader brError = new BufferedReader(new InputStreamReader(p0.getErrorStream(), "gb2312"));
?? ??? ??? ?String errline = null;
?? ??? ??? ?while ((errline = brError.readLine()) != null) {
?? ??? ??? ??? ? System.out.println(errline);
?? ??? ??? ?}
?? ??? ??? ?//waitFor()判斷Process進(jìn)程是否終止,通過(guò)返回值判斷是否正常終止。0代表正常終止
?? ??? ??? ?int c=p0.waitFor();
?? ??? ??? ?if(c!=0){
?? ??? ??? ??? ?baseRes.put("desc", "軟件升級(jí)失敗:執(zhí)行zxvf.sh異常終止");
?? ??? ??? ??? ?baseRes.setReturnFlag(false);
?? ??? ??? ??? ?return baseRes;
?? ??? ??? ?}
?? ??? ?} catch (IOException e1) {
?? ??? ??? ?baseRes.put("desc", "軟件升級(jí)失?。何募鈮菏?);
?? ??? ??? ?baseRes.setReturnFlag(false);
?? ??? ??? ?return baseRes;
?? ??? ?} catch (InterruptedException e1) {
?? ??? ??? ?baseRes.put("desc", "軟件升級(jí)失敗:文件解壓失敗");
?? ??? ??? ?baseRes.setReturnFlag(false);
?? ??? ??? ?return baseRes;
?? ??? ?}

也可以在執(zhí)行Runtime.getRuntime().exec(jyName)之后另外再啟動(dòng)兩個(gè)線程分別讀取標(biāo)準(zhǔn)錯(cuò)誤流和標(biāo)準(zhǔn)輸出流

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腳本中有關(guān)聯(lián)腳本,注意路徑

就是shell腳本中還要執(zhí)行其他腳本,這時(shí)候就是注意一個(gè)路徑的問(wèn)題,這個(gè)問(wèn)題也是我找了好長(zhǎng)時(shí)間的一個(gè)問(wèn)題。

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

在Test.java類(lèi)調(diào)用了etc目錄下的a.sh腳本, a.sh腳本中執(zhí)行etc目錄下的b.sh腳本,原來(lái)我在a.sh腳本中寫(xiě)的是./b.sh。其實(shí)這樣linux是找不到b.sh的,因?yàn)槲覀儓?zhí)行是在

Test.class目錄下調(diào)用的/etc/a.sh  所以當(dāng)a.sh中執(zhí)行./b.sh的時(shí)候他會(huì)在Test.class目錄下尋找,所以找不到,所以a.sh中要寫(xiě)成/etc/b.sh

4、java連續(xù)調(diào)用多個(gè)腳本

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

就是這種數(shù)組的方式。

5、java執(zhí)行.sh腳本文件的時(shí)候直接寫(xiě)目錄就行

例如這樣:Runtime.getRuntime().exec(“/etc/a.sh”)

java 直接執(zhí)行語(yǔ)句的時(shí)候需要加上"/bin/sh"  例如這樣:

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

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

最新評(píng)論