springboot通过接口执行本地shell脚本

这篇具有很好参考价值的文章主要介绍了springboot通过接口执行本地shell脚本。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

首先创建springboot项目
shell脚本
这里是执行本地脚本

#!/bin/sh
 echo 'Hello World!'

然后编写执行shell脚本的util类

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

public class ShellUtils {

    /**
     * @param pathOrCommand 脚本路径或者命令
     * @return
     */
    public static List<String> exceShell(String pathOrCommand) {
        List<String> result = new ArrayList<>();

        try {
            // 执行脚本
            Process ps = Runtime.getRuntime().exec(pathOrCommand);
            int exitValue = ps.waitFor();
            if (0 != exitValue) {
                System.out.println("call shell failed. error code is :" + exitValue);
            }

            // 只能接收脚本echo打印的数据,并且是echo打印的最后一次数据
            BufferedInputStream in = new BufferedInputStream(ps.getInputStream());
            BufferedReader br = new BufferedReader(new InputStreamReader(in));
            String line;
            while ((line = br.readLine()) != null) {
                System.out.println("脚本返回的数据如下: " + line);
                result.add(line);
            }
            in.close();
            br.close();

        } catch (Exception e) {
            e.printStackTrace();
        }

        return result;
    }
}

最后开发接口调用此类


@RestController
@RequestMapping("/shell/test")
public class ShellTestController {

    @GetMapping("/shell")
    public List<String> shellTest(){
        List<String> list = ShellUtils.exceShell("/home/shelltest/test.sh");
        return list;
    }
}

如何执行远程脚本
在这里我试用了三种方式,实现远程脚本的执行
但是使用ssh2时

java.io.IOException: Key exchange was not finished, connection is closed.
	at ch.ethz.ssh2.transport.KexManager.getOrWaitForConnectionInfo(KexManager.java:75)
	at ch.ethz.ssh2.transport.TransportManager.getConnectionInfo(TransportManager.java:169)
	at ch.ethz.ssh2.Connection.connect(Connection.java:759)
	at ch.ethz.ssh2.Connection.connect(Connection.java:628)
	at com.zhou.util.SSHClient.login(SSHClient.java:39)
	at com.zhou.util.SSHClient.exec(SSHClient.java:47)
	at com.zhou.util.SSHClient.main(SSHClient.java:76)
Caused by: java.io.IOException: Cannot negotiate, proposals do not match.
	at ch.ethz.ssh2.transport.ClientKexManager.handleMessage(ClientKexManager.java:123)
	at ch.ethz.ssh2.transport.TransportManager.receiveLoop(TransportManager.java:572)
	at ch.ethz.ssh2.transport.TransportManager$1.run(TransportManager.java:261)
	at java.lang.Thread.run(Thread.java:745)

会抛出上述的异常,大体的意思就是密钥交换算法不匹配,导致连接失败。
但是老版本的centos系统还是可以使用的
springboot通过接口执行本地shell脚本,问题杂谈,spring boot,shell
此版本使用没有问题 ,下面是代码
引入的maven

        <dependency>
            <groupId>ch.ethz.ganymed</groupId>
            <artifactId>ganymed-ssh2</artifactId>
            <version>262</version>
        </dependency>
package com.zhou.util;

import ch.ethz.ssh2.ChannelCondition;
import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.Session;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;

public class SSHClient {
    private String ip;
    private String username;
    private String password;

    private String charset = Charset.defaultCharset().toString();
    private static final int TIME_OUT = 1000 * 5 * 60;

    private Connection conn;

    public SSHClient(String ip, String username, String password) {
        this.ip = ip;
        this.username = username;
        this.password = password;
    }

    /**
     * 登录指远程服务器
     * @return
     * @throws IOException
     */
    private boolean login() throws IOException {
        conn = new Connection(ip);
        conn.connect();
        return conn.authenticateWithPassword(username, password);
    }

    public List<String> exec(String shell) throws Exception {
        List<String> result = new ArrayList<>();
        int ret = -1;
        try {
            if (login()) {
                Session session = conn.openSession();
                session.execCommand(shell);
                session.waitForCondition(ChannelCondition.EXIT_STATUS, TIME_OUT);
                ret = session.getExitStatus();
                // 只能接收脚本echo打印的数据,并且是echo打印的最后一次数据
                BufferedInputStream in = new BufferedInputStream(session.getStdout());
                BufferedReader br = new BufferedReader(new InputStreamReader(in));
                String line;
                while ((line = br.readLine()) != null) {
                    System.out.println("脚本返回的数据如下: " + line);
                    result.add(line);
                }
                in.close();
                br.close();
            } else {
                throw new Exception("登录远程机器失败" + ip); // 自定义异常类 实现略
            }
        } finally {
            if (conn != null) {
                conn.close();
            }
        }
        return result;
    }

