由于项目需要使用java来linux进行管理,近一番查找,发现第三方jar包 jsch 可以轻松实现对linux的管理,(相关文档及例子请访问官网),故引进。
在网上搜索了一些资料参考并修改(资料来源地址一下子找不到了,有发现的请提醒加上),创建一个工具类,可以实现对linux上的基本操作及系统上文件的上传和下载。
代码如下:
/** * @description 用来创建与 linux 交互的会话,操作文件和执行 操作 命令 * @date: 2016/7/25 * @author: gongtao */public class LinuxConnetionHelper { private static final org.slf4j.Logger log = LoggerFactory.getLogger(LinuxConnetionHelper.class); private static final int TIME_OUT = 5*60*1000; //设置超时为5分钟 private static final Mapcache = new HashMap<>(); //session缓存 public static SessionMonitor sessionMonitor; /** * 创建 连接,需手动关闭 * @param host * @param userName * @param password * @param port * @throws JSchException */ public static Session connect(String host,String userName,String password,int port) throws JSchException { //创建对象 JSch jsch = new JSch(); //创建会话 Session session = jsch.getSession(userName,host, port); //输入密码 session.setPassword(password); //配置信息 Properties config = new Properties(); //设置不用检查hostKey //如果设置成“yes”,ssh就不会自动把计算机的密匙加入“$HOME/.ssh/known_hosts”文件, //并且一旦计算机的密匙发生了变化,就拒绝连接。 config.setProperty("StrictHostKeyChecking", "no");// //默认值是 “yes” 此处是由于我们SFTP服务器的DNS解析有问题,则把UseDNS设置为“no”// config.put("UseDNS", "no"); session.setConfig(config); //过期时间 session.setTimeout(TIME_OUT); //建立连接 session.connect(); return session; } /** * 创建 连接,无需手动关闭 * @param host * @param userName * @param password * @param port * @throws JSchException */ public static Session longConnect(String host,String userName,String password,int port) throws JSchException { String key = host + userName + password + port; Session session = cache.get(key); if (session == null){ //创建对象 JSch jsch = new JSch(); //创建会话 session = jsch.getSession(userName,host, port); //输入密码 session.setPassword(password); //配置信息 Properties config = new Properties(); //设置不用检查hostKey //如果设置成“yes”,ssh就不会自动把计算机的密匙加入“$HOME/.ssh/known_hosts”文件, //并且一旦计算机的密匙发生了变化,就拒绝连接。 config.setProperty("StrictHostKeyChecking", "no");// //默认值是 “yes” 此处是由于我们SFTP服务器的DNS解析有问题,则把UseDNS设置为“no”// config.put("UseDNS", "no"); session.setConfig(config); //过期时间 //session.setTimeout(TIME_OUT); //建立连接,此时会在linux上新建一个进程,timeout 并不会结束进程,只有调用disconnect()才会结束此进程 session.connect(); cache.put(key,session); }else{ //判断session是否失效 if (testSessionIsDown(key)){ //session is down //session 失去连接则清除 closeLongSessionByKey(key); //重新生成session session = longConnect(host, userName, password, port); } } //创建定时器 createSessionMonitor(); return session; } /** * 销毁 session * @param session */ public static void close(Session session){ if (session != null){ session.disconnect(); } } /** * 测试session是否失效 * @param key * @return */ public static boolean testSessionIsDown(String key){ Session session = cache.get(key); if (session == null){ return true; } ChannelExec channelExec = null; try { channelExec = openChannelExec(session); channelExec.setCommand("true"); channelExec.connect(); return false; }catch (Throwable e){ //session is down return true; }finally { if (channelExec != null){ channelExec.disconnect(); } } } /** * 销毁 session * @param key */ public static synchronized void closeLongSessionByKey(String key){ Session session = cache.get(key); if (session != null){ session.disconnect(); cache.remove(key); } } /** * 销毁 session * @param session */ public static void closeLongSessionBySession(Session session){ Iterator iterator = cache.keySet().iterator(); while (iterator.hasNext()){ String key = (String)iterator.next(); Session oldSession = cache.get(key); if (session == oldSession){ session.disconnect(); cache.remove(key); return; } } } /** * 创建一个 sftp 通道并建立连接 * @param session * @return * @throws Exception */ public static ChannelSftp openChannelSftp(Session session) throws Exception { ChannelSftp channelSftp = (ChannelSftp)session.openChannel("sftp"); channelSftp.connect(); return channelSftp; } /** * 关闭 sftp 通道 * @param channelSftp * @throws Exception */ public static void closeChannelSftp(ChannelSftp channelSftp) { if (channelSftp != null){ channelSftp.disconnect(); } } /** * 下载文件 * @param remoteFile * 远程服务器的文件路径 * @param localPath * 需要保存文件的本地路径 * @throws IOException * @throws SftpException */ public static void downloadFile(Session session , String remoteFile, String localPath) throws Exception { ChannelSftp channelSftp = openChannelSftp(session); try { String remoteFilePath = remoteFile.substring(0, remoteFile.lastIndexOf("/")); String remoteFileName = remoteFile.substring(remoteFile.lastIndexOf("/") + 1,remoteFile.length()); if(localPath.charAt(localPath.length() - 1) != '/'){ localPath += '/'; } File file = new File(localPath + remoteFileName); if (!file.getParentFile().exists()) { file.getParentFile().mkdirs(); file.createNewFile(); } OutputStream output = new FileOutputStream(file); try { channelSftp.cd(remoteFilePath); log.info("远程服务器路径:" + remoteFilePath); log.info("本地下载路径:" + localPath + remoteFileName); SftpATTRS attrs = channelSftp.lstat(remoteFile); channelSftp.get(remoteFile, output, new FileSftpProgressMonitor(attrs.getSize())); }catch (Exception e){ throw e; }finally { output.flush(); output.close(); } }catch (Exception e){ throw e; }finally { closeChannelSftp(channelSftp); } } /** * 上传文件 * @param localFile * 本地文件路径 * @param remotePath * 远程服务器路径 * @throws IOException * @throws SftpException */ public static void uploadFile(Session session,String localFile,String remotePath) throws Exception { ChannelSftp channelSftp = openChannelSftp(session); String remoteFileName = localFile.substring(localFile.lastIndexOf("/") + 1, localFile.length()); File file = new File(localFile); final InputStream input = new FileInputStream(file); try { channelSftp.cd(remotePath); }catch (SftpException e){ String tempPath = null; try { tempPath = remotePath.substring(0, remotePath.lastIndexOf("/")); channelSftp.cd(tempPath); }catch (SftpException e1){ channelSftp.mkdir(tempPath); } channelSftp.mkdir(remotePath); channelSftp.cd(remotePath); } log.info("远程服务器路径:" + remotePath); log.info("本地上传路径:" + localFile); try { channelSftp.put(input, remoteFileName, new FileSftpProgressMonitor(file.length())); }catch (Exception e){ throw e; }finally { input.close(); closeChannelSftp(channelSftp); } } /** * 文件上传 * @param session * @param inputStream * @param fileName * @param remotePath * @throws Exception */ public static void uploadFile(Session session,InputStream inputStream,String fileName,String remotePath) throws Exception { ChannelSftp channelSftp = openChannelSftp(session); channelSftp.cd(remotePath); log.info("远程服务器路径:" + remotePath); try { channelSftp.put(inputStream, fileName,new FileSftpProgressMonitor(inputStream.available())); }catch (Exception e){ throw e; }finally { inputStream.close(); closeChannelSftp(channelSftp); } } /** * 获取远程服务器文件列表 * @param session * @param remotePath * 远程服务器路径 * @return * @throws SftpException */ public static Vector listFiles(Session session,String remotePath) throws Exception { ChannelSftp channelSftp = openChannelSftp(session); try { Vector vector = channelSftp.ls(remotePath); return vector; }catch (Exception e){ throw e; }finally { closeChannelSftp(channelSftp); } } /** * 删除文件 * @param session * @param remotePath * @param fileName * @throws Exception */ public static void removeFile(Session session,String remotePath,String fileName) throws Exception{ ChannelSftp channelSftp = openChannelSftp(session); try { channelSftp.cd(remotePath); channelSftp.rm(fileName); }catch (Exception e){ throw e; }finally { closeChannelSftp(channelSftp); } } /** * 删除文件夹 * @param session * @param remotePath * @throws Exception */ public static void removeDir(Session session,String remotePath) throws Exception{ ChannelSftp channelSftp = openChannelSftp(session); try { if (remotePath.lastIndexOf("/") == remotePath.length() - 1){ remotePath = remotePath.substring(0,remotePath.length() - 1); } String parentDir = remotePath.substring(0,remotePath.lastIndexOf("/") + 1); String rmDir = remotePath.substring(remotePath.lastIndexOf("/") + 1,remotePath.length()); channelSftp.cd(parentDir); channelSftp.rmdir(rmDir); }catch (Exception e){ throw e; }finally { closeChannelSftp(channelSftp); } } /** * 新建一个 exec 通道 * @param session * @return * @throws JSchException */ public static ChannelExec openChannelExec(Session session) throws JSchException { ChannelExec channelExec = (ChannelExec)session.openChannel("exec"); return channelExec; } /** * 关闭 exec 通道 * @param channelExec */ public static void closeChannelExec(ChannelExec channelExec){ if (channelExec != null){ channelExec.disconnect(); } } /** * 执行 脚本 * @param session * @param cmd * 执行 .sh 脚本 * @param charset * 字符格式 * @return * @throws IOException * @throws JSchException */ public static String[] execCmd(Session session,String cmd,String charset) throws Exception{ //打开通道 ChannelExec channelExec = openChannelExec(session); ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayOutputStream error = new ByteArrayOutputStream(); channelExec.setCommand(cmd); channelExec.setOutputStream(out); channelExec.setErrStream(error); channelExec.connect(); //确保能够执行完成及响应所有数据 Thread.sleep(10000); String[] msg = new String[2]; msg[0] = new String(out.toByteArray(),charset); msg[1] = new String(error.toByteArray(),charset); out.close(); error.close(); //关闭通道 closeChannelExec(channelExec); return msg; } /** * 创建一个交互式的 shell 通道 * @param session * @return * @throws JSchException */ public static ChannelShell openChannelShell(Session session) throws JSchException{ ChannelShell channelShell = (ChannelShell)session.openChannel("shell"); return channelShell; } /** * 关闭 shell 通道 * @param channelShell */ public static void closeChannelShell(ChannelShell channelShell){ if (channelShell != null){ channelShell.disconnect(); } } /** * 执行命令 * @param cmds * 命令参数 * @param session * @param timeout * 连接超时时间 * @param sleepTimeout * 线程等待时间 * @return * @throws Exception */ public static String execShellCmd(String[] cmds,Session session,int timeout,int sleepTimeout) throws Exception { //打开通道 ChannelShell channelShell = openChannelShell(session); //设置输入输出流 PipedOutputStream pipedOut = new PipedOutputStream(); ByteArrayOutputStream errorOut = new ByteArrayOutputStream(); channelShell.setInputStream(new PipedInputStream(pipedOut)); channelShell.setOutputStream(errorOut); channelShell.connect(timeout); for (String cmd : cmds){ pipedOut.write(cmd.getBytes("UTF-8")); //线程休眠,保证执行命令后能够及时返回响应数据 Thread.sleep(sleepTimeout); } String msg = new String(errorOut.toByteArray(),"UTF-8"); log.info(msg); pipedOut.close(); errorOut.close(); //关闭通道 closeChannelShell(channelShell); return msg; } /** * 创建定时器,清除timeout 的 session 连接 */ public static void createSessionMonitor(){ if (sessionMonitor == null){ synchronized (SessionMonitor.class){ if (sessionMonitor == null){ //定时器,定时清除失效的session sessionMonitor = new SessionMonitor(); sessionMonitor.start(); } } } } /** * 监控文件传输 */ static class FileSftpProgressMonitor extends TimerTask implements SftpProgressMonitor{ private long progressInterval = 5 * 1000; // 默认间隔时候为5秒 private boolean isEnd = false; // 记录传输是否停止 private long transfered; // 记录已传输的数据总大小 private long fileSize; // 记录文件总大小 private Timer timer; // 定时器对象 private boolean isScheduled = false; // 记录是否已启动timer定时器 private NumberFormat df = NumberFormat.getInstance(); //格式化 public FileSftpProgressMonitor(long fileSize){ this.fileSize = fileSize; } @Override public void run() { if (!isEnd()){ long transfered = getTransfered(); if (transfered != fileSize){ log.info("Current transfered: " + transfered + " bytes"); sendProgressMessage(transfered); }else{ log.info("transfered end."); setIsEnd(true); } }else { log.info("Transfering done. Cancel timer."); stop(); // 若是传输停止,停止timer记时器 } } /** * 定时器关闭 */ public void stop() { log.info("Try to stop progress monitor."); if (timer != null) { timer.cancel(); timer.purge(); timer = null; isScheduled = false; } log.info("Progress monitor stoped."); } /** * 定时器启动 */ public void start() { log.info("Try to start progress monitor."); if (timer == null) { timer = new Timer(); } timer.schedule(this, 1000, progressInterval); isScheduled = true; log.info("Progress monitor started."); } /** * 传输进度 * @param transfered */ private void sendProgressMessage(long transfered) { if (fileSize != 0) { double d = ((double)transfered * 100)/(double)fileSize; log.info("Sending progress message: " + df.format(d) + "%"); } else { log.info("Sending progress message: " + transfered); } } @Override public void init(int i, String s, String s1, long l) { log.info("transfering start."); } @Override public boolean count(long l) { if (isEnd()){ return false; } if (!getIsScheduled()){ start(); } add(l); return true; } @Override public void end() { setIsEnd(false); log.info("transfering end."); } private synchronized void add(long count) { transfered = transfered + count; } public synchronized boolean isEnd() { return isEnd; } public synchronized void setIsEnd(boolean isEnd) { this.isEnd = isEnd; } public synchronized long getTransfered() { return transfered; } public synchronized void setTransfered(long transfered) { this.transfered = transfered; } public synchronized boolean getIsScheduled() { return isScheduled; } public synchronized void setIsScheduled(boolean isScheduled) { this.isScheduled = isScheduled; } } /** * 定时器,定时清除失效的session */ static class SessionMonitor extends TimerTask{ private Timer timer; // 定时器对象 private long progressInterval = 30 * 1000; // 默认间隔时候为30秒 @Override public void run() { if (!cache.isEmpty()){ Iterator iterator = cache.keySet().iterator(); while (iterator.hasNext()){ String key = (String)iterator.next(); //清除失效session if (testSessionIsDown(key)){ closeLongSessionByKey(key); } } } } public void start(){ if (timer == null){ timer = new Timer(); } timer.schedule(this,1000,progressInterval); } public void stop(){ if (timer != null) { timer.cancel(); timer.purge(); timer = null; } } }}