From cf3130522520fa40f9f62ae3b3a490c6aa7090ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E5=A8=81?= Date: Tue, 26 Aug 2025 09:23:15 +0800 Subject: [PATCH] =?UTF-8?q?add:=E6=96=B0=E5=A2=9EJsch=E7=B1=BB=E5=9E=8B?= =?UTF-8?q?=E7=9A=84ssh=E5=AE=A2=E6=88=B7=E7=AB=AF=E5=90=8C=E6=AD=A5?= =?UTF-8?q?=E6=89=A7=E8=A1=8C=E6=96=B9=E6=B3=95=EF=BC=8C=E5=8F=AF=E5=88=A4?= =?UTF-8?q?=E6=96=AD=E5=91=BD=E4=BB=A4=E6=89=A7=E8=A1=8C=E6=98=AF=E5=90=A6?= =?UTF-8?q?=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../extra/ssh/engine/jsch/JschSession.java | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/hutool-extra/src/main/java/org/dromara/hutool/extra/ssh/engine/jsch/JschSession.java b/hutool-extra/src/main/java/org/dromara/hutool/extra/ssh/engine/jsch/JschSession.java index 81ea3fd12f..14a8b33cba 100644 --- a/hutool-extra/src/main/java/org/dromara/hutool/extra/ssh/engine/jsch/JschSession.java +++ b/hutool-extra/src/main/java/org/dromara/hutool/extra/ssh/engine/jsch/JschSession.java @@ -22,17 +22,20 @@ import com.jcraft.jsch.ChannelShell; import com.jcraft.jsch.JSchException; import org.dromara.hutool.core.io.IORuntimeException; import org.dromara.hutool.core.io.IoUtil; +import org.dromara.hutool.core.thread.ThreadUtil; import org.dromara.hutool.core.util.ByteUtil; import org.dromara.hutool.core.util.CharsetUtil; import org.dromara.hutool.extra.ssh.Connector; import org.dromara.hutool.extra.ssh.Session; import org.dromara.hutool.extra.ssh.SshException; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.InetSocketAddress; import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; /** * Jsch Session封装 @@ -202,6 +205,76 @@ public class JschSession implements Session { } } + /** + * 执行Shell命令 + * + * @param cmd 命令 + * @param charset 发送和读取内容的编码 + * @return {@link String} + */ + public String execSync(final String cmd, final Charset charset) { + return execSync(cmd, charset, System.err); + } + /** + * 执行Shell命令(使用EXEC方式) + *

+ * 此方法单次发送一个命令到服务端,不读取环境变量,执行结束后自动关闭channel,会阻塞直到命令执行完毕,命令执行错误,会抛出异常。 + *

+ * + * @param cmd 命令 + * @param charset 发送和读取内容的编码 + * @param errStream 错误信息输出到的位置 + * @return 执行结果内容 + * @since 4.3.1 + */ + public String execSync(final String cmd, Charset charset, final OutputStream errStream) { + if (null == charset) { + charset = CharsetUtil.UTF_8; + } + final ChannelExec channel = (ChannelExec) createChannel(ChannelType.EXEC); + channel.setCommand(ByteUtil.toBytes(cmd, charset)); + channel.setInputStream(null); + + channel.setErrStream(errStream); + InputStream in = null; + ByteArrayOutputStream realtimeOutput = new ByteArrayOutputStream(); + byte[] buffer = new byte[1024]; + try { + channel.connect(); + in = channel.getInputStream(); + while (!channel.isClosed()) { + if (in.available() > 0) { + int len = in.read(buffer); + if (len > 0) { + realtimeOutput.write(buffer, 0, len); // 写入本地缓冲区 + } + } + ThreadUtil.sleep(100); + } + if (in.available() > 0) { + int len = in.read(buffer); + if (len > 0) { + realtimeOutput.write(buffer, 0, len); + } + } + int exitStatus = channel.getExitStatus(); + if(exitStatus != 0){ + String errorMsg = errStream.toString().trim(); + throw new SshException(errorMsg); + } + return realtimeOutput.toString(StandardCharsets.UTF_8.name()).trim(); + } catch (final IOException e) { + throw new IORuntimeException(e); + } catch (final JSchException e) { + throw new SshException(e); + } finally { + IoUtil.closeQuietly(in); + if (channel.isConnected()) { + channel.disconnect(); + } + } + } + /** * 执行Shell命令 *

-- Gitee