最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java程序去調(diào)用并執(zhí)行shell腳本及問(wèn)題總結(jié)(推薦)

 更新時(shí)間:2020年06月12日 17:29:54   作者:vcfriend  
這篇文章主要介紹了Java程序去調(diào)用并執(zhí)行shell腳本及問(wèn)題總結(jié),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

摘要: 該文章來(lái)自阿里巴巴技術(shù)協(xié)會(huì)(ATA)精選集 背景 我們?cè)陂_(kāi)發(fā)過(guò)程中,大部分是java開(kāi)發(fā), 而在文本處理過(guò)程中,主要就是腳本進(jìn)行開(kāi)發(fā)。 java開(kāi)發(fā)的特點(diǎn)就是我們可以很早地進(jìn)行TDDL, METAQ 等等地對(duì)接; 而腳本開(kāi)發(fā)的特點(diǎn)就是在進(jìn)行批處理的時(shí)候非常方便。

背景

我們?cè)陂_(kāi)發(fā)過(guò)程中,大部分是java開(kāi)發(fā), 而在文本處理過(guò)程中,主要就是腳本進(jìn)行開(kāi)發(fā)。 java開(kāi)發(fā)的特點(diǎn)就是我們可以很早地進(jìn)行TDDL, METAQ 等等地對(duì)接; 而腳本開(kāi)發(fā)的特點(diǎn)就是在進(jìn)行批處理的時(shí)候非常方便。 前陣子我遇到這么一個(gè)需求場(chǎng)景: 對(duì)抓取的數(shù)據(jù)進(jìn)行打包, 后來(lái)又遇到我要通過(guò)腳本進(jìn)行抓取,比如nodejs下基于phantomjs的casperjs爬蟲。

解決方法

對(duì)于第一個(gè)問(wèn)題:java抓取,并且把結(jié)果打包。
那么比較直接的做法就是,java接收各種消息(db,metaq等等),然后借助于jstorm集群進(jìn)行調(diào)度和抓取。 最后把抓取的結(jié)果保存到一個(gè)文件中,并且通過(guò)調(diào)用shell打包, 回傳。 也許有同學(xué)會(huì)問(wèn), 為什么不直接把java調(diào)用odps直接保存文件,答案是,我們的集群不是hz集群,直接上傳odps速度很有問(wèn)題,因此先打包比較合適。(這里不糾結(jié)設(shè)計(jì)了,我們回到正題)

java調(diào)用shell的方法

通過(guò)ProcessBuilder進(jìn)行調(diào)度

這種方法比較直觀,而且參數(shù)的設(shè)置也比較方便, 比如我在實(shí)踐中的代碼(我隱藏了部分業(yè)務(wù)代碼):

ProcessBuilder pb = new ProcessBuilder("./" + RUNNING_SHELL_FILE, param1,
            param2, param3);
  pb.directory(new File(SHELL_FILE_DIR));
  int runningStatus = 0;
  String s = null;
  try {
   Process p = pb.start();
   try {
    runningStatus = p.waitFor();
   } catch (InterruptedException e) {
   }
 
  } catch (IOException e) {
  }
  if (runningStatus != 0) {
  }
  return;

這里有必要解釋一下幾個(gè)參數(shù):

RUNNING_SHELL_FILE:要運(yùn)行的腳本
SHELL_FILE_DIR:要運(yùn)行的腳本所在的目錄; 當(dāng)然你也可以把要運(yùn)行的腳本寫成全路徑。
runningStatus:運(yùn)行狀態(tài),0標(biāo)識(shí)正常。 詳細(xì)可以看java文檔。
param1, param2, param3:可以在RUNNING_SHELL_FILE腳本中直接通過(guò)1,2,$3分別拿到的參數(shù)。

直接通過(guò)系統(tǒng)Runtime執(zhí)行shell

這個(gè)方法比較暴力,也比較常用, 代碼如下:

