日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

怎么通过java去调用并执行shell脚本以及问题总结

發布時間:2025/3/15 编程问答 15 豆豆
生活随笔 收集整理的這篇文章主要介紹了 怎么通过java去调用并执行shell脚本以及问题总结 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

原文

https://blog.satikey.com/p/5759/how-java-calls-and-executes-shell-scripts-and-summary.html

主題?Shell?Java

背景

我們在開發過程中,大部分是java開發, 而在文本處理過程中,主要就是腳本進行開發。 java開發的特點就是我們可以很早地進行TDDL, METAQ 等等地對接; 而腳本開發的特點就是在進行批處理的時候非常方便。 前陣子我遇到這么一個需求場景: 對抓取的數據進行打包, 后來又遇到我要通過腳本進行抓取,比如nodejs下基于phantomjs的casperjs爬蟲。

解決方法

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

java調用shell的方法

通過ProcessBuilder進行調度

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

ProcessBuilderpb = 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; 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;

這里有必要解釋一下幾個參數:

RUNNING_SHELL_FILE:要運行的腳本

SHELL_FILE_DIR:要運行的腳本所在的目錄; 當然你也可以把要運行的腳本寫成全路徑。

runningStatus:運行狀態,0標識正常。 詳細可以看java文檔。

param1, param2, param3:可以在RUNNING_SHELL_FILE腳本中直接通過1,2,$3分別拿到的參數。

直接通過系統Runtime執行shell

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

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

我們發現,通過Runtime的方式并沒有builder那么方便,特別是參數方面,必須自己加空格分開,因為exec會把整個字符串作為shell運行。

可能存在的問題以及解決方法

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

沒權限運行

這個情況我們團隊的朱東方就遇到了, 在做DTS遷移的過程中,要執行包里面的shell腳本, 解壓出來了之后,發現執行不了。 那么就按照上面的方法授權吧

java進行一直等待shell返回

這個問題估計更加經常遇到。 原因是, shell腳本中有echo或者print輸出, 導致緩沖區被用完了! 為了避免這種情況, 一定要把緩沖區讀一下, 好處就是,可以對shell的具體運行狀態進行log出來。 比如上面我的例子中我會變成:

ProcessBuilderpb = 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();BufferedReaderstdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));BufferedReaderstdError = 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) {} 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();BufferedReaderstdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));BufferedReaderstdError = 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()之前把緩沖區讀出來打log, 就可以看到你的shell為什么會沒有按照預期運行。 這個還有一個好處是,可以讀shell里面輸出的結果, 方便java代碼進一步操作。

也許你還會遇到這個問題,明明手工可以運行的命令,java調用的shell中某一些命令居然不能執行,報錯:命令不存在!

比如我在使用casperjs的時候,手工去執行shell明明是可以執行的,但是java調用的時候,發現總是出錯。 通過讀取緩沖區就能發現錯誤日志了。 我發現即便自己把安裝的casperjs的bin已經加入了path中(/etc/profile, 各種bashrc中)還不夠。 比如:

exportNODE_HOME="/home/admin/node" exportCASPERJS_HOME="/home/admin/casperjs" exportPHANTOMJS_HOME="/home/admin/phantomjs" exportPATH=$PATH:$JAVA_HOME/bin:/root/bin:$NODE_HOME/bin:$CASPERJS_HOME/bin:$PHANTOMJS_HOME/bin ="/home/admin/node" exportCASPERJS_HOME="/home/admin/casperjs" exportPHANTOMJS_HOME="/home/admin/phantomjs" exportPATH=$PATH:$JAVA_HOME/bin:/root/bin:$NODE_HOME/bin:$CASPERJS_HOME/bin:$PHANTOMJS_HOME/bin

原來是因為java在調用shell的時候,默認用的是系統的/bin/下的指令。特別是你用root權限運行的時候。 這時候,你要在/bin下加軟鏈了。針對我上面的例子,就要在/bin下加軟鏈:

ln -s /home/admin/casperjs/bin/casperjscasperjs; ln -s /home/admin/node/bin/nodenode; ln -s /home/admin/phantomjs/bin/phantomjsphantomjs; /home/admin/casperjs/bin/casperjscasperjs; ln -s /home/admin/node/bin/nodenode; ln -s /home/admin/phantomjs/bin/phantomjsphantomjs;

