用jsch实现简单的命令交互和批量处理
程序员文章站
2022-06-05 23:11:13
...
其实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 } } } }
下一篇: jquery前端开发实践