服务器上命令执行java文件,Java 操作 Linux 服务器 上传文件并执行脚本

一、本项目核心目的

(目前支持.sql 和 .py脚本,.java脚本跟.py脚本大同小异,只是命令不同)

1.从A服务器获取脚本文件

2.上传到B服务器指定文件夹

3.通过命令执行上传后得脚本文件

4.返回执行结果

二、核心jar包

com.jcraft

jsch

0.1.54

ch.ethz.ganymed

ganymed-ssh2

262

三、Spring Boot 与 nacos 版本不对应时会报错,当前Spring Boot版本为2.3.9.RELEASE

7e1807de24c4

四、pom.xml 文件

org.springframework.boot

spring-boot-starter

org.springframework.boot

spring-boot-starter-web

org.springframework.boot

spring-boot-starter-test

test

ch.ethz.ganymed

ganymed-ssh2

262

com.alibaba.boot

nacos-config-spring-boot-starter

0.2.7

org.projectlombok

lombok

1.18.20

org.springframework

spring-web

5.2.12.RELEASE

org.springframework.cloud

spring-cloud-commons

2.2.2.RELEASE

org.springframework.cloud

spring-cloud-context

2.2.2.RELEASE

com.jcraft

jsch

0.1.54

五、RemoteCommandConfig(服务器调用)

import ch.ethz.ssh2.Connection;

import ch.ethz.ssh2.Session;

import ch.ethz.ssh2.StreamGobbler;

import com.alibaba.fastjson.JSONObject;

import lombok.extern.slf4j.Slf4j;

import org.apache.commons.lang3.StringUtils;

import org.springframework.stereotype.Component;

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStream;

import java.io.InputStreamReader;

@Slf4j

@Component

