English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
SSH를 통해 서버 파일 업로드 다운로드
먼저 말할 것입니다
이전에 Apache의 FTP 오픈 소스 컴포넌트를 사용하여 서버 파일 업로드 다운로드 방법에 대해 기록한 적이 있습니다. 그러나 나중에는 파일을 지우는 데 권한 문제가 있어 서버上的 파일을 지울 수 없게 되었습니다. Windows에서 FileZilla Server를 사용하여 읽기 쓰기 권한을 설정하면 문제가 없지만, 서버 측에서는 그리 편리하지 않습니다.
因为自己需要实现资源管理功能,除了单文件的FastDFS存储之外,一些特定资源的存储还是打算暂时存放服务器上,项目组同事说后面不会专门在服务器上开FTP服务,于是改成了sftp方式进行操作。
这个东西要怎么用
首先要去下载jsch jar包,地址是:http://www.jcraft.com/jsch/。网站上也写的很清楚:JSch is a pure Java implementation of SSH2. 这个是SSH2的纯Java实现。使用ip和端口,输入用户名密码就可以正常使用了,和Secure CRT使用方式一致。那么怎么来使用这个有用的工具呢?
其实不会写也没关系,官方也给出了示例,链接:http://www.jcraft.com/jsch/examples/Shell.java,来看一眼吧:
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ /** * This program enables you to connect to sshd server and get the shell prompt. * $ CLASSPATH=.:../build javac Shell.java * $ CLASSPATH=.:../build java Shell * You will be asked username, hostname and passwd. * If everything works fine, you will get the shell prompt. Output may * be ugly because of lacks of terminal-emulation, but you can issue commands. * */ import com.jcraft.jsch.*; import java.awt.*; import javax.swing.*; public class Shell{ public static void main(String[] arg){ try{ JSch jsch=new JSch(); //jsch.setKnownHosts("/홈/foo/.ssh/known_hosts"); String host=null; if(arg.length>0){ host=arg[0]; } else{ host=JOptionPane.showInputDialog("Enter username@hostname", System.getProperty("user.name")+ "@localhost"); } String user=host.substring(0, host.indexOf('@')); host=host.substring(host.indexOf('@')+1); Session session=jsch.getSession(user, host, 22); String passwd = JOptionPane.showInputDialog("Enter password"); session.setPassword(passwd); UserInfo ui = new MyUserInfo(){ public void showMessage(String message){ JOptionPane.showMessageDialog(null, message); } public boolean promptYesNo(String message){ Object[] options={ "yes", "no" }; int foo=JOptionPane.showOptionDialog(null, message, "경고", JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE, null, options, options[0]); return foo==0; } // Session#connect() 호출 전에 비밀번호가 제공되지 않았다면, // 이 방법들도 구현하십시오, // * UserInfo#getPassword(), // * UserInfo#promptPassword(String message) 및 // * UIKeyboardInteractive#promptKeyboardInteractive() }; session.setUserInfo(ui); // It must not be recommended, but if you want to skip host-key check, // invoke following, // session.setConfig("StrictHostKeyChecking", "no"); //session.connect(); session.connect(30000); // making a connection with timeout. Channel channel=session.openChannel("shell"); // Enable agent-forwarding. //((ChannelShell)channel).setAgentForwarding(true); channel.setInputStream(System.in); /* // a hack for MS-DOS prompt on Windows. channel.setInputStream(new FilterInputStream(System.in){ public int read(byte[] b, int off, int len)throws IOException{ return in.read(b, off, (len>1024?1024:len)); } }); */ channel.setOutputStream(System.out); /* // Choose the pty-type "vt102". ((ChannelShell)channel).setPtyType("vt102 */ /* // Set environment variable "LANG" as "ja_JP.eucJP". ((ChannelShell)channel).setEnv("LANG", "ja_JP.eucJP"); */ //channel.connect(); channel.connect(3*1000); } catch(Exception e){ System.out.println(e); } } public static abstract class MyUserInfo implements UserInfo, UIKeyboardInteractive{ public String getPassword(){ return null; } public boolean promptYesNo(String str){ return false; } public String getPassphrase(){ return null; } public boolean promptPassphrase(String message){ return false; } public boolean promptPassword(String message){ return false; } String[] prompt, boolean[] echo){ return null; } } }
이 코드에서는 필요한 모든 것을 볼 수 있습니다. 먼저 사용자 정보를 생성해야 합니다. 이는 인증에 사용되며, UserInfo, UIKeyboardInteractive 두 개의 인터페이스를 구현하면 됩니다. 그런 다음 session을 생성하고 userInfo를 설정한 후 연결을 수행합니다.
파일 업로드/다운로드 래핑
위는 Jsch의 기본 사용 방법이며, 몇 가지 기본 패턴입니다. 아래에서는 우리가 사용하고자 하는 기능을 단축하여 파일 업로드/다운로드와 같은 작업을 수행할 수 있도록 자체적으로 래핑하겠습니다.
먼저, UserInfo를 생성해보겠습니다:
public class MyUserInfo implements UserInfo, UIKeyboardInteractive{ public String getPassword(){ return null; } public boolean promptYesNo(String str){ return true; } public String getPassphrase(){ return null; } public boolean promptPassphrase(String message){ return true; } public boolean promptPassword(String message){ return true; } public void showMessage(String message){ } @Override public String[] promptKeyboardInteractive(String arg0, String arg1, String arg2, String[] arg3, boolean[] arg4) { return null; } }
以下是实现类:
package com.tfxiaozi.common.utils; import java.io.InputStream; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Vector; import org.apache.log4j.Logger; import com.jcraft.jsch.Channel; import com.jcraft.jsch.ChannelExec; import com.jcraft.jsch.ChannelSftp; import com.jcraft.jsch.JSch; import com.jcraft.jsch.JSchException; import com.jcraft.jsch.Session; import com.jcraft.jsch.SftpException; import com.jcraft.jsch.SftpProgressMonitor; /** * SSH Utils * @author tfxiaozi * */ public class Ssh { Logger logger = Logger.getLogger(this.getClass()); private String host = ""; private String user = ""; private int port = 22; private String password = ""; private static final String PROTOCOL = "sftp"; JSch jsch = new JSch(); private Session session; private Channel channel; private ChannelSftp sftp; public String getHost() { return host; } public void setHost(String host) { this.host = host; } public String getUser() { return user; } public void setUser(String user) { this.user = user; } public Ssh() { } public Ssh(String host, int port, String user, String password) { this.host = host; this.user = user; this.password = password; this.port = port; } /** * connect ssh * @throws JSchException */ public void connect() throws JSchException { if (session == null) { session = jsch.getSession(user, host, port); MyUserInfo ui = new MyUserInfo(); session.setUserInfo(ui); session.setPassword(password); session.connect(); channel = session.openChannel(PROTOCOL); channel.connect(); sftp = (ChannelSftp)channel; } } /** * disconnect ssh */ public void disconnect() { if (session != null) { session.disconnect(); session = null; } } /** * upload * @param 로컬파일이름 * @param 원격파일이름 * @return */ public boolean upload(String localFileName, String remoteFileName) throws Exception{ boolean bSucc = false; try { SftpProgressMonitor monitor = new MyProgressMonitor(); int mode = ChannelSftp.OVERWRITE; sftp.put(localFileName, remoteFileName, monitor, mode); bSucc = true; } catch(Exception e) { logger.error(e); } finally { if (null != channel) { channel.disconnect(); } } return bSucc; } /** * 파일을 지우기 * @param directory * @param fileName * @return */ public boolean deteleFile(String directory, String fileName) { boolean flag = false; try { sftp.cd(directory); sftp.rm(fileName); flag = true; } catch (SftpException e) { flag = false; logger.error(e); } return flag; } /** * 디렉토리를 지우기 * @param directory 지울 디렉토리 * @param sure 지우기 전에 확인하십시오 * @return */ public String deleteDir(String directory, boolean sure) { String 명령어 = "rm" -rf " + directory; String result = execCommand(command, true); return result; } /** * 파일과 하위 파일을 압축합니다-디렉토리의 파일과 하위 파일을 압축하여 compressName로 명명된 zip 파일로 변환합니다 * @param directory 압축할 컨텐트 디렉토리 * @param compressName 압축된 후 디렉토리에 있는 이름 * @throws SftpException * @usage ssh.compressDir("/홈/tfxiaozi/webapp", "test.zip"); */ public void compressDir(String directory, String compressName) throws SftpException { String command = "cd "+ directory +"\nzip -r " + compressName + " ./" + compressName.substring(0, compressName.lastIndexOf(".")); execCommand(command, true); } /** * 다운로드 * @param 로컬파일이름 * @param 원격파일이름 * @return */ public boolean 다운로드(String 로컬파일이름, String 원격파일이름) { boolean bSucc = false; Channel channel = null; try { SftpProgressMonitor monitor = new MyProgressMonitor(); sftp.get(remoteFileName, localFileName, monitor, ChannelSftp.OVERWRITE); bSucc = true; } catch(Exception e) { logger.error(e); } finally { if (null != channel) { channel.disconnect(); } } return bSucc; } /** * execute command * @param command * @param flag * @return */ public String execCommand(String command, boolean flag) { Channel channel = null; InputStream in = null; StringBuffer sb = new StringBuffer("")} try { channel = session.openChannel("exec"); System.out.println("command:"); + command); ((ChannelExec)channel).setCommand("export TERM=ansi && " + command); ((ChannelExec)channel).setErrStream(System.err); in = channel.getInputStream(); channel.connect(); if (flag) { byte[] tmp = new byte[10240]; while (true) { while (in.available()>0) { int i = in.read(tmp, 0, 10240); if(i < 0) { break; } sb.append(new String(tmp, 0, i)); } if (channel.isClosed()){ break; } } } in.close(); } catch(Exception e){ logger.error(e); } finally { if (channel != null) { channel.disconnect(); } } return sb.toString(); } /** * get cpu info * @return */ public String[] getCpuInfo() { Channel channel = null; InputStream in = null; StringBuffer sb = new StringBuffer("")} try { channel = session.openChannel("exec"); ((ChannelExec)channel).setCommand("export TERM=ansi && top -bn 1//ansi一定要加 in = channel.getInputStream(); ((ChannelExec)channel).setErrStream(System.err); channel.connect(); byte[] tmp = new byte[10240]; while (true) { while (in.available()>0) { int i = in.read(tmp, 0, 10240); if(i < 0) { break; } sb.append(new String(tmp, 0, i)); } if (channel.isClosed()){ break; } } } catch(Exception e){ logger.error(e); } finally { if (channel != null) { channel.disconnect(); } } String buf = sb.toString(); if (buf.indexOf("Swap") != -1) { buf = buf.substring(0, buf.indexOf("Swap")); } if (buf.indexOf("Cpu") != -1) { buf = buf.substring(buf.indexOf("Cpu"), buf.length()); } buf.replaceAll(" ", " "); return buf.split("\\n"); } /** * get hard disk info * @return */ public String getHardDiskInfo() throws Exception{ Channel channel = null; InputStream in = null; StringBuffer sb = new StringBuffer("")} try { channel = session.openChannel("exec"); ((ChannelExec)channel).setCommand("df -lh"); in = channel.getInputStream(); ((ChannelExec)channel).setErrStream(System.err); channel.connect(); byte[] tmp = new byte[10240]; while (true) { while (in.available()>0) { int i = in.read(tmp, 0, 10240); if(i < 0) { break; } sb.append(new String(tmp, 0, i)); } if (channel.isClosed()){ break; } } } catch(Exception e){ throw new RuntimeException(e); } finally { if (channel != null) { channel.disconnect(); } } String buf = sb.toString(); String[] info = buf.split("\n"); if(info.length > 2) {//first line: Filesystem Size Used Avail Use% Mounted on String tmp = ""; for(int i=1; i< info.length; i++) { tmp = info[i]; String[] tmpArr = tmp.split("%"); if(tmpArr[1].trim().equals("/")){ boolean flag = true; while(flag) { tmp = tmp.replaceAll(" ", " "); if (tmp.indexOf(" ") == -1{ flag = false; } } String[] result = tmp.split(" "); if(result != null && result.length == 6) { buf = result[1] + " total, " + result[2] + " used, " + result[3] + " free"; break; } else { } } } } } else { } } buf = ""; } /** * return buf; * @return * @throws Exception */ public double getFreeDisk() throws Exception { String hardDiskInfo = getHardDiskInfo(); if(hardDiskInfo == null || hardDiskInfo.equals("")) { logger.error("get free harddisk space failed....."); return -1; } String[] diskInfo = hardDiskInfo.replace(" ", "").split(","); if(diskInfo == null || diskInfo.length == 0) { logger.error("get free disk info failed........."); return -1; } String free = diskInfo[2]; free = free.substring(0, free.indexOf("free")); //System.out.println("free space:" + free); String unit = free.substring(free.length()-1); //System.out.println("unit:" + unit); String freeSpace = free.substring(0, free.length()-1); double freeSpaceL = Double.parseDouble(freeSpace); //System.out.println("free spaceL:" + freeSpaceL); if(unit.equals("K")) { return freeSpaceL*1024; }else if(unit.equals("M")) { return freeSpaceL*1024*1024; } else if(unit.equals("G")) { return freeSpaceL*1024*1024*1024; } else if(unit.equals("T")) { return freeSpaceL*1024*1024*1024*1024; } else if(unit.equals("P")) { return freeSpaceL*1024*1024*1024*1024*1024; } return 0; } /** * 지정된 디렉토리에 있는 모든 서브 디렉토리 및 파일을 가져옵니다. * @param directory * @return * @throws Exception */ @SuppressWarnings("rawtypes") public List<String> listFiles(String directory) throws Exception { Vector fileList = null; List<String> fileNameList = new ArrayList<String>(); fileList = sftp.ls(directory); Iterator it = fileList.iterator(); while (it.hasNext()) { String fileName = ((ChannelSftp.LsEntry) it.next()).getFilename(); if (fileName.startsWith(".") || fileName.startsWith("..")) { continue; } fileNameList.add(fileName); } return fileNameList; } public boolean mkdir(String path) { boolean flag = false; try { sftp.mkdir(path); flag = true; } catch (SftpException e) { flag = false; } return flag; } }
테스트해 보세요;
public static void main(String[] arg) throws Exception{ Ssh ssh = new Ssh("10.10.10.83", 22, "test", "test"); try { ssh.connect(); } catch (JSchException e) { e.printStackTrace(); } /*String remotePath = ""/홈/tfxiaozi/" + "webapp"/"; try { ssh.listFiles(remotePath); } catch (Exception e) { ssh.mkdir(remotePath); }*/ /*boolean b = ssh.upload("d:");/test.zip", "webapp/ System.out.println(b);*/ //String []buf = ssh.getCpuInfo(); //System.out.println("cpu:" + buf[0]); //System.out.println("메모:" + buf[1]); //System.out.println(ssh.getHardDiskInfo().replace(" ", "")); //System.out.println(ssh.getFreeDisk()); /*List<String> list = ssh.listFiles("webapp"/test"); for(String s : list) { System.out.println(s); }*/ /*boolean b = ssh.deteleFile("webapp", "test.zip"); System.out.println(b);*/ /*try { String s = ssh.execCommand("ls" -l /홈/tfxiaozi/webapp1/test", true); System.out.println(s); } catch (Exception e) { System.out.println(e.getMessage()); }*/ //ssh.sftp.setFilenameEncoding("UTF"-8 /*try { String ss = ssh.execCommand("unzip" /홈/tfxiaozi/webapp1/테스트.zip -d /홈/tfxiaozi/webapp1/ System.out.println(ss); } catch (Exception e) { System.out.println( e.getMessage()); }*/ /*String 경로 = "/홈/tfxiaozi/webapp1/test.zip"; try { List<String> list = ssh.listFiles(경로); for(String s:list) { System.out.println(s); } System.out.println("ok"); } catch (Exception e) { System.out.println("추출 실패...."); }*/ /*String 명령어 = "rm" -rf /홈/tfxiaozi/webapp1/" + "물채국학"; String sss = ssh.execCommand(명령어, true); System.out.println(sss);*/ /*String 검색명령어 = "find" /홈/tfxiaozi/webapp1/물채국학 -이름 'index.html'"; String 결과 = ssh.execCommand(검색명령어, true); System.out.println(결과);*/ /*String 경로 = ""; ssh.listFiles(remotePath);*/ /* ssh.deleteDir("/홈/tfxiaozi/webapp1 */ //아래는 webapp에 해제됩니다.1디렉토리, webapp1/test/xxx //ssh.execCommand("unzip /홈/tfxiaozi/webapp1/테스트.zip -d /홈/tfxiaozi/webapp1 //아래는 해제된 디렉토리입니다./webapp1/test 디렉토리, webapp1/test/test/xxx //ssh.execCommand("unzip /홈/tfxiaozi/webapp1/테스트.zip -d /홈/tfxiaozi/webapp1 //ssh.compressDir("/홈/tfxiaozi/webapp1 //ssh.sftp.cd("/홈/tfxiaozi/webapp1 //ssh.compressDir("/홈/tfxiaozi/webapp1 /*boolean b = ssh.download("d:/temp/test.zip", "webapp/test.zip"); System.out.println(b);*/ //ssh.getHardDiskInfo(); System.out.println(ssh.getFreeDisk()); ssh.disconnect(); }
이제 리눅스 방식으로 직접 작업을 수행하겠지만, 중국어 파일을 압축해제할 때, 압축해제할 때 인코드가 고장날 수 있으므로, unzip와 같은 매개변수를 추가해야 합니다. -O cp936 테스트.zip -d /홈/tfxiaozi/테스트。
이것이 이 문서의 모든 내용입니다. 많은 도움이 되길 바랍니다. 또한, 나르시아 가이드를 많이 지지해 주세요.
언급: 이 문서의 내용은 인터넷에서 가져왔으며, 저작권자는 모두에게 있습니다. 내용은 인터넷 사용자가 자발적으로 기여하고 업로드한 것이며, 이 사이트는 소유권을 가지지 않으며, 인공적인 편집을 하지 않았으며, 관련 법적 책임도 부담하지 않습니다. 저작권 위반 내용이 있음을 발견하면, notice#w로 이메일을 보내 주십시오.3codebox.com에 대한 신고를 보내기 위해 #을 @으로 변경하고, 관련 증거를 제공하십시오. 사실을 확인하면, 이 사이트는 즉시 의심스러운 저작권 내용을 제거합니다.