p = Runtime.getRuntime().exec(SHELL_FILE_DIR + RUNNING_SHELL_FILE + " "+param1+" "+param2+" "+param3);
p.waitFor();

我們發(fā)現(xiàn),通過(guò)Runtime的方式并沒(méi)有builder那么方便,特別是參數(shù)方面,必須自己加空格分開(kāi),因?yàn)閑xec會(huì)把整個(gè)字符串作為shell運(yùn)行。

可能存在的問(wèn)題以及解決方法

如果你覺(jué)得通過(guò)上面就能滿足你的需求,那么可能是要碰壁了。你會(huì)遇到以下情況。

沒(méi)權(quán)限運(yùn)行

這個(gè)情況我們團(tuán)隊(duì)的朱東方就遇到了, 在做DTS遷移的過(guò)程中,要執(zhí)行包里面的shell腳本, 解壓出來(lái)了之后,發(fā)現(xiàn)執(zhí)行不了。 那么就按照上面的方法授權(quán)吧

ProcessBuilder builder = new ProcessBuilder("/bin/chmod", "755", tempFile.getPath());
   Process process = builder.start();
   int rc = process.waitFor();

java進(jìn)行一直等待shell返回

這個(gè)問(wèn)題估計(jì)更加經(jīng)常遇到。 原因是, shell腳本中有echo或者print輸出, 導(dǎo)致緩沖區(qū)被用完了! 為了避免這種情況, 一定要把緩沖區(qū)讀一下, 好處就是,可以對(duì)shell的具體運(yùn)行狀態(tài)進(jìn)行l(wèi)og出來(lái)。 比如上面我的例子中我會(huì)變成:

ProcessBuilder pb = new ProcessBuilder("./" + RUNNING_SHELL_FILE, keyword.trim(),
            taskId.toString(), fileName);
  pb.directory(new File(CASPERJS_FILE_DIR));
  int runningStatus = 0;
  String s = null;
  try {
   Process p = pb.start();
   BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
   BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
   while ((s = stdInput.readLine()) != null) {
    LOG.error(s);
   }
   while ((s = stdError.readLine()) != null) {
    LOG.error(s);
   }
   try {
    runningStatus = p.waitFor();
   } catch (InterruptedException e) {
   } 

記得在start()之后, waitFor()之前把緩沖區(qū)讀出來(lái)打log, 就可以看到你的shell為什么會(huì)沒(méi)有按照預(yù)期運(yùn)行。 這個(gè)還有一個(gè)好處是,可以讀shell里面輸出的結(jié)果, 方便java代碼進(jìn)一步操作。

也許你還會(huì)遇到這個(gè)問(wèn)題,明明手工可以運(yùn)行的命令,java調(diào)用的shell中某一些命令居然不能執(zhí)行,報(bào)錯(cuò):命令不存在!

比如我在使用casperjs的時(shí)候,手工去執(zhí)行shell明明是可以執(zhí)行的,但是java調(diào)用的時(shí)候,發(fā)現(xiàn)總是出錯(cuò)。 通過(guò)讀取緩沖區(qū)就能發(fā)現(xiàn)錯(cuò)誤日志了。 我發(fā)現(xiàn)即便自己把安裝的casperjs的bin已經(jīng)加入了path中(/etc/profile, 各種bashrc中)還不夠。 比如:

export NODE_HOME="/home/admin/node"
export CASPERJS_HOME="/home/admin/casperjs"
export PHANTOMJS_HOME="/home/admin/phantomjs"
export PATH=$PATH:$JAVA_HOME/bin:/root/bin:$NODE_HOME/bin:$CASPERJS_HOME/bin:$PHANTOMJS_HOME/bin

原來(lái)是因?yàn)閖ava在調(diào)用shell的時(shí)候,默認(rèn)用的是系統(tǒng)的/bin/下的指令。特別是你用root權(quán)限運(yùn)行的時(shí)候。 這時(shí)候,你要在/bin下加軟鏈了。針對(duì)我上面的例子,就要在/bin下加軟鏈:

