javashell,JAVA shellevaluate 包含字元串

本文目錄一覽:

怎麼通過java去調用並執行shell腳本以及問題總結

對於第一個問題: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;

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

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();

我們發現,通過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) {

}

記得在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

原來是因為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;

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

如果是通過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);

EnumerationJarEntry 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();

java怎麼執行shell腳本

如果shell腳本和java程序運行在不同的伺服器上,可以使用遠程執行Linux命令執行包,使用ssh2協議連接遠程伺服器,並發送執行命令就行了,ganymed.ssh2相關mave配置如下,你可以自己百度搜索相關資料。

如果shell腳本和java程序在同一台伺服器上,

這裡不得不提到java的process類了。

process這個類是一個抽象類,封裝了一個進程(你在調用linux的命令或者shell腳本就是為了執行一個在linux下執行的程序,所以應該使用process類)。

process類提供了執行從進程輸入,執行輸出到進程,等待進程完成,檢查進程的推出狀態,以及shut down掉進程。

dependency  

  groupIdcom.ganymed.ssh2/groupId  

  artifactIdganymed-ssh2-build/artifactId  

  version210/version  

 /dependency

本地執行命令代碼如下:

String shpath=”/test/test.sh”;   //程序路徑

    Process process =null;

    String command1 = 「chmod 777 」 + shpath;

    process = Runtime.getRuntime().exec(command1);

    process.waitFor();

java如何與shell實現交互?

互動式模式就是shell等待你的輸入,並且執行你提交的命令。

這種模式被稱作互動式是因為shell與用戶進行交互。這種模式也是大多數用戶非常熟悉的:登錄、執行一些命令、簽退。當你簽退後,shell也終止了。

shell也可以運行在另外一種模式:非互動式模式。在這種模式下,shell不與你進行交互,而是讀取存放在文件中的命令,並且執行它們。當它讀到文件的結尾,shell也就終止了。

如何在java中執行shell腳本

// 用法:Runtime.getRuntime().exec(“命令”);

String shpath=”/test/test.sh”; //程序路徑

Process process =null;

String command1 = 「chmod 777 」 + shpath;

try {

Runtime.getRuntime().exec(command1 ).waitFor();

} catch (IOException e1) {

e1.printStackTrace();

}catch (InterruptedException e) {

e.printStackTrace();

}

String var=”201102″; /參數

String command2 = 「/a href=”;tn=44039180_cprfenlei=mv6quAkxTZn0IZRqIHckPjm4nH00T1YkuARkryDYnjfYn1T3rjnd0ZwV5Hcvrjm3rH6sPfKWUMw85HfYnjn4nH6sgvPsT6KdThsqpZwYTjCEQLGCpyw9Uz4Bmy-bIi4WUvYETgN-TLwGUv3EPjRdrHfYrHc3n104PW0znWfd” target=”_blank” class=”baidu-highlight”bin/a/sh 」 + shpath + 」 」 + var;

Runtime.getRuntime().exec(command2).waitFor();

請教個java調用shell命令操作

近日項目中有這樣一個需求:系統中的外幣資金調度完成以後,要將調度信息生成一個Txt文件,然後將這個Txt文件發送到另外一個系統(Kondor)中。生成文件自然使用OutputStreamWirter了,發送文件有兩種方式,一種是用寫個一個類似於FTP功能的程序,另外一種就是使用Java來調用Shell,在Shell中完成文件的發送操作。我們選擇後一種,即當完成外幣資金的調度工作後,用Java的OutputStreamWriter來生成一個Txt文件,然後用Java來調用Shell腳本,在Shell腳本中完成FTP文件到Kondor系統的工作。

以下為Java程序JavaShellUtil.java:import java.io.BufferedReader;

import java.io.File;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStreamReader;

import java.io.OutputStream;

import java.io.OutputStreamWriter;

import java.text.DateFormat;

import java.text.SimpleDateFormat;

import java.util.Date;

public class JavaShellUtil {

//基本路徑

private static final String basePath = “/tmp/”;

//記錄Shell執行狀況的日誌文件的位置(絕對路徑)

private static final String executeShellLogFile = basePath + “executeShell.log”;

//發送文件到Kondor系統的Shell的文件名(絕對路徑)

private static final String sendKondorShellName = basePath + “sendKondorFile.sh”;

public int executeShell(String shellCommand) throws IOException {

int success = 0;

StringBuffer stringBuffer = new StringBuffer();

BufferedReader bufferedReader = null;

//格式化日期時間,記錄日誌時使用

DateFormat dateFormat = new SimpleDateFormat(“yyyy-MM-dd HH:mm:SS “);

try {

stringBuffer.append(dateFormat.format(new Date())).append(“準備執行Shell命令 “).append(shellCommand).append(” \r\n”);

Process pid = null;

String[] cmd = {“/bin/sh”, “-c”, shellCommand};

//執行Shell命令

pid = Runtime.getRuntime().exec(cmd);

if (pid != null) {

stringBuffer.append(“進程號:”).append(pid.toString()).append(“\r\n”);

//bufferedReader用於讀取Shell的輸出內容 bufferedReader = new BufferedReader(new InputStreamReader(pid.getInputStream()), 1024);

pid.waitFor();

} else {

stringBuffer.append(“沒有pid\r\n”);

}

stringBuffer.append(dateFormat.format(new Date())).append(“Shell命令執行完畢\r\n執行結果為:\r\n”);

String line = null;

//讀取Shell的輸出內容,並添加到stringBuffer中

while (bufferedReader != null

(line = bufferedReader.readLine()) != null) {

stringBuffer.append(line).append(“\r\n”);

}

} catch (Exception ioe) {

stringBuffer.append(“執行Shell命令時發生異常:\r\n”).append(ioe.getMessage()).append(“\r\n”);

} finally {

if (bufferedReader != null) {

OutputStreamWriter outputStreamWriter = null;

try {

bufferedReader.close();

//將Shell的執行情況輸出到日誌文件中

OutputStream outputStream = new FileOutputStream(executeShellLogFile);

outputStreamWriter = new OutputStreamWriter(outputStream, “UTF-8”);

outputStreamWriter.write(stringBuffer.toString());

} catch (Exception e) {

e.printStackTrace();

} finally {

outputStreamWriter.close();

}

}

success = 1;

}

return success;

}

}

