java调用ruby连接winrm执行命令、上传文件,解决winrm4j冲突问题
一、准备环境
ruby 2.7.8
java jdk8
远程windows10专业版 22H2
二、安装ruby
1、开发机器 windows
下载ruby安装包
一路默认安装即可,记得勾选Add Ruby executables to your PATH
安装完成 cmd 输入
ruby -v
查看是否成功安装
2、生产环境 linux
下载安装包
tar -zxvf ruby-2.7.8.tar.gz
cd ruby-2.7.8
./configure
make
make install#查看是否成功安装
ruby -v
源码安装如果报错通常是缺少依赖,安装下下面的依赖
yum -y install gcc gcc-c++ make autoconf libjpeg libjpeg-devel libpng libpng-devel freetype freetype-devel libxml2 libxml2-devel zlib zlib-devel glibc glibc-devel glib2 glib2-devel bzip2 bzip2-devel ncurses ncurses-devel curl-devel e2fsprogs e2fsprogs-devel krb5 krb5-devel libidn libidn-devel openssl openssl-devel openldap openldap-devel nss_ldap openldap-clients openldap-servers
三、Ruby脚本
require 'winrm-elevated'
require 'winrm'
require 'json'class RubyClientdef initialize(hostname, username, password)@hostname = hostname@username = username@password = password@conn = WinRM::Connection.new(endpoint: "http://#{@hostname}:5985/wsman",user: @username,password: @password)enddef execute_command(command)result = @conn.shell(:powershell) do |shell|shell.run(command) do |_, _|# puts "STDOUT: #{stdout}" unless stdout.nil?# puts "STDERR: #{stderr}" unless stderr.nil?endendif result.exitcode == 0output = result.stdout.stripelseoutput = result.stderr.stripend# 构建 JSON 结果json_result = { code: result.exitcode, data: output }.to_json# 输出 JSON 结果puts json_resultenddef upload_file(local_path, remote_path)file_manager = WinRM::FS::FileManager.new(@conn)result = file_manager.upload(local_path, remote_path)ifresult.to_i == 0transfer_result = '{"code":0,"data":"transfer_success"}'elsetransfer_result = '{"code":1,"data":"transfer_fail"}'endputs transfer_resultend
endclient = RubyClient.new(ARGV[0], ARGV[1], ARGV[2])
execute_type = ARGV[3]
if execute_type == "upload"return client.upload_file(ARGV[4], ARGV[5])
endif execute_type == "command"return client.execute_command(ARGV[4])
endif execute_type == "multiple"str = ARGV[4]str_split = str.split(";")result = ''str_split.each do |element|result += element.to_s + ' 'endreturn client.execute_command(result)
end#
# client = RubyClient.new('192.168.46.60', 'Administrator', 'DDDFs')
# # client.execute_command("Test-Path -Path 'E:/echo.bat'")
# client.upload_file("E:\\testTmp\\a.txt", "E:\\tmp\\a.txt")
四、Java 调用 ruby
1、导入依赖
gem install winrm
gem install winrm-elevated
2、 RubyClient
package com.info2soft.core.util;import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Objects;/*** @Author: Lisy* @Date: 2023/06/02/15:12* @Description: 调用 ruby 工具类*/
@Slf4j
public class RubyClient {private static final boolean WINDOWS = System.getProperty("os.name").toLowerCase(Locale.ROOT).startsWith("windows");private static final String COMMAND = "command";private static final String UPLOAD = "upload";private static final String MULTIPLE = "multiple";private static final String SPACE = " ";private final String username;private final String password;private final String ip;private static final String RUBY;private static final String RUBY_FILE;static {if (WINDOWS) {// windows 开发环境替换下面文件的绝对路径RUBY = "C:\\Ruby27-x64\\bin\\ruby.exe";RUBY_FILE = "F:\\code\\i2drm\\drm\\agilebpm-oa-app\\src\\main\\resources\\ruby\\ruby_client.rb";} else {RUBY = "/usr/local/bin/ruby";RUBY_FILE = "/usr/local/ruby_client.rb";}}public RubyClient(String username, String password, String ip) {this.username = username;this.password = password;this.ip = ip;}/*** 判断调用ruby脚本是否成功* @param result 调用返回结果* @return*/public boolean executeSuccess(String result) {if (StringUtils.isBlank(result)) {return false;}JSONObject jsonObject = JSONObject.parseObject(result);if (Objects.isNull(jsonObject)) {return false;}return jsonObject.getInteger("code") == 0;}/*** 通过ruby 远程连接winrm 执行命令** @param command 需要执行的命令* @param multiple 是否是多参数,true:则将空格的参数替换成 ';'* 如 Test-Path -Path 'E:\\a.txt' 替换成 Test-Path;-Path;'E:/echo.bat'* @return 执行结果*/public List<String> executeCommand(String command, boolean multiple) {isInstall();String cmdTmp = multiple ? MULTIPLE : COMMAND;String cmd = RUBY + SPACE + RUBY_FILE + SPACE +ip + SPACE + username + SPACE + password + SPACE +cmdTmp + SPACE + command;return execute(cmd);}public List<String> executeCommand(String command) {return executeCommand(command, false);}/*** 通过ruby 远程连接winrm 执行命令,* @param command 需要执行的命令* @return 返回一行执行结果*/public String executeCommand1Line(String command) {return executeCommand1Line(command, false);}public String executeCommand1Line(String command, boolean multiple) {List<String> strings = executeCommand(command, multiple);return strings.get(0);}public String transferFile(String localFile, String remoteFile) {isInstall();if (!Files.exists(Paths.get(localFile))) {throw new RuntimeException("File " + localFile + "不存在!");}String cmd = RUBY + SPACE + RUBY_FILE + SPACE +ip + SPACE + username + SPACE + password + SPACE +UPLOAD + SPACE + localFile + SPACE + remoteFile;List<String> execute = execute(cmd);return execute.get(0);}private List<String> execute(String command) {Process proc;List<String> result = new ArrayList<>();try {proc = Runtime.getRuntime().exec(command);BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream()));String line;while ((line = in.readLine()) != null) {result.add(line);}in.close();proc.waitFor();} catch (IOException | InterruptedException e) {e.printStackTrace();}return result;}private void isInstall() {if (!Files.exists(Paths.get(RUBY_FILE))) {throw new RuntimeException("ruby 脚本不存在:" + RUBY_FILE + "请检查此路径是否存在此文件");}if (!Files.exists(Paths.get(RUBY))) {throw new RuntimeException("ruby 执行程序不存在:"+ RUBY +",请先安装!");}}
}
3、Ruby测试类
public class RubyTest {RubyClient rubyClient;@Beforepublic void before() {String ip = "192.18.4.0";String user = "123";String pwd = "123";rubyClient = new RubyClient(user, pwd, ip);}@Testpublic void executeCommand() {List<String> hostname = rubyClient.executeCommand("hostname");hostname.forEach(System.out::println);}@Testpublic void start() {String hostname = rubyClient.executeCommand1Line("Test-Path;-Path;'E:/echo.bat'", true);System.out.println("hostname = " + hostname);}@Testpublic void transferFiletest() {String localFile = "E:\\testTmp\\a.txt";String hostname = rubyClient.transferFile(localFile, "E:\\tmpa\\a.txt");System.out.println(hostname);}}
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