ln -s /home/admin/casperjs/bin/casperjs casperjs;
ln -s /home/admin/node/bin/node node;
ln -s /home/admin/phantomjs/bin/phantomjs phantomjs;

這樣,問(wèn)題就可以解決了。

如果是通過(guò)java調(diào)用shell進(jìn)行打包,那么要注意路徑的問(wèn)題了

因?yàn)閟hell里面tar的壓縮和解壓可不能直接寫:

tar -zcf /home/admin/data/result.tar.gz /home/admin/data/result

直接給你報(bào)錯(cuò),因?yàn)閠ar的壓縮源必須到路徑下面, 因此可以寫成

tar -zcf /home/admin/data/result.tar.gz -C /home/admin/data/ result

如果我的shell是在jar包中怎么辦?

答案是:解壓出來(lái)。再按照上面指示進(jìn)行操作。

(1)找到路徑

String jarPath = findClassJarPath(ClassLoaderUtil.class);
  JarFile topLevelJarFile = null;
  try {
   topLevelJarFile = new JarFile(jarPath);
   Enumeration<JarEntry> entries = topLevelJarFile.entries();
   while (entries.hasMoreElements()) {
    JarEntry entry = entries.nextElement();
    if (!entry.isDirectory() && entry.getName().endsWith(".sh")) {
     對(duì)你的shell文件進(jìn)行處理
    }
   }

對(duì)文件處理的方法就簡(jiǎn)單了,直接touch一個(gè)臨時(shí)文件,然后把數(shù)據(jù)流寫入,代碼:

FileUtils.touch(tempjline);
tempjline.deleteOnExit();
FileOutputStream fos = new FileOutputStream(tempjline);
IOUtils.copy(ClassLoaderUtil.class.getResourceAsStream(r), fos);
fos.close();

有這個(gè)這個(gè)東東,相信大家會(huì)減少踩坑,而且大膽地使用java和腳本之間的交互吧。 java可以調(diào)用shell,那么shell再調(diào)用其他就方便了。 記得一點(diǎn), 不要過(guò)度地依賴緩沖區(qū)進(jìn)行線程之間的通信。原因自己去學(xué)習(xí)吧。

總結(jié)

到此這篇關(guān)于Java程序去調(diào)用并執(zhí)行shell腳本及問(wèn)題總結(jié)的文章就介紹到這了,更多相關(guān)java調(diào)用并執(zhí)行shell腳本內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java中@ConfigurationProperties實(shí)現(xiàn)自定義配置綁定問(wèn)題分析

    Java中@ConfigurationProperties實(shí)現(xiàn)自定義配置綁定問(wèn)題分析

    這篇文章主要介紹了@ConfigurationProperties實(shí)現(xiàn)自定義配置綁定問(wèn)題,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-08-08
  • 如何解決IDEA git拉取代碼后本地代碼莫名消失的問(wèn)題

    如何解決IDEA git拉取代碼后本地代碼莫名消失的問(wèn)題

    這篇文章主要介紹了如何解決IDEA git拉取代碼后本地代碼莫名消失的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • Java面試高頻問(wèn)題之RabbitMQ系列全面解析

    Java面試高頻問(wèn)題之RabbitMQ系列全面解析

    在介紹RabbitMQ之前實(shí)現(xiàn)要介紹一下MQ,MQ是什么?MQ全稱是Message Queue,可以理解為消息隊(duì)列的意思,簡(jiǎn)單來(lái)說(shuō)就是消息以管道的方式進(jìn)行傳遞。RabbitMQ是一個(gè)實(shí)現(xiàn)了AMQP(Advanced Message Queuing Protocol)高級(jí)消息隊(duì)列協(xié)議的消息隊(duì)列服務(wù),用Erlang語(yǔ)言的
    2021-11-11
  • Java?數(shù)據(jù)結(jié)構(gòu)與算法系列精講之漢諾塔

    Java?數(shù)據(jù)結(jié)構(gòu)與算法系列精講之漢諾塔

    漢諾塔是源于印度一個(gè)古老傳說(shuō)的益智玩具。大梵天創(chuàng)造世界時(shí)做了三根石柱,在一根柱子上從下往上按大小順序摞著64片黃金圓盤。大梵天命令婆羅門把圓盤從下面開(kāi)始按大小順序重新擺放在另一根柱子上。并且規(guī)定,在小圓盤上不能放大圓盤,三根柱子之間一次只能移動(dòng)一個(gè)圓盤
    2022-02-02
  • springboot 之jpa高級(jí)查詢操作

    springboot 之jpa高級(jí)查詢操作

    這篇文章主要介紹了springboot 之jpa高級(jí)查詢操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-01-01
  • java開(kāi)發(fā)主流定時(shí)任務(wù)解決方案全橫評(píng)詳解

    java開(kāi)發(fā)主流定時(shí)任務(wù)解決方案全橫評(píng)詳解

    這篇文章主要為大家介紹了java開(kāi)發(fā)主流定時(shí)任務(wù)解決方案全橫評(píng)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • 堆排序算法的講解及Java版實(shí)現(xiàn)

    堆排序算法的講解及Java版實(shí)現(xiàn)

    這篇文章主要介紹了堆排序算法的講解及Java版實(shí)現(xiàn),堆排序基于堆這種數(shù)據(jù)結(jié)構(gòu),在本文中對(duì)堆的概念也有補(bǔ)充介紹,需要的朋友可以參考下
    2016-05-05
  • SpringBoot高版本修改為低版本時(shí)測(cè)試類報(bào)錯(cuò)的解決方案

    SpringBoot高版本修改為低版本時(shí)測(cè)試類報(bào)錯(cuò)的解決方案

    這篇文章主要介紹了SpringBoot高版本修改為低版本時(shí)測(cè)試類報(bào)錯(cuò)的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • Java 畫時(shí)鐘遇到的問(wèn)題及解決方案

    Java 畫時(shí)鐘遇到的問(wèn)題及解決方案

    我是一個(gè)剛?cè)腴T的小菜鳥,希望我寫的東西可以幫助和我一樣剛?cè)腴T的兄弟們少走一些彎路,也希望大佬們可以多指點(diǎn)指點(diǎn)我。感謝!解決在畫時(shí)鐘遇到的問(wèn)題讓我花費(fèi)不少時(shí)間...說(shuō)兩個(gè)困擾我比較久的
    2021-11-11
  • SpringBoot項(xiàng)目使用jasypt加解密的方法

    SpringBoot項(xiàng)目使用jasypt加解密的方法

    jasypt是一個(gè)通用的加解密庫(kù),我們可以使用它在配置文件中對(duì)數(shù)據(jù)庫(kù)密碼進(jìn)行加密,以確保其安全性,接下來(lái)通過(guò)本文給大家介紹SpringBoot項(xiàng)目使用jasypt加解密的方法,感興趣的朋友一起看看吧
    2022-05-05

最新評(píng)論

通许县| 阿城市| 绥德县| 台江县| 延安市| 陈巴尔虎旗| 鱼台县| 微山县| 沧源| 沧州市| 璧山县| 博湖县| 南丹县| 武清区| 宜章县| 西乡县| 道真| 醴陵市| 迭部县| 昆山市| 阜城县| 竹北市| 晋城| 湘西| 石棉县| 衡水市| 聂拉木县| 六枝特区| 阆中市| 古丈县| 塔城市| 临桂县| 溆浦县| 望都县| 库尔勒市| 海原县| 无极县| 浦县| 乌拉特后旗| 五寨县| 无棣县|