這樣,問題就可以解決了。

如果是通過java調用shell進行打包,那么要注意路徑的問題了

因為shell里面tar的壓縮和解壓可不能直接寫:

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

直接給你報錯,因為tar的壓縮源必須到路徑下面, 因此可以寫成

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

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

答案是:解壓出來。再按照上面指示進行操作。(1)找到路徑

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

對文件處理的方法就簡單了,直接touch一個臨時文件,然后把數據流寫入,代碼:

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

有這個這個東東,相信大家會減少踩坑,而且大膽地使用java和腳本之間的交互吧。 java可以調用shell,那么shell再調用其他就方便了。 記得一點, 不要過度地依賴緩沖區進行線程之間的通信。原因自己去學習吧。

via:?https://yq.aliyun.com/articles/2362

?

學習地址:https://www.tuicool.com/articles/quIVvaB

總結

以上是生活随笔為你收集整理的怎么通过java去调用并执行shell脚本以及问题总结的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 男人网站在线观看 | 欧美tickle狂笑裸体vk | 中字幕视频在线永久在线观看免费 | 婷婷精品进入 | 思思在线视频 | 青娱乐国产精品 | 香港台湾日本三级大全 | √资源天堂中文在线视频 | 中日精品一色哟哟 | 九九自拍偷拍 | 国产专区欧美专区 | 日韩av女优在线观看 | 69人妻精品久久无人专区 | 亚洲一区欧美日韩 | 三级黄色片免费 | 久久人人人 | 国产精品久久久久久久久借妻 | 亚洲欧美日韩一区二区三区在线观看 | 成片免费观看视频 | 国产精品视频免费网站 | 欧美成a | 大肉大捧一进一出好爽视频 | 国产麻豆剧果冻传媒白晶晶 | 96超碰在线 | 日本高清中文字幕 | 91免费精品视频 | 摸摸摸bbb毛毛毛片 午夜爽爽影院 | 丝袜调教91porn | 日韩av有码 | av中文字幕亚洲 | av在线播放一区 | 欧美极品少妇xxxxⅹ免费视频 | 日本久久精品 | 国产成人自拍一区 | 色屁屁网站 | 爱综合网 | 国产精品51麻豆cm传媒 | 亚洲AV成人无码电影在线观看 | 成人国产在线 | 欧美日韩国产免费观看 | 国产精品腿扒开做爽爽爽挤奶网站 | av在线收看 | 夜夜操天天 | 国产精品成人一区二区三区 | 欧洲av网站| 一区二区三区精 | 骚视频在线观看 | 日本成人免费在线 | 999在线视频| 国产污视频在线播放 | 亚洲夜夜操 | 国产精品桃色 | 日本一级做a爱片 | 青草福利视频 | 制服 丝袜 综合 日韩 欧美 | 天天躁日日躁狠狠很躁 | 巨乳美女在线 | 91黄色在线观看 | 911看片| 久久午夜神器 | 亚洲黄页网站 | 亚洲色成人网站www永久四虎 | 国产精品国产av | 动漫av在线 | 亚洲永久视频 | 国产精品99久久久久久宅男 | 伊人狠狠操 | 草民午夜理伦三级 | 久久久精品人妻无码专区 | 欧美激情欧美激情在线五月 | 日本久久高清 | 亚洲午夜久久久久久久久红桃 | 亚洲精品一区二区三区影院忠贞 | 成人性生交大片免费看 | 青青艹在线视频 | 欧美特级黄 | 在线色av| 淫久久| 国产免费一区二区三区最新6 | 日韩一级黄色片 | 国产一区二区三区视频 | 精品少妇一区二区三区在线观看 | 牛牛超碰| 亚洲卡一卡二 | 成人超碰在线 | 国产无套内射又大又猛又粗又爽 | 国产91在线播放九色 | 色综合99久久久无码国产精品 | 国产精品精东影业 | 色综合天天综合网天天看片 | 高潮网 | 久热中文字幕 | 国产性自拍 | 暗呦丨小u女国产精品 | www.尤物 | 日韩精品一区二区不卡 | 亚洲精品一二三 | 日韩精品免费电影 | 日日操天天操 |