`

用jsch实现简单的命令交互和批量处理

 
阅读更多

其实gradle ssh plugin已经很方便了,就是我们公司的内网没有外网环境,配置gradle依赖有点麻烦。
所以就模仿写了一个,发现还是挺好用的,附上一个例子,扫描一些目标机器并添加ssh key免登陆。

只依赖了commons-net/jsch

import org.apache.commons.net.telnet.TelnetClient

def mkHostTrust = {String hostToBeTrust, String targetHosts ->
	JschUtils.session(hostToBeTrust){session ->
		JschUtils.exeSh("ssh-keygen -t rsa", session, 1000){str ->
			if(str.contains("The key's"))
				return null
			else if(str.contains("Overwrite"))
				return "y"
			else
				return "\n"
		}

		targetHosts.split(',').each{
			def arr = it.split(':')

			JschUtils.exeSh("scp /root/.ssh/id_rsa.pub ${arr[-2]}@${arr[0]}:~/.ssh/authorized_keys", session, 2000){str ->
				if(str.contains("yes/no"))
					return "yes"
				else if(str.contains("password"))
					return "${arr[-1]}"
				else
					return null
			}

			println 'done copy pub key to ' + arr[0]

			JschUtils.exeSh("ssh ${arr[0]}", session, 1000){str ->
				if(str.contains("yes/no"))
					return "yes"
				if(str.contains("known hosts"))
					return "exit"
				else
					return null
			}
		}
	}
}

String pre = '172.16.0.'
List ips = [35..49, 188..194].flatten()

List ipsOkList = []

def tc = new TelnetClient()

for(it in ips){
	try{
	    tc.connect(pre + it, 22)
		ipsOkList << it
	}catch(e){
		println 'error telnet 22 4 ' + it
	}finally{
		try{
			tc.disconnect()
		}catch(e){
		}
	}
}

String ss = ipsOkList.collect{
	pre + it + ':22:root:xxx'
}.join(',')

mkHostTrust(pre + '34:22:root:xxx', ss)

 

下面是JschUtils的代码

import com.jcraft.jsch.ChannelSftp
import com.jcraft.jsch.SftpATTRS

import com.jcraft.jsch.*

import org.slf4j.Logger
import org.slf4j.LoggerFactory

class JschUtils {
	// *** log
	static Logger l = LoggerFactory.getLogger(JschUtils.class)

	private static Properties config = [StrictHostKeyChecking: 'no']

	public static int timeout = 10000

	private static String read(InputStream is){
		def buf = new StringBuilder(1024)
		def tmp = new byte[1024]
		while ( is.available() > 0 ) {
			int i = is.read( tmp, 0, 1024 )
			if ( i < 0 ) break;
			buf << new String( tmp, 0, i )
		}
		buf.toString()
	}

	private static String exeInner(String cmd, long wait, OutputStream os, InputStream is, Closure cl){
		l.info  'begin exe ' + cmd
		os.write("${cmd.trim()}\r".getBytes())
		Thread.currentThread().sleep(wait)

		String result = read(is)
		l.info result
		cl.call(result)
	}

	public static void exeSh(String cmd, s, long wait = 500, Closure cl = null){
		def ch = s.openChannel('shell')

		def pipeIn = new PipedInputStream() 
		def pipeOut = new PipedOutputStream(pipeIn)

		def pipeIn2 = new PipedInputStream() 
		def pipeOut2 = new PipedOutputStream(pipeIn2)

		ch.inputStream = pipeIn
		ch.outputStream = pipeOut2

		ch.connect(timeout)

		Thread.currentThread().sleep(wait)
		l.info read(pipeIn2)

		// -i
		if(cl != null){
			String nextCmd = exeInner(cmd, wait, pipeOut, pipeIn2, cl)
			while(nextCmd != null){
				Thread.currentThread().sleep(wait)
				nextCmd = exeInner(nextCmd, wait, pipeOut, pipeIn2, cl)
			}
		}else{
			cmd.split(',').each{
				l.info  'begin exe ' + it
				pipeOut.write("${it.trim()}\r".getBytes())
				Thread.currentThread().sleep(wait)
			}
		}

		pipeOut.close()
		pipeIn.close()

		pipeOut2.close()
		pipeIn2.close()

		ch.disconnect()
	}

	public static void exe(String cmd, s){
		def ch = s.openChannel('exec')
		ch.command = cmd
		ch.errStream = System.err

		def is = ch.inputStream

		ch.connect() 
		int res = -1
		def buf = new StringBuffer(1024)
		def tmp = new byte[1024]
		while ( true ) {  
			while ( is.available() > 0 ) {
				int i = is.read( tmp, 0, 1024 );
				if ( i < 0 ) break;
				buf.append( new String( tmp, 0, i ) );
			}
			if ( ch.isClosed() ) {
				res = ch.exitStatus
				l.info  'exist status ' + res
				break
			}
		}

		l.info  buf.toString()
		ch.disconnect()
	}

	public static void put(s, String local, dst){
		l.info 'put ' + local + ' -> ' + dst

		// upload script
		def channel = s.openChannel('sftp')
		channel.connect()
		l.info  'sftp channel connected'

		channel.put(local, dst, null, ChannelSftp.OVERWRITE)
		channel.quit()
		channel.disconnect()
	}

	// sinfo -> host:port:username:password
	public static void session(String hostInfo, Closure cl){
		Map sinfo = [:]
		def arr = hostInfo.split(':')
		sinfo.host = arr[0]
		sinfo.port = arr[1] as int
		sinfo.username = arr[2]
		sinfo.password = arr[3]

		def session
		try{
			def jsch = new JSch()
			session = jsch.getSession(sinfo.username, sinfo.host, sinfo.port)
			session.password = sinfo.password

			session.config = config
			session.timeout = timeout
			session.connect()
			l.info  'session opened ' + sinfo.host

			cl.call(session)
		}catch(e){
			l.error('ex get', e)
		}finally{
			if(session){
				session.disconnect()
				l.info  'session disconnected ' + sinfo.host
			}
		}
	}
}

 

1
0
分享到:
评论

相关推荐

    Jsch批量执行多条命令,包含切换用户输入密码

    参考expect4j的交互式操作方式控制输入输出流实现批量执行多条shell命令同时支持切换用户输入密码提权执行命令输入密码等操作 有完整的测试用例,便于理解 模板化执行命令示例 [$]send[su - root] [Password:]...

    java实现模拟SSH和telnet登陆(实现命令的发送和接受)

    Java 实现模拟 SSH 和 Telnet 登陆,以及发送与接收命令是网络编程中常见的需求,主要应用于自动化测试、远程系统管理或数据交换等场景。在本文中,我们将深入探讨如何利用 Java 实现这一功能。 首先,SSH(Secure ...

    java版SFTP实现示例(使用jsch)

    以上就是使用JSch在Java中实现SFTP的基本流程和关键知识点。通过这些,你可以构建自己的SFTP客户端应用,实现与远程服务器的安全文件交互。注意,在实际项目中,可能还需要考虑错误处理、连接超时、资源管理等更复杂...

    jsch-0.1.54.zip

    - **自动化运维**:在自动化运维工具和脚本中,JSch可以帮助执行远程命令,监控系统状态,进行批量更新或配置更改。 - **持续集成/持续部署(CI/CD)**:在CI/CD流程中,JSch用于安全地部署代码到远程服务器,确保...

    java调用shell脚本

    ganymed-ssh2是一个开源项目,提供了SSH2协议的纯Java实现,而jsch则是一个广泛使用的Java SSH API,支持SFTP、SCP和SSH命令的执行。 Ganymed-ssh2的版本是262.jar,而jsch的版本是0.1.53.jar。它们通常需要添加到...

    通过SSHPASS执行命令及相关脚本

    以下是关于`sshpass`使用和相关脚本编写的一些详细知识点: 1. **安装sshpass**:在大多数Linux发行版中,可以通过包管理器如`apt`(Ubuntu/Debian)或`yum`(CentOS/RHEL)来安装`sshpass`。例如: ``` sudo apt...

    java实现ftp自动上传文件

    这可以通过递归方式实现,使用`java.io.File`类的`listFiles()`方法获取当前目录下的文件和子目录,并对每个文件或子目录进行相应的处理。 9. 异常处理:在FTP操作中,可能会遇到各种异常,如网络问题、权限问题等...

    ssh2增删改查实例

    - 性能优化:批量操作而非单条处理,减少网络交互次数。 总结,这个“ssh2增删改查实例”提供了一个实用的框架,帮助开发者在SSH2环境下安全地管理远程数据库,同时支持多语言环境,使得应用程序更加全球化。通过...

    SFtp文件处理

    2. **SFTP协议**:介绍SFTP的协议规范,包括其命令交互过程和数据传输方式。 3. **SFTP客户端库**:在Java中,可能会提到JSch、Apache SSHD、Netty SFTP等库,这些库允许开发者在Java应用中实现SFTP功能。 4. **...

    Andrtoid+ssh(向服务器提交数据)

    JSch是一个Java实现的SSH2库,它提供了客户端和服务器端的实现。将JSch库添加到Android项目的依赖中,可以通过Gradle添加如下代码: ```groovy implementation 'com.jcraft:jsch:0.1.55' ``` 2. **配置SSH连接**...

    jenkins插件:publish-over-ssh

    "publish-over-ssh" 插件是其中一个重要的插件,它允许Jenkins通过SSH(Secure Shell)协议与远程服务器进行交互,实现文件的发布、执行命令等功能,这对于运维工作尤其有用。 该插件的主要功能包括: 1. **文件...

    JAVA开发的FTP系统

    FTP协议包含两个通道:控制通道和数据通道,用于命令交互和文件传输。 3. **JAVA FTP库**:JAVA标准库中的`java.net`包并不直接支持FTP,但有第三方库如Apache Commons Net,它提供了FTPClient和FTPSClient类,简化...

    SSH程序框架代码_可以直接运行

    8. **许可证**:检查代码的开源许可证,确保在使用和修改代码时符合规定。 9. **社区支持**:如果该SSH框架有活跃的社区,可以寻求帮助和分享经验。 10. **性能优化**:了解如何优化SSH连接速度,减少延迟,特别是...

    ftp上传工具, 上传ftp服务器

    在实际开发中,必须对可能出现的网络错误、认证失败等异常进行捕获和处理,确保程序的健壮性。 8. **性能优化**: - **批量上传**:一次性上传多个文件,减少网络交互次数。 - **缓存策略**:对于大文件,可以先...

    SftpUtil.zip_Java编程_Java_

    本文将深入探讨如何使用JSch库来实现SFTP功能,包括文件的下载、上传以及批量上传。 首先,JSch是Java Secure Channel的缩写,它是一个开源的Java库,提供了SSH2协议的支持,包括SFTP。通过JSch,开发者可以在Java...

Global site tag (gtag.js) - Google Analytics