public class RemoteCommandConfig {

/**

* 只是用来测试,无其他用处

*/

public static void main(String[] args) {

Connection conn = login("这里填服务器IP地址", "账号", "密码");

JSONObject execute = execute(conn, "cd /script/ &&mysql -vvv -uadmin -p123456 spring_data < 测试.sql");

System.out.println(execute.toString());

}

private static String DEFAULTCHART = "UTF-8";

/**

* @return 登录成功返回true,否则返回false

* @描述 登录主机

*/

public static Connection login(String ip, String username, String password) {

boolean flg;

Connection conn = null;

try {

conn = new Connection(ip);

conn.connect();//连接

flg = conn.authenticateWithPassword(username, password);//认证

if (flg) {

return conn;

}

} catch (IOException e) {

log.error("脚本执行登录服务器失败,error={}" + e.getMessage());

e.printStackTrace();

}

return conn;

}

/**

* @param cmd 即将执行的命令

* @return 命令执行完后返回的结果值

* @描述 远程执行shll脚本或者命令

*/

public static JSONObject execute(Connection conn, String cmd) {

JSONObject result = new JSONObject();

result.put("code", 200);

String str = "";

try {

if (conn != null) {

Session session = conn.openSession();//打开一个会话

session.execCommand(cmd);//执行命令

str = processStdout(session.getStdout(), DEFAULTCHART);

//如果为得到标准输出为空,说明脚本执行出错了

if (StringUtils.isBlank(str)) {

result.put("code", 400);

result.put("msg", "得到标准输出为空,链接conn:" + conn + ",执行的命令:" + cmd);

str = processStdout(session.getStderr(), DEFAULTCHART);

} else {

result.put("msg", 200);

result.put("msg", "执行命令成功,链接conn:" + conn + ",执行的命令:" + cmd);

}

conn.close();

session.close();

}

} catch (IOException e) {

log.info("执行命令失败,链接conn:" + conn + ",执行的命令:" + cmd + " error={}" + e.getMessage());

}

result.put("data", str);

return result;

}

/**

* @param in 输入流对象

* @param charset 编码

* @return 以纯文本的格式返回

* @描述 解析脚本执行返回的结果集

*/

private static String processStdout(InputStream in, String charset) {

InputStream stdout = new StreamGobbler(in);

StringBuffer buffer = new StringBuffer();

try {

BufferedReader br = new BufferedReader(new InputStreamReader(stdout, charset));

String line;

while ((line = br.readLine()) != null) {

buffer.append(line + "\n");

}

} catch (Exception e) {

log.error("解析脚本出错,error={}" + e.getMessage());

e.printStackTrace();

}

return buffer.toString();

}

六、RestTemplateConfig防止项目因为RestTemplate启动失败

import org.springframework.boot.web.client.RestTemplateBuilder;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.web.client.RestTemplate;

@Configuration

public class RestTemplateConfig {

@Bean

@LoadBalanced

public RestTemplate restTemplate(RestTemplateBuilder builder){

return builder.build();

}

}

七、ScriptDealWithController (方法整合)

import ch.ethz.ssh2.Connection;

import com.alibaba.fastjson.JSON;

import com.alibaba.fastjson.JSONObject;

import com.alibaba.nacos.api.config.annotation.NacosValue;

import com.jcraft.jsch.Channel;

import com.jcraft.jsch.ChannelSftp;

import com.jcraft.jsch.JSch;

import com.jcraft.jsch.Session;

import com.sd.config.RemoteCommandConfig;

import org.apache.commons.lang3.StringUtils;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.cloud.context.config.annotation.RefreshScope;

import org.springframework.http.*;

import org.springframework.util.CollectionUtils;

import org.springframework.util.LinkedMultiValueMap;

import org.springframework.util.MultiValueMap;

import org.springframework.web.bind.annotation.PostMapping;

import org.springframework.web.bind.annotation.RequestBody;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

import org.springframework.web.client.RestTemplate;

import java.io.OutputStream;

import java.util.Date;

import java.util.HashMap;

import java.util.Map;

//nacos实时动态参数获取

@RefreshScope

@RestController

@RequestMapping("/script")

public class ScriptDealWithController {

/**

* 本项目所在服务器地址

*/

@NacosValue(value = "${gyyh_login.ip}")

private String gyyhIP;//登录获取ip

@NacosValue(value = "${gyyh_login.username}")

private String gyyhUsername;//系统账号

@NacosValue(value = "${gyyh_login.password}")

private String gyyhPassword;//系统密码

/**

* MySQL服务器地址

*/

@NacosValue(value = "${mysql_script.ip}")

private String myIp;//MySQL所在ip

@NacosValue(value = "${mysql_script.username}")

private String myUsername;//MySQL所在ip账号

@NacosValue(value = "${mysql_script.password}")

private String myPassword;//MySQL所在ip密码

@NacosValue(value = "${mysql_script.command}")

private String myCommand;//MySQL脚本执行命令

@NacosValue(value = "${mysql_script.file_path}")

private String myFilePath;//文件保存路径

/**

* pythonL服务器地址

*/

@NacosValue(value = "${python_script.ip}")

private String pyIp;//MySQL所在ip

@NacosValue(value = "${python_script.username}")

private String pyUsername;//MySQL所在ip账号

@NacosValue(value = "${python_script.password}")

private String pyPassword;//MySQL所在ip密码

@NacosValue(value = "${python_script.command}")

private String pyCommand;//MySQL脚本执行命令

@NacosValue(value = "${python_script.file_path}")

private String pyFilePath;//文件保存路径

@Autowired

private RestTemplate restTemplate;

/**

* @描述 获取平台登录token

* @参数 []

* @返回值 java.lang.String

* @创建时间 2021/7/23

*/

public String getToken() {

String url = gyyhIP + "/获取token地址";

HttpHeaders headers = new HttpHeaders();

headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

MultiValueMap params = new LinkedMultiValueMap<>();

params.add("username", gyyhUsername);

params.add("password", gyyhPassword);

HttpEntity> requestEntity = new HttpEntity<>(params, headers);

ResponseEntity response = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);

JSONObject body = JSON.parseObject(response.getBody());

JSONObject data = body.getJSONObject("data");

if (CollectionUtils.isEmpty(data)) {

throw new RuntimeException("token获取失败");

}

return data.getString("token");

}

/**

* @描述 调用平台文件下载接口获取文件流

* @参数 [body]

* @返回值 byte[]

* @创建时间 2021/7/23

*/

public byte[] download(String token, String type, String downloadId) {

String url = gyyhIP + "文件下载接口地址";

HttpHeaders headers = new HttpHeaders();

headers.setContentType(MediaType.APPLICATION_JSON);

headers.set("Authorization", token);

Map params = new HashMap<>();

params.put("type", type);

params.put("downloadId", downloadId);

HttpEntity> requestEntity = new HttpEntity<>(params, headers);

ResponseEntity response = restTemplate.postForEntity(url, requestEntity, byte[].class);

return response.getBody();

}

/**

* @描述 写入文件到指定目录下

* @参数 [bfile, filePath, fileName]

* @返回值 void

* @创建时间 2021/7/23

*/

public void upload(byte[] bfile, String ip, String username, String password, String filePath, String fileName) throws Exception {

//服务器端口 默认22

int port = 22;

Session session = null;

Channel channel = null;

JSch jsch = new JSch();

if (port <= 0) {

//连接服务器,采用默认端口

session = jsch.getSession(username, myIp);

} else {

//采用指定的端口连接服务器

session = jsch.getSession(username, ip, port);

}

//如果服务器连接不上,则抛出异常

if (session == null) {

throw new Exception("session is null");

}

//设置登陆主机的密码

session.setPassword(password);//设置密码

//设置第一次登陆的时候提示,可选值:(ask | yes | no)

session.setConfig("StrictHostKeyChecking", "no");

//设置登陆超时时间

session.connect(30000);

OutputStream outstream = null;

try {

//创建sftp通信通道

channel = session.openChannel("sftp");

channel.connect(1000);

ChannelSftp sftp = (ChannelSftp) channel;

//进入服务器指定的文件夹

sftp.cd(filePath);

//以下代码实现从本地上传一个文件到服务器,如果要实现下载,对换以下流就可以了

outstream = sftp.put(fileName);

outstream.write(bfile);

} catch (Exception e) {

e.printStackTrace();

} finally {

//关流操作

if (outstream != null) {

outstream.flush();

outstream.close();

}

if (session != null) {

session.disconnect();

}

if (channel != null) {

channel.disconnect();

}

}

}

/**

* @描述 脚本执行

* @参数 [body]

* @返回值 java.lang.String

* @创建时间 2021/7/27

*/

@PostMapping("/execute")

public JSONObject execute(@RequestBody JSONObject body) throws Exception {

String fileName = "";

String type = body.getString("type");

String downloadId = body.getString("downloadId");

//脚本类型 sql 、python

String languageType = body.getString("languageType");

Connection conn = null;

//执行脚本

String cmd = "";

//获取平台登录token

String token = getToken();

//调用平台文件下载接口获取文件流

byte[] download = download(token, type, downloadId);

if (StringUtils.equals("sql", languageType)) {

cmd = myCommand;

fileName = new Date().getTime() + ".sql";

conn = RemoteCommandConfig.login(myIp, myUsername, myPassword);

//写入文件到sql服务器指定目录下

upload(download, myIp, myUsername, myPassword, myFilePath, fileName);

} else if (StringUtils.equals("python", languageType)) {

cmd = pyCommand;

fileName = new Date().getTime() + ".py";

conn = RemoteCommandConfig.login(pyIp, pyUsername, pyPassword);

//写入文件到py服务器指定目录下

upload(download, pyIp, pyUsername, pyPassword, pyFilePath, fileName);

}

//执行脚本

return RemoteCommandConfig.execute(conn, cmd + fileName);

}

}

八、启动类

import com.alibaba.nacos.api.config.ConfigType;

import com.alibaba.nacos.spring.context.annotation.config.NacosPropertySource;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication

@NacosPropertySource(dataId = "script_****", type = ConfigType.YAML,groupId = "DEFAULT_GROUP",autoRefreshed = true)

public class ScriptDealWithApplication {

public static void main(String[] args) {

SpringApplication.run(ScriptDealWithApplication.class, args);

}

}

九、application.yml配置

server:

port: 8001

nacos:

config:

server-addr: 101.***.**.**:8848 #Nacos 链接地址

namespace: 55572fea-***-********************* #Nacos 命名空间ID

十、nacos配置

7e1807de24c4

7e1807de24c4

7e1807de24c4

gyyh_login:

ip: http://101.***.***.***:8088/

username: admin

password: 123456

mysql_script:

ip: 192.168.**.***

username: root

password: vagrant

file_path: /usr/local/script/

command: cd /usr/local/script/ &&mysql -vvv -uroot -p123456 spring_data <

python_script:

ip: 192.168.**.***

username: root

password: vagrant

file_path: /usr/local/script/

command: python /usr/local/script/

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值