以下是Shell腳本sendKondorFile.sh,該Shell腳本的作用是FTP文件到指定的位置:

#!/bin/sh

#日誌文件的位置

logFile=”/opt/fms2_kondor/sendKondorFile.log”

#Kondor系統的IP地址,會將生成的文件發送到這個地址

kondor_ip=192.168.1.200

#FTP用戶名

ftp_username=kondor

#FTP密碼

ftp_password=kondor

#要發送的文件的絕對路徑

filePath=””

#要發送的文件的文件名

fileName=””

#如果Shell命令帶有參數,則將第一個參數賦給filePath,將第二個參數賦給fileName

if [ $# -ge “1” ]

then

filePath=$1

else

echo “沒有文件路徑”

echo “沒有文件路徑\n”

$logFile

return

fi

if [ $# -ge “2” ]

then

fileName=$2

else

echo “沒有文件名”

echo “沒有文件名\n”

$logFile

return

fi

echo “要發送的文件是 ${filePath}/${fileName}”

cd ${filePath}

ls $fileName

if (test $? -eq 0)

then

echo “準備發送文件:${filePath}/${fileName}”

else

echo “文件 ${filePath}/${fileName} 不存在”

echo “文件 ${filePath}/${fileName} 不存在\n”

$logFile

return

fi

ftp -n ${kondor_ip}

_end

user ${ftp_username} ${ftp_password}

asc

prompt

put $fileName

bye

_end

echo “`date +%Y-%m-%d’ ‘%H:%M:%S` 發送了文件 ${filePath}/${fileName}”

echo “`date +%Y-%m-%d’ ‘%H:%M:%S` 發送了文件 ${filePath}/${fileName}\n”

$logFile

調用方法為:

JavaShellUtil javaShellUtil = new JavaShellUtil();

//參數為要執行的Shell命令,即通過調用Shell腳本sendKondorFile.sh將/temp目錄下的tmp.pdf文件發送到192.168.1.200上

int success = javaShellUtil.executeShell(“sh /tmp/sendKondorFile.sh /temp tmp.pdf”);

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/152038.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-11-12 00:54
下一篇 2024-11-12 00:54

相關推薦

  • java client.getacsresponse 編譯報錯解決方法

    java client.getacsresponse 編譯報錯是Java編程過程中常見的錯誤,常見的原因是代碼的語法錯誤、類庫依賴問題和編譯環境的配置問題。下面將從多個方面進行分析…

    編程 2025-04-29
  • Java JsonPath 效率優化指南

    本篇文章將深入探討Java JsonPath的效率問題,並提供一些優化方案。 一、JsonPath 簡介 JsonPath是一個可用於從JSON數據中獲取信息的庫。它提供了一種DS…

    編程 2025-04-29
  • Java騰訊雲音視頻對接

    本文旨在從多個方面詳細闡述Java騰訊雲音視頻對接,提供完整的代碼示例。 一、騰訊雲音視頻介紹 騰訊雲音視頻服務(Cloud Tencent Real-Time Communica…

    編程 2025-04-29
  • Java Bean載入過程

    Java Bean載入過程涉及到類載入器、反射機制和Java虛擬機的執行過程。在本文中,將從這三個方面詳細闡述Java Bean載入的過程。 一、類載入器 類載入器是Java虛擬機…

    編程 2025-04-29
  • Python字元串寬度不限制怎麼打代碼

    本文將為大家詳細介紹Python字元串寬度不限制時如何打代碼的幾個方面。 一、保持代碼風格的統一 在Python字元串寬度不限制的情況下,我們可以寫出很長很長的一行代碼。但是,為了…

    編程 2025-04-29
  • Java Milvus SearchParam withoutFields用法介紹

    本文將詳細介紹Java Milvus SearchParam withoutFields的相關知識和用法。 一、什麼是Java Milvus SearchParam without…

    編程 2025-04-29
  • Python中將字元串轉化為浮點數

    本文將介紹在Python中將字元串轉化為浮點數的常用方法。在介紹方法之前,我們先來思考一下這個問題應該如何解決。 一、eval函數 在Python中,最簡單、最常用的將字元串轉化為…

    編程 2025-04-29
  • Java 8中某一周的周一

    Java 8是Java語言中的一個版本,於2014年3月18日發布。本文將從多個方面對Java 8中某一周的周一進行詳細的闡述。 一、數組處理 Java 8新特性之一是Stream…

    編程 2025-04-29
  • Java判斷字元串是否存在多個

    本文將從以下幾個方面詳細闡述如何使用Java判斷一個字元串中是否存在多個指定字元: 一、字元串遍歷 字元串是Java編程中非常重要的一種數據類型。要判斷字元串中是否存在多個指定字元…

    編程 2025-04-29
  • VSCode為什麼無法運行Java

    解答:VSCode無法運行Java是因為默認情況下,VSCode並沒有集成Java運行環境,需要手動添加Java運行環境或安裝相關插件才能實現Java代碼的編寫、調試和運行。 一、…

    編程 2025-04-29

發表回復

登錄後才能評論