使用scp從windows拷貝文件到linux服務器 scp(security copy protocol)
1. 問題緣起:
需求:公司的項目系統需要將硬件採集到window上的數據文件轉移到我們的linux服務器上指定文件夾
2. 尋找解決方案: >
開始時沒有搞清楚需求,以爲就是像web系統一樣通過表單上傳文件到服務器一樣(只是不需要表單了,有點傻呵呵),想到的都是javaweb的文件上傳工具、方法,顯然是不行的,搞了2個小時左右,沒有找到一個行的通的解決方案,還在繼續鬱悶摸索,當然摸索的過程中也不斷的明確了點我到底想要什麼 1、所要做的操作是拷貝文件,2、環境是跨系統的,遠程的,3、操作的工具語言是java; 差不多在這個時候,我覺得爲了工程的進度不能在自己一個這樣胡亂摸索了,太浪費時間,老大就在旁邊,何不求教!
然後向老大描述了我的思考和探索進展情況,說還沒有找到可行的解決方案。老大就是老大,果然經驗(知識面廣)很重要,聽了以後告訴我scp,讓我看看,還幫我找了一個博客。看到scp,然後再思考對比發現,正是我要找的方案。至此,找到了理論上可以的解決方案。果然要多聽老人言,哈哈。
反思
那如果沒有老大的指點,我們應該如何面對一個問題?這個是關鍵。從這次問題中我覺得可以得到幾點答案:
> 1、就是知道想要什麼效果? 2、現在的是什麼情況? 3、想要怎麼做、可以怎麼做?
說白了就是搞清需求,在有針對性的找解決方案。
關鍵代碼
package service;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.SCPClient;
public class Scpclient {
static private Scpclient instance;
static synchronized public Scpclient getInstance(String IP, int port,
String username, String passward) {
if (instance == null) {
instance = new Scpclient(IP, port, username, passward);
}
return instance;
}
public Scpclient(String IP, int port, String username, String passward) {
this.ip = IP;
this.port = port;
this.username = username;
this.password = passward;
}
public void getFile(String remoteFile, String localTargetDirectory) {
Connection conn = new Connection(ip,port);
try {
conn.connect();
boolean isAuthenticated = conn.authenticateWithPassword(username,
password);
if (isAuthenticated == false) {
System.err.println("authentication failed");
}
SCPClient client = new SCPClient(conn);
client.get(remoteFile, localTargetDirectory);
conn.close();
} catch (IOException ex) {
Logger.getLogger(SCPClient.class.getName()).log(Level.SEVERE, null,ex);
}
}
public void putFile(String localFile, String remoteTargetDirectory) {
Connection conn = new Connection(ip,port);
try {
conn.connect();
boolean isAuthenticated = conn.authenticateWithPassword(username,
password);
if (isAuthenticated == false) {
System.err.println("authentication failed");
}
SCPClient client = new SCPClient(conn);
client.put(localFile, remoteTargetDirectory);
conn.close();
} catch (IOException ex) {
Logger.getLogger(SCPClient.class.getName()).log(Level.SEVERE, null,ex);
}
}
public void putFile(String localFile, String remoteFileName,String remoteTargetDirectory,String mode) {
Connection conn = new Connection(ip,port);
try {
conn.connect();
boolean isAuthenticated = conn.authenticateWithPassword(username,
password);
if (isAuthenticated == false) {
System.err.println("authentication failed");
}
SCPClient client = new SCPClient(conn);
if((mode == null) || (mode.length() == 0)){
mode = "0600";
}
client.put(localFile, remoteFileName, remoteTargetDirectory, mode);
//重命名
ch.ethz.ssh2.Session sess = conn.openSession();
String tmpPathName = remoteTargetDirectory +File.separator+ remoteFileName;
String newPathName = tmpPathName.substring(0, tmpPathName.lastIndexOf("."));
sess.execCommand("mv " + remoteFileName + " " + newPathName);//重命名回來
conn.close();
} catch (IOException ex) {
Logger.getLogger(SCPClient.class.getName()).log(Level.SEVERE, null,ex);
}
}
public void putFile(String localFile, String remoteFileName,String remoteTargetDirectory) {
Connection conn = new Connection(ip,port);
try {
conn.connect();
boolean isAuthenticated = conn.authenticateWithPassword(username,
password);
if (isAuthenticated == false) {
System.err.println("authentication failed");
}
SCPClient client = new SCPClient(conn);
client.put(getBytes(localFile), remoteFileName, remoteTargetDirectory);
conn.close();
} catch (IOException ex) {
Logger.getLogger(SCPClient.class.getName()).log(Level.SEVERE, null,ex);
}
}
public static byte[] getBytes(String filePath) {
byte[] buffer = null;
try {
File file = new File(filePath);
FileInputStream fis = new FileInputStream(file);
ByteArrayOutputStream byteArray = new ByteArrayOutputStream(1024*1024);
byte[] b = new byte[1024*1024];
int i;
while ((i = fis.read(b)) != -1) {
byteArray.write(b, 0, i);
}
fis.close();
byteArray.close();
buffer = byteArray.toByteArray();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return buffer;
}
private String ip;
private int port;
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
}
3. 調試嘗試解決方案核心功能
> 首先在網上找到的解決方案,剛好有代碼,就直接拿來用上了,需要一個scp支持jar包
包]
調試遇到問題1:
報錯:unknown host exception 未知主機異常
後來發現是把ip寫錯了,ip比如192.168.0.1,被我寫成了http://192.168.0.1,肯定就找不到主機了,改回來就好了
調試遇到問題2:
報錯:Remote scp terminated unexpectedly
意思:遠程scp意外終止。
剛開始只是盲目的去網上找這個錯誤的相關信息,然而結果並不理想,但是隨着對scp的瞭解,發現原來scp也是linux上運行的一個命令協議,和ssh一樣,那就現在linux上以scp協議連接然後 直接使用scp命令試一下吧,試一下,果然出錯了,如下:
[root@fengyun scpclient]# scp -t -d /home/scpclient/
-bash: scp: command not found
因爲遠程liunx服務器端不能運行scp命令,果然在網上找打解決辦法:
使用yum install openssh-clients命令安裝openssh-clients
“`
[root@fengyun tmp]# yum install openssh-clients
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
* base: mirrors.zju.edu.cn
* extras: mirrors.163.com
* updates: mirrors.163.com
base | 3.7 kB 00:00
extras | 3.4 kB 00:00
updates | 3.4 kB 00:00
Setting up Install Process
Resolving Dependencies
–> Running transaction check
—> Package openssh-clients.x86_64 0:5.3p1-122.el6 will be installed
–> Processing Dependency: openssh = 5.3p1-122.el6 for package: openssh-clients-5.3p1-122.el6.x86_64
–> Processing Dependency: libedit.so.0()(64bit) for package: openssh-clients-5.3p1-122.el6.x86_64
–> Running transaction check
—> Package libedit.x86_64 0:2.11-4.20080712cvs.1.el6 will be installed
—> Package openssh.x86_64 0:5.3p1-94.el6 will be updated
–> Processing Dependency: openssh = 5.3p1-94.el6 for package: openssh-server-5.3p1-94.el6.x86_64
—> Package openssh.x86_64 0:5.3p1-122.el6 will be an update
–> Running transaction check
—> Package openssh-server.x86_64 0:5.3p1-94.el6 will be updated
—> Package openssh-server.x86_64 0:5.3p1-122.el6 will be an update
–> Finished Dependency Resolution
Dependencies Resolved
==================================================================================================================================================================================================================
Package Arch Version Repository Size
Installing:
openssh-clients x86_64 5.3p1-122.el6 base 443 k
Installing for dependencies:
libedit x86_64 2.11-4.20080712cvs.1.el6 base 74 k
Updating for dependencies:
openssh x86_64 5.3p1-122.el6 base 277 k
openssh-server x86_64 5.3p1-122.el6 base 329 k
Transaction Summary
Install 2 Package(s)
Upgrade 2 Package(s)
Total download size: 1.1 M
Is this ok [y/N]: y
Downloading Packages:
(1/4): libedit-2.11-4.20080712cvs.1.el6.x86_64.rpm | 74 kB 00:00
(2/4): openssh-5.3p1-122.el6.x86_64.rpm | 277 kB 00:02
(3/4): openssh-clients-5.3p1-122.el6.x86_64.rpm | 443 kB 00:03
(4/4): openssh-server-5.3p1-122.el6.x86_64.rpm | 329 kB 00:02
Total 147 kB/s | 1.1 MB 00:07
Running rpm_check_debug
Running Transaction Test
Transaction Test Succeeded
Running Transaction
Updating : openssh-5.3p1-122.el6.x86_64 1/6
Installing : libedit-2.11-4.20080712cvs.1.el6.x86_64 2/6
Installing : openssh-clients-5.3p1-122.el6.x86_64 3/6
Updating : openssh-server-5.3p1-122.el6.x86_64 4/6
Cleanup : openssh-server-5.3p1-94.el6.x86_64 5/6
Cleanup : openssh-5.3p1-94.el6.x86_64 6/6
Verifying : openssh-server-5.3p1-122.el6.x86_64 1/6
Verifying : libedit-2.11-4.20080712cvs.1.el6.x86_64 2/6
Verifying : openssh-5.3p1-122.el6.x86_64 3/6
Verifying : openssh-clients-5.3p1-122.el6.x86_64 4/6
Verifying : openssh-5.3p1-94.el6.x86_64 5/6
Verifying : openssh-server-5.3p1-94.el6.x86_64 6/6
Installed:
openssh-clients.x86_64 0:5.3p1-122.el6
Dependency Installed:
libedit.x86_64 0:2.11-4.20080712cvs.1.el6
Dependency Updated:
openssh.x86_64 0:5.3p1-122.el6 openssh-server.x86_64 0:5.3p1-122.el6
Complete!
[root@fengyun tmp]#
“`
測試代碼:
@Test
public void test(){
Scpclient scpclient = new Scpclient("192.168.0.122", 22, "root", "linux root賬戶密碼");
scpclient.putFile("C:\\Users\\zhengss\\Pictures\\fullinfo.png", "fullinfo.png", "/home/scpclient/", null);
}
再使用secureCRT遠程連接linux工具,選擇scp協議連接linux服務器,測試scp -t -d /home/scpclient/
如下再次使用java程序傳輸文件成功,歐耶!