您的位置:

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