java调用本地及远程shell脚本

场景:

在linux服务器上有这样一个脚本文件

/home/xxxx/my_script/run_dev_job_etl_usermonitor_task_list.sh

需求:

在java代码中直接调用此sh脚本文件

方法:

定义一个接口

com.xxx.service.ShellService
在这里插入图片描述

java调用本地shell脚本

@Override
public int exec(String[] cmds) throws Exception {
    String s;
    Process p = Runtime.getRuntime().exec(cmds);
    BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
    BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
    while ((s = stdInput.readLine()) != null) {
        logger.info(s);
    }
    while ((s = stdError.readLine()) != null) {
        logger.error(s);
    }
    try {
        int result = p.waitFor();
        logger.info("执行shell脚本结果:{}",result);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    // 执行成功返回0
    return 0;
}

获取响应字符流方式,阻塞在这里

process = Runtime.getRuntime().exec("tail -f /var/log/syslog");
inputStream = process.getInputStream();

// 一定要启动新的线程,防止InputStream阻塞处理WebSocket的线程
TailLogThread thread = new TailLogThread(inputStream, session);
thread.start();

java通过ssh方式调用远程shell脚本

引入依赖

compile group: 'org.jvnet.hudson', name: 'ganymed-ssh2', version: 'build210-hudson-1'
@Override
public int exec(String[] cmds) throws Exception {
    InputStream stdOut = null;
    InputStream stdErr = null;
    String outStr;
    String outErr;
    int ret;
    try {
        if (login()) {
            // Open a new {@link Session} on this connection
            Session session = connection.openSession();
            // Execute a command on the remote machine.
            session.execCommand(cmds[0]);

            stdOut = new StreamGobbler(session.getStdout());
            outStr = processStream(stdOut, charset);

            stdErr = new StreamGobbler(session.getStderr());
            outErr = processStream(stdErr, charset);

            if (StringUtils.isNotEmpty(outStr)) {
                logger.info("outStr=" + outStr);
            }
            if (StringUtils.isNotEmpty(outErr)) {
                logger.info("outErr=" + outErr);
                // 获取hive执行时长
                String hiveExecutionTime = StringUtils.substringBetween(outErr, "Time taken:", " seconds");
                logger.info("hiveExecutionTime:{}", hiveExecutionTime);
            }

            session.waitForCondition(ChannelCondition.EXIT_STATUS, TIME_OUT);

            // 一般情况下shell脚本正常执行完毕,getExitStatus方法返回0
            ret = session.getExitStatus();
            return ret;
        } else {
            // 自定义异常类 实现略
            throw new Exception("登录远程机器失败" + ip);
        }
    } finally {
        if (connection != null) {
            connection.close();
        }
        IOUtils.closeQuietly(stdOut);
        IOUtils.closeQuietly(stdErr);
    }
}

private boolean login() throws IOException {
    connection = new Connection(ip);
    connection.connect();
    return connection.authenticateWithPassword(username, password);
}

获取响应字符流方式,阻塞在这里

ch.ethz.ssh2.Session sshSession = connection.openSession();
sshSession.execCommand("tail -0f /var/log/prometheus.log");
InputStream inputStream = new StreamGobbler(sshSession.getStdout());

安全注意

需要注意:操作系统命令注入

Java 语言提供了类似 Runtime.exec(…) 的 API,可以用来执行特定命令,假设我们构建了一个应用,以输入文本作为参数,执行下面的命令:

ls –la input_file_name

但是如果用户输入是

input_file_name; rm –rf /*

这就有可能出现问题了。当然,这只是个举例,Java 标准类库本身进行了非常多的改进,所以类似这种编程错误,未必可以真的完成攻击,但其反映的一类场景是真实存在的。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值