    public static void main(String[] args) {
        try {
            SSHClient sshClient = new SSHClient("192.168.0.1", "root", "123456");
            List<String> exec = sshClient.exec("/home/shell/run_all.sh");
            for (String s : exec) {
                System.out.println(s);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

使用sshd可以正常进行远程执行shell文件
maven代码

<!--        ssh-core start-->
        <dependency>
            <groupId>org.apache.sshd</groupId>
            <artifactId>sshd-core</artifactId>
            <version>2.9.2</version>
        </dependency>
        <dependency>
            <groupId>net.i2p.crypto</groupId>
            <artifactId>eddsa</artifactId>
            <version>0.3.0</version>
        </dependency>
<!--        ssh-core end-->
package com.zhou.util.sshcore;

import org.apache.sshd.client.SshClient;
import org.apache.sshd.client.channel.ChannelExec;
import org.apache.sshd.client.channel.ClientChannelEvent;
import org.apache.sshd.client.future.ConnectFuture;
import org.apache.sshd.client.session.ClientSession;

import java.io.ByteArrayOutputStream;
import java.util.EnumSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;

public class SshSelfDemo {
    public static String runCommand(String hostName,String userName,String pwd,int port,String cmd, long timeout)
            throws Exception {
        SshClient client = SshClient.setUpDefaultClient();

        try {
            // Open the client
            client.start();
            // Connect to the server
            ConnectFuture cf = client.connect(userName, hostName, port);
            ClientSession session = cf.verify().getSession();
            session.addPasswordIdentity(pwd);
            session.auth().verify();
            // Create the exec and channel its output/error streams
            ChannelExec ce = session.createExecChannel(cmd);
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            ByteArrayOutputStream err = new ByteArrayOutputStream();
            ce.setOut(out);
            ce.setErr(err);
//       Execute and wait
            ce.open();
            Set<ClientChannelEvent> events =
                    ce.waitFor(EnumSet.of(ClientChannelEvent.CLOSED), TimeUnit.SECONDS.toMillis(timeout));
            session.close(false);
            return out.toString();

        } finally {
            client.stop();
        }

    }
    public static void main(String[] args) throws Exception{
        String hostName = "192.168.0.1";
        String userName = "root";
        String pwd = "123456";
        int port = 22;
        SshConnection  conn  = new SshConnection(userName,pwd,hostName);
//    &&-表示前面命令执行成功在执行后面命令; ||表示前面命令执行失败了在执行后面命令; ";"表示一次执行两条命令
        String cmd = "/home/shell/run_all.sh";
        String result = runCommand(hostName,userName,pwd,port,cmd,15);
        System.out.println("===返回结果===>"+result);


//    runCommandForInteractive(conn,15);
    }
}

使用jsch也可以正常执行shell文件
maven依赖

        <dependency>
            <groupId>com.jcraft</groupId>
            <artifactId>jsch</artifactId>
            <version>0.1.54</version>
        </dependency>

代码

package com.zhou.util.sshcore;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.InputStream;
import java.util.Properties;

public class JSchExecShellUtil {

    private static final Logger logger = LoggerFactory.getLogger(JSchExecShellUtil.class);

    public static String execShell(String hostName,String userName,String pwd,int port,String command, int timeout){
        // 创建JSch对象
        JSch jSch = new JSch();
        Session jSchSession = null;
        Channel jschChannel = null;
        // 存放执行命令结果
        StringBuffer result = new StringBuffer();
        int exitStatus = 0;
        try {
            // 根据主机账号、ip、端口获取一个Session对象
            jSchSession = jSch.getSession(userName, hostName, port);
            // 存放主机密码
            jSchSession.setPassword(pwd);

            // 去掉首次连接确认
            Properties config = new Properties();
            config.put("StrictHostKeyChecking", "no");
            jSchSession.setConfig(config);

            // 超时连接时间为3秒
            jSchSession.setTimeout(timeout);
            // 进行连接
            jSchSession.connect();
            jschChannel = jSchSession.openChannel("exec");
            ((ChannelExec) jschChannel).setCommand(command);

            jschChannel.setInputStream(null);
            // 错误信息输出流,用于输出错误的信息,当exitstatus<0的时候
            ((ChannelExec)jschChannel).setErrStream(System.err);

            // 执行命令,等待执行结果
            jschChannel.connect();

            // 获取命令执行结果
            InputStream in = jschChannel.getInputStream();
            /**
             * 通过channel获取信息的方式,采用官方Demo代码
             */
            byte[] tmp=new byte[1024];
            while(true){
                while(in.available() > 0){
                    int i = in.read(tmp, 0, 1024);
                    if (i < 0) {
                        break;
                    }
                    result.append(new String(tmp, 0, i));
                }
                // 从channel获取全部信息之后,channel会自动关闭
                if(jschChannel.isClosed()){
                    if (in.available() > 0) {
                        continue;
                    }
                    exitStatus = jschChannel.getExitStatus();
                    break;
                }
                try{Thread.sleep(1000);}catch(Exception ee){}
            }

        } catch (Exception e) {
            logger.warn(e.getMessage());
        } finally {
            // 关闭sftpChannel
            if (jschChannel != null && jschChannel.isConnected()) {
                jschChannel.disconnect();
            }

            // 关闭jschSesson流
            if (jSchSession != null && jSchSession.isConnected()) {
                jSchSession.disconnect();
            }

        }
        logger.info("获取执行命令的结果结果:"+result);
        logger.info("退出码为:"+exitStatus);
        return result.toString();
    }

    public static void main(String[] args) {
        String username = "root";
        String password = "123456";
        String host = "192.168.0.1";
        int port = 22;
        String commond = "/home/shell/run_all.sh";
        execShell(host,username,password, port, commond, 1000);
    }
}


以上是整理的Java远程调用以及本地调用的代码实现文章来源地址https://www.toymoban.com/news/detail-621661.html

到了这里,关于springboot通过接口执行本地shell脚本的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 在shell脚本中切换用户之后再执行多个函数以及执行多行命令的方法和遇到的问题

    其中,username是您要切换到的用户的用户名,function1和function2是您要执行的函数名称,您可以根据需要添加更多函数和命令。在EOF标记之间的所有内容都将作为切换后的用户执行。请注意,您需要确保切换后的用户具有执行所需命令和函数的权限。 其中,username为要切换到的

    2024年02月04日
    浏览(81)
  • 【Linux命令-shell】虚拟机中创建shell脚本、查看当前路径、执行脚本

    目录 一、创建shell脚本 二、查看当前的路径 三、执行脚本 一、创建shell脚本 shell脚本的特点 提前将可执行的命令语句写入一个文件中 顺序执行 解释器逐行解释代码 常见的脚本有:shell、python、PHP...... 注:用什么解释器就是什么脚本 编写shell脚本: 步骤: 1、新建文件 2、

    2024年02月05日
    浏览(46)
  • 【Linux】编写一个 shell 脚本&执行

    在Linux中编写和执行脚本相对简单。下面是一个基本的步骤指南,帮助你创建一个简单的bash脚本并运行它: 1. 创建脚本文件 首先,你需要使用文本编辑器创建一个新的文件。这个文件通常会有 .sh 的扩展名,以表明它是一个shell脚本。例如,你可以创建一个名为 myscript.sh 的文

    2024年04月26日
    浏览(26)
  • Linux下定时执行shell脚本

    vi test.sh 录入要执行的命令  保存退出,并且对脚本进行授权  :wq chmod 777 test.sh  生产文件data.txt touch /opt/data.txt  vi /etc/crontab  录入: 一分钟执行一次  保存退出即可每个一分钟执行一次 配置说明:

    2024年02月17日
    浏览(41)
  • nodejs脚本中执行shell命令

    Node.js v8.x 中文文档: child_process - 子进程 Node.js中使用内置的 child_process 模块来执行shell命令。该模块提供了 exec 、 execFile 、 spawn 等方法来启动子进程并执行命令 exec 方法是将整个命令输出缓存到内存中,当执行 完成后一次性 返回,所以适合执行 较小 的命令 exec 方法的 回调

    2024年01月21日
    浏览(37)
  • shell脚本-批量主机执行命令(expect)

    上次连接多台服务器使用ssh-keygen,24机器去连接22、25,所以存在.ssh/authorized_keys 1.如果有.ssh/authorized_keys该文件则先删除 1.expect命令含义 expect是一种脚本语言,它能够代替人工实现与终端的交互,主要应用于执行命令和程序时,系统以交互形式要求输入指定字符串,实现交互

    2024年02月13日
    浏览(41)
  • shell批量执行命令与文件传输脚本

    对未进行主机信任操作的服务器进行批量操作 由于ssh只能在交互模式中输入服务器密码进行登录登操作,不便于进行大批量服务器进行巡检或日志采集。sshpass恰好又解决了这个问题,使用 ssh -p passwd 可以实现命令行输入密码操作,便于进行规模巡检 首先需要在脚本执行机器

    2024年02月08日
    浏览(33)
  • Linux 环境使用定时任务执行shell脚本

    前言:Linux添加定时任务需要依赖crond服务,如果没有该服务,需要先安装:yum -y install crontabs 1、crond服务相关命令介绍         启动crond服务: service crond start         停止crond服务: service crond stop         重启crond服务: service crond restart         重载crond服务

    2024年02月16日
    浏览(54)
  • postgresql|数据库|批量执行SQL脚本文件的shell脚本

    对于数据库的维护而言,肯定是有SQL脚本的执行,例如,某个项目需要更新,那么,可能会有很多的SQL脚本需要执行,SQL脚本可能会包含有建表,插入数据,索引建立,约束建立,主外键建立等等内容。 那么,几个SQL脚本可能无所谓,navicat或者psql命令行 简简单单的就导入了

    2024年02月01日
    浏览(46)
  • Centos内Shell脚本基础语法讲解及执行

    Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁。Shell 既是一种命令语言,又是一种程序设计语言。 Shell 是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务。 Ken Thompson 的 sh 是第一种 Unix Shell,Windows Explorer 是一个典型

    2024年02月05日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包