1. 程式人生 > >SFTP服務配置以及命令/程式碼操作

SFTP服務配置以及命令/程式碼操作

一、SFTP簡述

二、SFTP服務配置(基於CentOS 7)

三、SFTP常用命令

五、踩坑記錄

一、SFTP簡述

sftp(Secure File Transfer Protocol)是一種安全的檔案傳送協議,是ssh內含協議,也就是說只要sshd伺服器啟動了,sftp就可使用,不需要額外安裝,它的預設埠和SSH一樣為22。
sftp通過使用加密/解密技術來保障傳輸檔案的安全性,因此sftp的傳輸效率比普通的FTP要低,但sftp的安全性要比ftp高,因此sftp通常用於報表、對賬單等對安全性要求較高的場景。

二、SFTP服務配置(基於Centos 7)

在CentOS 7系統中按照如下步驟配置sftp服務
1、使用root使用者檢視openssh的版本:版本需大於4.8p1

ssh -V    // 如果版本過低,可以使用 yun update 進行更新

2、使用root使用者建立使用者組,組名為sftpgroup;建立sftp使用者,使用者名稱為sftpuser,並設定密碼

groupadd sftpgroup      // 建立sftp組

useradd -g sftpgroup -M -s /sbin/nologin sftpuser    //-M 表示建立使用者時不生成對應home目錄,-s /sbin/nologin 表示sftp使用者不能登入系統

passwd sftpuser        // 修改sftp使用者密碼

3、修改配置檔案sshd_config

vi /etc/ssh/sshd_config

修改如下:

 將下面這行註釋掉
    #Subsystem sftp /usr/libexec/openssh/sftp-server
    ## 在檔案末尾新增如下幾行
Subsystem sftp internal-sftp
Match Group sftpgroup
X11Forwarding no 
AllowTcpForwarding no
ChrootDirectory %h
ForceCommand internal-sftp

4、使用root使用者新建目錄/home/sftpfile,將其設定為sftpuser的home目錄,並指定目錄許可權

mkdir -p /sftp/sftpuser     //-p 表示parents,即遞迴建立目錄
usermod -d /sftp/sftpuser sftpuser    // -d 表示修改使用者home目錄

// 設定Chroot目錄許可權
chown root:sftpgroup   /sftp/sftpuser
chmod 755 /sftp/sftpuser

// 設定sftp使用者可以操作的目錄
mkdir /sftp/sftpuser/upload
chown sftpuser:sftpgroup /sftp/sftpuser/upload
chmod 755 /sftp/sftpuser/upload

5、重啟SSH

systemctl restart sshd.service

6、驗證:切換到sftpuser使用者進行驗證

sftp [email protected]

三、SFTP常用命令

sftp的常用命令和ftp基本相同,使用help命令即可查詢

四、Java程式碼實現SFTP操作

Java操作sftp需要使用一個開源包jsch,官網地址為 http://www.jcraft.com/jsch/,Maven專案中通過在pom.xml中引入如下依賴,如果需要其他版本,可在Maven中央倉庫http://mvnrepository.com/ 查詢。

<dependency>
    <groupId>com.jcraft</groupId>
    <artifactId>jsch</artifactId>
    <version>0.1.54</version>
</dependency>

Jsch提供了sftp的各類操作的Java實現,ChannelSftp類是實現SFTP操作的核心類,sftp的命令即為該類中的方法,可以對比上圖的sftp常用命令,如:sftp命令中ls為展示目錄下的檔案列表,則ChannelSftp類中有 ls() 方法與其對應。

1、sftp服務連線和關閉

