后来被分配做了维护项目,同时需要开发新产品,老项目经常部署测试环境是替换class等文件!!!当时我也是惊了个呆。。。好吧抽空网上找了java sftp的资料写了个算是半成品的上传工具,还有不足之处,今后有修改再放上来。说下主要的思路和还有的一些缺点。
思路:本身sftp需要的是上传的文件路径和目标路径,通过连接后执行的shell命令find -name 查询出目标文件路径并处理成目标路径dst,而本地我是通过按行读取txt中需要上传的文件路径src,到此传入upload方法中即可上传。
缺点:首先新创建的文件需要先上传一遍,之后执行find命令才能查询到,这样才能做后续的步骤。当然如果各位有什么思路也可以说下,前提是老项目。新项目就用jenkins等部署工具吧。
代码中读取properties文件是由于需要切换环境而新增的配置文件如下:
Host=ip地址
UserName=用户名
Password=密码
package com.test; public class SshConfiguration { private String host; private String userName; private String password; //省略getset方法 }
1 package com.test; 2 3 import com.jcraft.jsch.Channel; 4 import com.jcraft.jsch.ChannelExec; 5 import com.jcraft.jsch.ChannelSftp; 6 import com.jcraft.jsch.JSch; 7 import com.jcraft.jsch.JSchException; 8 import com.jcraft.jsch.Session; 9 import com.jcraft.jsch.SftpException; 10 import com.jcraft.jsch.SftpProgressMonitor; 11 12 import java.io.BufferedReader; 13 import java.io.File; 14 import java.io.FileNotFoundException; 15 import java.io.FileReader; 16 import java.io.IOException; 17 import java.io.InputStream; 18 import java.io.InputStreamReader; 19 import java.util.ArrayList; 20 import java.util.Date; 21 import java.util.Properties; 22 23 24 import org.apache.log4j.Logger; 25 26 public class SFTPUtils 27 { 28 private static final Logger log = Logger.getLogger(SFTPUtils.class); 29 private ChannelSftp channelSftp; 30 // private ChannelExec channelExec; 31 private static Session session = null; 32 private int timeout = 60000; 33 private static String host; 34 private static String userName; 35 private static String passWord; 36 // 保存输出内容的容器 37 private static ArrayList<String> stdout; 38 39 public SFTPUtils(SshConfiguration conf) throws JSchException 40 { 41 log.info("try connect to " + conf.getHost() + ",username: " 42 + conf.getUserName() + ",password: " + conf.getPassword() 43 + ",port: " + conf.getPort()); 44 JSch jSch = new JSch(); // 创建JSch对象 45 session = jSch.getSession(conf.getUserName(), conf.getHost(), 46 conf.getPort());// 根据用户名,主机ip和端口获取一个Session对象 47 session.setPassword(conf.getPassword()); // 设置密码 48 Properties config = new Properties(); 49 config.put("StrictHostKeyChecking", "no"); 50 stdout = new ArrayList<String>(); 51 session.setConfig(config);// 为Session对象设置properties 52 session.setTimeout(timeout);// 设置超时 53 session.connect();// 通过Session建立连接 54 } 55 56 // public void download(String src, String dst) throws JSchException, 57 // SftpException { 58 // // src linux服务器文件地址,dst 本地存放地址 59 // channelSftp = (ChannelSftp) session.openChannel("sftp"); 60 // channelSftp.connect(); 61 // channelSftp.get(src, dst); 62 // channelSftp.quit(); 63 // } 64 65 public void upLoad(String src, String dst) throws JSchException, 66 SftpException 67 { 68 // src 本机文件地址。 dst 远程文件地址 69 channelSftp = (ChannelSftp) session.openChannel("sftp"); 70 channelSftp.connect(); 71 channelSftp.put(src, dst); 72 log.info("upload file success!"); 73 channelSftp.quit(); 74 } 75 76 public static void close() 77 { 78 session.disconnect(); 79 log.info("disconnect success!"); 80 } 81 static 82 { 83 Properties properties = new Properties(); 84 85 try 86 { 87 // 使用InPutStream流读取properties文件 88 BufferedReader bufferedReader = new BufferedReader(new FileReader("读取配置文件的路径xxx.properties")); 89 properties.load(bufferedReader); 90 } 91 catch (FileNotFoundException e1) 92 { 93 e1.printStackTrace(); 94 } 95 catch (IOException e) 96 { 97 e.printStackTrace(); 98 } 99 // 获取key对应的value值 100 host = properties.getProperty("Host"); 101 userName = properties.getProperty("UserName"); 102 passWord = properties.getProperty("Password"); 103 } 104 public static void main(String[] args) throws IOException 105 { 106 /** 107 * *********上传准备文件*************** 108 */ 109 SshConfiguration configuration = new SshConfiguration(); 110 configuration.setHost(host); 111 configuration.setUserName(userName); 112 configuration.setPassword(passWord); 113 configuration.setPort(22); 114 int returnCode = 0; 115 BufferedReader bufferedReader = null; 116 try 117 { 118 File file = new File("E:\uploadFile\upload.txt");//该txt中放的需要上传的文件全路径 如需定位class,可自行百度如何定位class路径 119 bufferedReader = new BufferedReader(new FileReader(file)); 120 } 121 catch (Exception e) 122 { 123 e.printStackTrace(); 124 log.error("Exception:", e); 125 } 126 String srcinput = null; 127 String shellCommand = null; 128 try 129 { 130 while ((srcinput = bufferedReader.readLine()) != null) // 按行读取 131 { 132 if("xx.x.xx.xxx的ip".equals(host)) 133 { 134 shellCommand = "find /84环境目录/ -name "; //84环境 135 } 136 else if("xx.x.xx.xxx的ip".equals(host)) 137 { 138 shellCommand = "find /142环境目录/ -name "; //142环境 139 } 140 else if("197".equals(host)) 141 { 142 shellCommand = ""; 143 } 144 145 146 StringBuilder commands = new StringBuilder(shellCommand); 147 if(srcinput.contains("--")) //文件中--就会跳过 148 { 149 continue; 150 } 151 SFTPUtils sftp = new SFTPUtils(configuration); 152 String[] asd = srcinput.split("\\"); 153 String fileName = asd[asd.length - 1]; 154 String fileNameRe = fileName; 155 if (fileNameRe.contains("$")) // 对$Actions类特殊处理shell命令,其中的$需加转义 156 { 157 StringBuilder rebStr = new StringBuilder(fileNameRe); 158 rebStr.insert(fileNameRe.indexOf("$"), "\"); 159 fileNameRe = rebStr.toString(); 160 } 161 // 打开通道,设置通道类型,和执行的命令 162 Channel channel = session.openChannel("exec"); 163 ChannelExec channelExec = (ChannelExec) channel; 164 commands = commands.append(fileNameRe); 165 channelExec.setCommand(commands.toString());// 设置shell命令 166 channelExec.setInputStream(null); 167 BufferedReader input = new BufferedReader( 168 new InputStreamReader(channelExec.getInputStream())); 169 channelExec.connect(); 170 log.info("执行的shell命令:" + commands); 171 // 接收远程服务器执行命令的结果 172 String line; 173 while ((line = input.readLine()) != null) 174 { 175 stdout.add(line); 176 } 177 input.close(); 178 // 得到returnCode 179 if (channelExec.isClosed()) 180 { 181 returnCode = channelExec.getExitStatus(); 182 } 183 log.info("returnCode:" + returnCode); 184 // 关闭通道 185 channelExec.disconnect(); 186 log.info("-----------------------准备上传文件-----------------------"); 187 if (stdout != null && stdout.size() == 1) // 不唯一则确认在服务器上是否还有别的 188 { 189 String str = stdout.get(0); 190 log.info("源文件:" + srcinput); 191 String dst = str.replace("/" + fileName, ""); 192 log.info("目标路径:" + dst); 193 // sftp.upLoad(srcinput, dst);上传前自己先确认路径 194 } 195 else//find的时候出现多条路径结果才需要else如果文件都是唯一的,就不需要else 196 { 197 log.info("请注意,文件是不唯一的!"); 198 // AccidentInsuranceServiceImpl.class特殊处理 84环境需要142环境不需要特殊处理 199 String dst = null; 200 if (srcinput.contains("AccidentInsuranceServiceImpl")) 201 { 202 for (String str : stdout) 203 { 204 if (str.contains("/唯一确认路径")) // 取出唯一的路径:老项目放得乱,有些文件不唯一 205 { 206 dst = str.replace("/" + fileName, ""); 207 } 208 } 209 } 210 // PolicyManageServiceImpl.class特殊处理 211 if (srcinput.contains("PolicyManageServiceImpl")) 212 { 213 for (String str : stdout) 214 { 215 if (srcinput.contains("根据本地目录确认上传的文件是要往哪传")) // 判断上传的是xxx下的类 216 { 217 if("ip地址".equals(host)) //84环境 218 { 219 if (str.contains("/唯一能确认的路径")) //取出唯一要上传的路径并处理 220 { 221 dst = str.replace("/" + fileName, ""); 222 } 223 } 224 else if("ip地址".equals(host)) //142环境 225 { 226 if (str.contains("/唯一能确认的路径")) //取出唯一要上传的路径并处理 227 { 228 dst = str.replace("/" + fileName, ""); 229 } 230 } 231 } 232 } 233 } 234 log.info("源文件:" + srcinput); 235 log.info("目标路径:" + dst); 236 // sftp.upLoad(srcinput, dst); 237 } 238 log.info("-----------------------上传文件结束-----------------------"); 239 } 240 241 } 242 catch (Exception e) 243 { 244 e.printStackTrace(); 245 log.error(e.getMessage(), e); 246 } 247 finally 248 { 249 if (bufferedReader != null) 250 { 251 bufferedReader.close(); 252 } 253 close(); 254 System.exit(0); 255 } 256 257 } 258 }