private void connect(SFTPConfig sftpConfig) {
        try {
            // 通過JSch物件獲取session物件
            session = new JSch().getSession(
                    sftpConfig.getSftpUserName(),           // sftp使用者名稱
                    sftpConfig.getSftpHost(),               // sftp主機IP
                    sftpConfig.getSftpPort());              // sftp埠
            if (null != sftpConfig.getSftpPassword()) {
                session.setPassword(sftpConfig.getSftpPassword());     // sftp使用者密碼
            }
            if (null != sftpConfig.getTimeout()) {
                session.setTimeout(sftpConfig.getTimeout());           // 超時時間
            }
            session.setConfig("StrictHostKeyChecking", "no");          // 讓ssh客戶端自動接受新主機的hostkey
            session.connect();

            this.channelSftp = (ChannelSftp) session.openChannel("sftp");   // 開啟sftp渠道,除sftp外還有shell、X11等型別
            this.channelSftp.connect();

        } catch (JSchException e) {
            this.close();
            e.printStackTrace();
        }
    }

public void close() {
        channelSftp.quit();
        if (null != channelSftp) {
            channelSftp.disconnect();
        }
        if (null != session) {
            session.disconnect();
        }
    }

2、JSch的傳輸模式

JSch有三種檔案傳輸模式:
(1)OVERWRITE:完全覆蓋模式。JSch的預設檔案傳輸模式,傳輸的檔案將覆蓋目標檔案。
(2)APPEND:追加模式。如果目標檔案已存在,則在目標檔案後追加。
(3)RESUME:恢復模式。如果檔案正在傳輸時,由於網路等原因導致傳輸中斷,則下一次傳輸相同的檔案
時,會從上一次中斷的地方續傳。

3、sftp上傳

JSch為每種傳輸模式提供了3類不同的上傳方法
(1)最常用也是最簡單的呼叫

/**
     * @param sftpParams
     * @param channelSftpModel 呼叫的模式: ChannelSftp.OVERWRITE,ChannelSftp.APPEND,ChannelSftp.RESUME
     * @throws SFTPException
     */
public void upload(SFTPParams sftpParams, int channelSftpModel) throws SFTPException {
        try {
            channelSftp.put(sftpParams.getLocalFilepath(), sftpParams.getRemoteFilepath(), channelSftpModel);
        } catch (SftpException e) {
            throw new SFTPException("Upload [" + sftpParams.getLocalFilepath() + "] to SFTP "
                    + sftpConfig.getSftpHost() + ":" + sftpConfig.getSftpPort()
                    + "[" + sftpParams.getRemoteFilepath() + "]" + " error.", e);
        }
    }

(2)基於InputStream的呼叫
這種方法適用於原始檔案不存在,需要儲存到遠端目錄的資料來源於網路或者程式碼生成,當然原始檔案如果存在,也可以通過FileInputStream上傳。

/**
     *
     * @param sftpParams
     * @param channelSftpModel 呼叫的模式: ChannelSftp.OVERWRITE,ChannelSftp.APPEND,ChannelSftp.RESUME
     * @param src 輸入流
     * @throws SFTPException
     */
    public void upload(SFTPParams sftpParams, int channelSftpModel, InputStream src) throws SFTPException {
        try {
            channelSftp.put(src, sftpParams.getRemoteFilepath(), channelSftpModel);
        } catch (SftpException e) {
            throw new SFTPException("Upload [" + sftpParams.getLocalFilepath() + "] to SFTP "
                    + sftpConfig.getSftpHost() + ":" + sftpConfig.getSftpPort()
                    + "[" + sftpParams.getRemoteFilepath() + "]" + " error.", e);
        }
    }

(3)基於OutputStream的呼叫
通過向put()方法返回的輸出流中寫入資料的方式來儲存檔案,這種方式可以自定義輸出流的資料塊大小(Jsch預設資料塊大小為32KB)

/**
     * @param sftpParams
     * @param channelSftpModel 呼叫的模式: ChannelSftp.OVERWRITE,ChannelSftp.APPEND,ChannelSftp.RESUME
     * @param src 輸入流
     * @param bufferSize 資料塊大小
     * @throws SFTPException
     */
    public void upload(SFTPParams sftpParams, int channelSftpModel, InputStream src, int bufferSize) throws SFTPException {
        OutputStream out = null;
        try {
            out = channelSftp.put(sftpParams.getRemoteFilepath(), channelSftpModel);
            byte[] buff = new byte[bufferSize]; // 設定每次傳輸的資料塊大小
            int read;
            if (out != null) {
                do {
                    read = src.read(buff, 0, buff.length);
                    if (read > 0) {
                        out.write(buff, 0, read);
                    }
                    out.flush();
                } while (read >= 0);
            }
        } catch (IOException e) {
            throw new SFTPException("Upload [" + sftpParams.getLocalFilepath() + "] to SFTP "
                    + sftpConfig.getSftpHost() + ":" + sftpConfig.getSftpPort()
                    + "[" + sftpParams.getRemoteFilepath() + "]" + " error.", e);
        } catch (SftpException e) {
            throw new SFTPException("Upload [" + sftpParams.getLocalFilepath() + "] to SFTP "
                    + sftpConfig.getSftpHost() + ":" + sftpConfig.getSftpPort()
                    + "[" + sftpParams.getRemoteFilepath() + "]" + " error.", e);
        } finally {
            if (null != out) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

4、sftp下載

JSch提供了3類不同的下載方法,JSch提供的下載方法,如果沒有顯示指明傳輸模式,則預設為覆蓋模式
(1)最常用也是最簡單的呼叫

public void download(SFTPParams sftpParams) throws SFTPException {
        try {
            channelSftp.get(sftpParams.getRemoteFilepath(), sftpParams.getLocalFilepath());
        } catch (SftpException e) {
            throw new SFTPException("Download [" + sftpParams.getRemoteFilepath() + "] from SFTP "
                    + sftpConfig.getSftpHost() + ":" + sftpConfig.getSftpPort() + " error.", e);
        }
    }

(2)基於OutputStream的呼叫
開啟一個輸出流,將遠端檔案寫入輸出流中。如,通過FileOutPutStream得到一個本地檔案輸出流,呼叫該方法將遠端檔案資料寫入該輸出流,預設資料塊大小為32KB。

public void download(SFTPParams sftpParams, OutputStream os) throws SFTPException {
        try {
            channelSftp.get(sftpParams.getRemoteFilepath(), os);
        } catch (SftpException e) {
            throw new SFTPException("Download [" + sftpParams.getRemoteFilepath() + "] from SFTP "
                    + sftpConfig.getSftpHost() + ":" + sftpConfig.getSftpPort() + " error.", e);
        }
    }

(3)基於InputStream呼叫
將遠端檔案資料轉換成一個輸入流,之後可以通過程式碼從輸入流中拿取資料

public InputStream download2InputStream(SFTPParams sftpParams) throws SFTPException {
        try {
            return channelSftp.get(sftpParams.getRemoteFilepath());
        } catch (SftpException e) {
            throw new SFTPException("Download [" + sftpParams.getRemoteFilepath() + "] from SFTP "
                    + sftpConfig.getSftpHost() + ":" + sftpConfig.getSftpPort() + " error.", e);
        }
    }

5、監聽器

JSch可以檔案傳輸時,對傳輸進度進行監控,通過實現JSch提供的SftpProgressMonitor介面來實現監聽器的功能。
SftpProgressMonitor介面定義如下

package com.jcraft.jsch;

public interface SftpProgressMonitor{
  public static final int PUT=0;
  public static final int GET=1;
  public static final long UNKNOWN_SIZE = -1L;

  // 傳輸開始時,呼叫init方法。其中op為操作型別,即為上面定義的PUT/GET,max為檔案的大小
  void init(int op, String src, String dest, long max);   
  // 當每次傳輸一個數據塊後,呼叫count方法,引數為這一次傳輸的資料塊大小
  boolean count(long count);
  // 傳輸結束時,呼叫end方法
  void end();
}

現在實現一個每隔1秒,獲取上傳的進度的功能

public class TimerSFTPProgressMonitor implements SftpProgressMonitor {

    private boolean isTransEnd = false; // 是否傳輸完成
    private long fileTotalSize;  // 需要傳輸檔案的大小
    private long fileTransferedSize; // 已傳輸的大小
    private ScheduledExecutorService service = Executors.newScheduledThreadPool(1);

    public void init(int op, String src, String dest, long max) {
        System.out.println("Begin transferring.");
        fileTotalSize = max;
        if (fileTotalSize != 0) {
            final DecimalFormat df = new DecimalFormat("#.##");
            service.scheduleAtFixedRate(new Runnable() {
                public void run() {
                    if (!isTransEnd) {
                        if (fileTransferedSize != fileTotalSize) {
                            double d = ((double) fileTransferedSize * 100) / (double) fileTotalSize;
                            System.out.println("Current progress: " + df.format(d) + "%");
                        } else {
                            isTransEnd = true; // 已傳輸大小等於檔案總大小,則已完成
                        }
                    }
                }
            }, 0, 1, TimeUnit.SECONDS);
        }
    }

    public boolean count(final long count) {
        fileTransferedSize = fileTransferedSize + count;
        return true;
    }

    public void end() {
        service.shutdown();
        System.out.println("End transferring, transferedSize : " + fileTransferedSize);
    }

}

最後效果如下

五、踩坑記錄

1、JSch實現sftp上傳時,2: No such file

原因:在SFTP服務配置一節中,我們將檔案上傳到/sftp/sftpuser/upload,但是在程式碼中不能直接寫入這個路徑,而需要寫入 /upload 這個路徑,因為對於sftpuser來說,它是沒有/sftp/sftpuser/這個路徑的。可以通過sftp的 ls / 命令來檢視

相關推薦

SFTP服務配置以及命令/程式碼操作

一、SFTP簡述 二、SFTP服務配置(基於CentOS 7) 三、SFTP常用命令 五、踩坑記錄 一、SFTP簡述 sftp(Secure File Transfer Protocol)是一種安全的檔案傳送協議,是ssh內含協議,也就是說

Linux下sftp服務配置操作說明

Linux下sftp服務配置操作說明Linux下sftp服務配置操作說明 查看openssh的版本,使用ssh -V 命令來查看openssh的版本,版本必須大於4.8p1,低於的這個版本需要升級。1、創建sftpusers組groupadd sftpusers2、創建sftpusers用戶,設置用戶不能用於

mongodb安裝配置以及其他基礎操作

mongodb最近公司有個項目要用mongodb,之前沒搞過,今天臨時磨刀上陣,花了半天時間研究,中間有遇到幾個坑寫出來分享給大家。tar -zxf mongodb-linux-x86_64-v3.6.3.tgzcp -pr mongodb-linux-x86_64-v3.6.3 /usr/local/mon

打包springboot項目部署到雲服務以及其他一些操作

java 運行 code bsp jdk1.8 yun yum 服務器 上傳文件 1.項目打包:https://blog.csdn.net/qq_34409900/article/details/80561277 2.添加yum源:https://help.aliyun.

Linux入門總結——虛擬機安裝配置以及vim簡單操作

路徑 con 後繼 更新 功能 繼續 共享文件 hive 文件訪問 安裝配置ubuntu 安裝準備 vittualbox-5.2.22版本(win10) ubuntu-12.04 安裝VirtualBox 1.雙擊VirtualBox-5.2.2-119230-Win,默認

spring boot 上傳檔案配置以及前後臺程式碼

spring boot上傳檔案 1、pom.xml依賴新增 org.apache.poi poi 3.8 com

Linux入門總結——虛擬機器安裝配置以及vim簡單操作

安裝配置ubuntu 安裝準備 vittualbox-5.2.22版本(win10) ubuntu-12.04 安裝VirtualBox 1.雙擊VirtualBox-5.2.2-119230-Win,預設安裝。 2.新建—》名稱ubuntu(可自定) 型別:linux 版本:ubuntu64/ubuntu3

Mybatis學習第一天——Mybatis的安裝配置以及基本CURD操作

1.Mybatis下載  Mybatis是開源的持久層框架,能夠度jdbc進行簡單的封裝,但其並不是完全的ORM(Object Relational Mapping,物件關係對映),無法脫離資料庫進行適配。目前Mybatis能夠在githup上直接下載:https://github.com/mybatis/m

針對javaWeb專案部署伺服器上的流程和配置以及命令

部署流程,tomcat  資料庫環境的安裝就不介紹了。 1.進入資料夾命令  cd,如進入usr下面的local下面的tomcat,連線上伺服器後,用 cd /usr/local/tomcat    如果你嫌棄把所有的命令都打出來,就打前幾個字母用Tab鍵會自動補全。

Sublime安裝配置以及scala程式碼測試編譯

下載安裝Sublime text3 、JDK、scala https://yunpan.cn/cSXuu2A3HbK3R 訪問密碼 c987 注意Scala和jdk需要提前下載配置好(win10 64bit) scala: https://yunpan

Linux 配置 history 命令顯示操作時間、使用者和登入 IP

一、在配置檔案中(/etc/bashrc 或者 /etc/profile 或者~/.bash_profile 或者 ~/.bashrc)新增如下配置 HISTFILESIZE=4000

cisco路由器的Dhcp配置以及一個dhcp服務不同網段共享

dhcp 不同網段 路由器 實驗拓撲:(上面有兩種配置方式,還有一種就是交換機的配置方式,路由器的配置方式一模一樣,就是要把vlan端口打開 並設置vlan的ip就可以實現dhcp服務)實驗步驟:第一種:路由器充當dhcp服務(如圖)(註:路由器本身需要網絡之間發包任務,最好不要在路由器上配置除了

Linux操作系統的安裝以及基本的操作命令詳解

tomcat7 replicat rem 命令詳解 onf 日誌文件 out 橋接 ati 背景:使用的虛擬機安裝Linux 虛擬機使用的是VMware Linux版本:CentOS-6.7-X86 自行下載:CentOS-6.7-x86_64-bin-DVD1.

個人技術博客——linux服務配置以及flask框架

png sgi clas 創建 安全協議 deb win com 點擊 本次的軟件工程實踐,我負責我們組後臺服務的搭建,我選用了bandwagon的服務器,安裝的是Debian GNU/Linux,後端服務是用python的flask框架。 本地登錄遠程服務器 在本地登錄

(linux服務器)apache開啟gzip的配置以及效果對比

evel 左右 bsp image XML php 以及 .com erb 配置: 1 進入配置目錄: cd /opt/lampp/etc 2 編輯配置文件: vi httpd.conf 3 配置:增加以下代碼片段 # gzip壓縮 <IfModule mo

三層交換機dhcp服務配置命令

打開 png cer fault AI one -c lin trunk 每個二層交換機上配置好VLAN ,在三層交換機上配置好VLAN ip ,在三層交換機上打開fa0/1-fa0/3的trunk ,再給三層交換機配置dhcp服務,下面是VLAN10的,每個VLAN

Win7 環境下虛擬機內 Samba 服務器的安裝、配置以及與主機的通信實現

path 正常 驅動器 update tps RM 找到 samba配置 需要 考慮到window和linux虛擬機之間互傳文件較為麻煩,遂打算在虛擬機中安裝Samba服務器,以此實現共享文件給window使用。然而安裝配置過程曲折,遂作記錄如下: 一、samba服務器的安

Vsftpd服務配置、ftp命令、錯誤代碼、日誌格式

Vsftpd服務配置 ftp命令 錯誤代碼 日誌格式 1、Vsftpd的配置文件:/etc/vsftpd/vsftpd.conf :主配置文件 /usr/sbin/vsftpd :Vsftpd的主程序/etc/rc.d/init.d/vsftpd

OpenLDAP 服務端安裝與配置以及原理

ldapOpenLDAP 服務端安裝與配置 一、什麽是LDAP 目錄是一個為查詢、瀏覽和搜索而優化的專業分布式數據庫,它呈樹狀結構組織數據,就好象Linux/Unix系統中的文件目錄一樣。目錄數據庫和關 系數據庫不同,它有優異的讀性能,但寫性能差,並且沒有事務處理、回滾等復雜功能,不適於存儲修改頻繁的數據。所

查找nginx安裝的路徑以及相關安裝操作命令

cor clas 顯示 操作 nginx安裝 行記錄 font nginx版本號 nginx 1、查看nginx安裝目錄 輸入命令 # ps -ef | grep nginx 返回結果包含安裝目錄 root 2662 1 0 07:12 ?