DevOps系列文章之 linux安装ftp

news2025/1/12 3:42:35

第一步

1、用root 进入系统

2、使用命令 rpm -qa|grep vsftpd 查看系统是否安装了ftp,若安装了vsftp,使用这个命令会在屏幕上显示vsftpd的版本

3、使用命令rpm -e vsftpd 即可卸载ftp

4、再使用rpm -qa|grep vsftpd 查看系统是否已删除ftp,若删除成功,屏幕上不会显示vsftpd的版本
安装vsftpd

查看是否已经安装vsftpd
rpm -qa | grep vsftpd

如果没有,就安装,并设置开机启动
yum -y install vsftpd
chkconfig vsftpd on

配置防火墙

本次用虚拟机,直接关了了事

开启防火墙
systemctl start firewalld
//临时关闭
# service iptables stop
//禁止开机启动
# chkconfig iptables off

第二步

FTP用户管理
创建FTP用户并指定分组和主目录

useradd -d /home/ftp -s /sbin/nologin -g ftp -G root ftpadmin

解析:
useradd 添加用户ftpadmin
-d 指定用户根目录为/home/ftp
-s 指定shell脚本为/sbin/nologin,表示不允许shell登录
-g 创建分组ftp
-G 指定root分组
PS:创建有问题可以删除重新创建 userdel -r ftpadmin
设定密码

passwd ftpadmin

输入 1234


设置访问权限

chown ftpadmin /home/ftp

第三步

配置vsftpd

1.默认的配置文件是/etc/vsftpd/vsftpd.conf,你可以用文本编辑器打开。
vi /etc/vsftpd/vsftpd.conf

修改为anonymous_enable=NO

2.添加ftp用户

下面是添加ftpuser用户,设置根目录为/home/wwwroot/ftpuser,禁止此用户登录SSH的权限,并限制其访问其它目录。
#chroot_list_enable=YES
# (default follows)
#chroot_list_file=/etc/vsftpd.chroot_list

改为
chroot_list_enable=YES
# (default follows)
chroot_list_file=/etc/vsftpd/chroot_list

3、编辑文件chroot_list:
vi /etc/vsftpd/chroot_list

内容为ftp用户名,每个用户占一行,如:
ftpadmin

4、编辑shells 

vi /etc/shells 

添加/sbin/nologin

 最后重新启动vsftpd
service vsftpd restart

第四步

测试

本地验证ftp是否可以正常访问

2.1、安装ftp

yum -y install ftp

2.2、使用ftpadmin登陆,密码 1234

ftp 192.168.1.12

查看FTP服务器文件夹信息 

220表示服务正常,可以登陆;230表示登陆成功。

 外部证ftp是否可以正常访问

1、关闭防火墙(也可以设置防火墙规则)

systemctl stop firewalld.service

或者 将21端口插入到INPUT的ACCEPT中

 iptables -I INPUT 5 -p tcp --dport 21 -j ACCEPT

为防止机器重启后防火墙服务重新开启,可将防火墙服务永久关闭。

systemctl disable firewalld.service

windows 开始 —-> 输入CMD —–> ftp 192.168.1.12
提示,输入用户名,然后输入密码,如下图所示,登录成功 

 也可以使用软件Xftp5或Filezilla,如下图所示:

 

第五步

maven依赖pom.xml 中添加

<dependency>
    	<groupId>commons-fileupload</groupId>
		<artifactId>commons-fileupload</artifactId>
		<version>1.1.1</version>
</dependency>

Java客户端访问

package com.sac.demo.test;


import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.TimeZone;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPClientConfig;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;

import org.apache.log4j.Logger;

public class Ftp {
    private FTPClient ftpClient;
    private String strIp;
    private int intPort;
    private String user;
    private String password;

    private static Logger logger = Logger.getLogger(Ftp.class.getName());

    /* *
     * Ftp构造函数
     */
    public Ftp(String strIp, int intPort, String user, String Password) {
        this.strIp = strIp;
        this.intPort = intPort;
        this.user = user;
        this.password = Password;
        this.ftpClient = new FTPClient();
    }
    /**
     * @return 判断是否登入成功
     * */
    public boolean ftpLogin() {
        boolean isLogin = false;
        FTPClientConfig ftpClientConfig = new FTPClientConfig();
        ftpClientConfig.setServerTimeZoneId(TimeZone.getDefault().getID());
        this.ftpClient.setControlEncoding("GBK");
        this.ftpClient.configure(ftpClientConfig);
        try {
            if (this.intPort > 0) {
                this.ftpClient.connect(this.strIp, this.intPort);
            } else {
                this.ftpClient.connect(this.strIp);
            }
            // FTP服务器连接回答
            int reply = this.ftpClient.getReplyCode();
            if (!FTPReply.isPositiveCompletion(reply)) {
                this.ftpClient.disconnect();
                logger.error("登录FTP服务失败!");
                return isLogin;
            }
            this.ftpClient.login(this.user, this.password);
            // 设置传输协议
            this.ftpClient.enterLocalPassiveMode();
            this.ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
            logger.info("恭喜" + this.user + "成功登陆FTP服务器");
            isLogin = true;
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(this.user + "登录FTP服务失败!" + e.getMessage());
        }
        this.ftpClient.setBufferSize(1024 * 2);
        this.ftpClient.setDataTimeout(30 * 1000);
        return isLogin;
    }

    /**
     * @退出关闭服务器链接
     * */
    public void ftpLogOut() {
        if (null != this.ftpClient && this.ftpClient.isConnected()) {
            try {
                boolean reuslt = this.ftpClient.logout();// 退出FTP服务器
                if (reuslt) {
                    logger.info("成功退出服务器");
                }
            } catch (IOException e) {
                e.printStackTrace();
                logger.warn("退出FTP服务器异常!" + e.getMessage());
            } finally {
                try {
                    this.ftpClient.disconnect();// 关闭FTP服务器的连接
                } catch (IOException e) {
                    e.printStackTrace();
                    logger.warn("关闭FTP服务器的连接异常!");
                }
            }
        }
    }

    /***
     * 上传Ftp文件
     * @param localFile 当地文件
     * @param romotUpLoadePath 上传服务器路径 - 应该以/结束
     * */
    public boolean uploadFile(File localFile, String romotUpLoadePath) {
        BufferedInputStream inStream = null;
        boolean success = false;
        try {
            this.ftpClient.changeWorkingDirectory(romotUpLoadePath);// 改变工作路径
            inStream = new BufferedInputStream(new FileInputStream(localFile));
            logger.info(localFile.getName() + "开始上传.....");
            success = this.ftpClient.storeFile(localFile.getName(), inStream);
            if (success == true) {
                logger.info(localFile.getName() + "上传成功");
                return success;
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            logger.error(localFile + "未找到");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (inStream != null) {
                try {
                    inStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return success;
    }

    /***
     * 下载文件
     * @param remoteFileName   待下载文件名称
     * @param localDires 下载到当地那个路径下
     * @param remoteDownLoadPath remoteFileName所在的路径
     * */

    public boolean downloadFile(String remoteFileName, String localDires,
                                String remoteDownLoadPath) {
        String strFilePath = localDires + remoteFileName;
        BufferedOutputStream outStream = null;
        boolean success = false;
        try {
            this.ftpClient.changeWorkingDirectory(remoteDownLoadPath);
            outStream = new BufferedOutputStream(new FileOutputStream(
                    strFilePath));
            logger.info(remoteFileName + "开始下载....");
            success = this.ftpClient.retrieveFile(remoteFileName, outStream);
            if (success == true) {
                logger.info(remoteFileName + "成功下载到" + strFilePath);
                return success;
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(remoteFileName + "下载失败");
        } finally {
            if (null != outStream) {
                try {
                    outStream.flush();
                    outStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        if (success == false) {
            logger.error(remoteFileName + "下载失败!!!");
        }
        return success;
    }

    /***
     * @上传文件夹
     * @param localDirectory
     *            当地文件夹
     * @param remoteDirectoryPath
     *            Ftp 服务器路径 以目录"/"结束
     * */
    public boolean uploadDirectory(String localDirectory,
                                   String remoteDirectoryPath) {
        File src = new File(localDirectory);
        try {
            remoteDirectoryPath = remoteDirectoryPath + src.getName() + "/";
            this.ftpClient.makeDirectory(remoteDirectoryPath);
            // ftpClient.listDirectories();
        } catch (IOException e) {
            e.printStackTrace();
            logger.info(remoteDirectoryPath + "目录创建失败");
        }
        File[] allFile = src.listFiles();
        for (int currentFile = 0; currentFile < allFile.length; currentFile++) {
            if (!allFile[currentFile].isDirectory()) {
                String srcName = allFile[currentFile].getPath().toString();
                uploadFile(new File(srcName), remoteDirectoryPath);
            }
        }
        for (int currentFile = 0; currentFile < allFile.length; currentFile++) {
            if (allFile[currentFile].isDirectory()) {
                // 递归
                uploadDirectory(allFile[currentFile].getPath().toString(),
                        remoteDirectoryPath);
            }
        }
        return true;
    }

    /***
     * @下载文件夹
     * @param localDirectoryPath 本地地址
     * @param remoteDirectory 远程文件夹
     * */
    public boolean downLoadDirectory(String localDirectoryPath,String remoteDirectory) {
        try {
            String fileName = new File(remoteDirectory).getName();
            localDirectoryPath = localDirectoryPath + fileName + "//";
            new File(localDirectoryPath).mkdirs();
            FTPFile[] allFile = this.ftpClient.listFiles(remoteDirectory);
            for (int currentFile = 0; currentFile < allFile.length; currentFile++) {
                if (!allFile[currentFile].isDirectory()) {
                    downloadFile(allFile[currentFile].getName(),localDirectoryPath, remoteDirectory);
                }
            }
            for (int currentFile = 0; currentFile < allFile.length; currentFile++) {
                if (allFile[currentFile].isDirectory()) {
                    String strremoteDirectoryPath = remoteDirectory + "/"+ allFile[currentFile].getName();
                    downLoadDirectory(localDirectoryPath,strremoteDirectoryPath);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
            logger.info("下载文件夹失败");
            return false;
        }
        return true;
    }
    // FtpClient的Set 和 Get 函数
    public FTPClient getFtpClient() {
        return ftpClient;
    }
    public void setFtpClient(FTPClient ftpClient) {
        this.ftpClient = ftpClient;
    }

    public static void main(String[] args) throws IOException {
        initLogRecord.initLog();
        Ftp ftp=new Ftp("192.168.1.12",21,"ftpadmin","1234");
        ftp.ftpLogin();
        //上传文件夹
        ftp.uploadFile(new File("D:\\myBatisLoginDemo-main\\src\\main\\resources\\upload.jsp"), "/home/data/");
        //下载文件夹
        ftp.downLoadDirectory("d://tmp//", "/home/data");
        ftp.ftpLogOut();
    }
}

拓展部分

FTP 数字代码的意义
110 重新启动标记应答。
120 服务在多久时间内ready。
125 数据链路埠开启,准备传送。
150 文件状态正常,开启数据连接端口。
200 命令执行成功。
202 命令执行失败。
211 系统状态或是系统求助响应。
212 目录的状态。
213 文件的状态。
214 求助的讯息。
215 名称系统类型。
220 新的联机服务ready。
221 服务的控制连接埠关闭,可以注销。
225 数据连结开启,但无传输动作。
226 关闭数据连接端口,请求的文件操作成功。
227 进入passive mode。
230 使用者登入。
250 请求的文件操作完成。
257 显示目前的路径名称。
331 用户名称正确,需要密码。
332 登入时需要账号信息。
350 请求的操作需要进一部的命令。
421 无法提供服务,关闭控制连结。
425 无法开启数据链路。
426 关闭联机,终止传输。
450 请求的操作未执行。
451 命令终止:有本地的错误。
452 未执行命令:磁盘空间不足。
500 格式错误,无法识别命令。
501 参数语法错误。
502 命令执行失败。
503 命令顺序错误。
504 命令所接的参数不正确。
530 未登入。
532 储存文件需要账户登入。
550 未执行请求的操作。
551 请求的命令终止,类型未知。
552 请求的文件终止,储存位溢出。
553 未执行请求的的命令,名称不正确。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/679859.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【小技巧】vscode 在 JS 文件中补全 HTML标签

文章目录 vscode中有很多插件可以支持 HTML 标签自动补全&#xff0c;在.vue和.html文件中都没有问题&#xff0c;但是在使用react时&#xff0c;HTML标签是写在js或者是ts文件中&#xff0c;插件就不起作用了 解决方案&#xff1a; 在设置中插入这段设置代码 "emmet.i…

uniapp 微信小程序sourcemap映射

uniapp 微信小程序sourcemap映射 错误捕获 由于微信小程序中没有window对象&#xff0c;不能通过window.onerror和window.onunhandledRejection方法进行全局的监听。不过我们也可以使用以下几种方法。 使用try…catch 将可能出现的错误的代码使用try...catch包裹 try{cont…

【C++】一文读懂C++中的异常处理机制

文章目录 C 中的异常处理机制1.1 什么是异常&#xff1f;1.2 调用abort()1.3 返回错误码1.4 异常机制1.5 将对象用作异常类型1.6 异常规范和C111.7 栈解退1.7.1 return和throw的区别1.7.2 什么是栈解退 1.8 其他异常特性1.9 excepyion类1.9.1 stdexcept异常类1.9.2 bad_alloc异…

329款超有设计感的英文字体合集

一组超有设计感的英文字体合集&#xff0c;总共329个字库包含多种字体风格&#xff1a;手写字体、签名字体、复古字体、笔刷字体、漫画字体等无衬线字体。适用于签名、文具、标志、排版引言、杂志或书籍封面。素材获取&#xff1a;取括号内容&#xff0c;&#xff08;scwan&…

【 openGauss数据库】--运维指南01

【 openGauss数据库】--运维指南01 &#x1f53b; 一、 openGauss数据库运维指南&#x1f530; 1.1 启停openGauss&#x1f530; 1.2 查看openGauss数据库状态 &#x1f53b; 二、 维护检查项&#x1f530; 2.1 检查实例状态&#x1f530; 2.2 检查锁信息&#x1f530; 2.3 统计…

个人向非企业,基于目前主流图床的选购指南

1. 为什么需要搭建自己的图床 最近研究了一下国内外比较主流的图床与对象存储&#xff0c;因为个人写作更加偏向于使用Markdown&#xff0c;而国内很多平台如掘金&#xff0c;简书&#xff0c;csdn等等网站都做了相关的防盗链&#xff0c;即使是我为作者本人&#xff0c;想取用…

C语言里面那些你必须知道的常用关键字(详细讲解)

前言 哈喽&#xff0c;各位铁汁们好啊&#xff01;✨今天来给大家带来的是C语言中我们常用的关键字静态static的详细讲解和typedef 、#define定义常量和宏。   既然是详解想必大家必定是想学一些平常学不到的东西吧&#xff01;这里博主给大家详细讲解static修饰的变量在内存…

2023最全的Java架构师面试120题解析(MySQL/Redis/架构/高并发等)

最全架构师题目将包含如下技术范围&#xff1a; 1.Java基础和高级: 集合框架: List&#xff1a;ArrayList、LinkedList&#xff1b;Set&#xff1a;HashSet、TreeSet Map:TreeMap/ConcurrentHashMap&#xff1b;Queue:ConcurrentLinkedQueue等 泛型、反射、并发编程、JVM、A…

基于Smb协议实现网络文件传输(Golang)

在前面章节已经展示了一些关于SMB的基本介绍&#xff0c;以及对应SMB相关操作的Java实现&#xff0c;这一章主要是前一章的补充&#xff0c;使用Golang来对 SMB共享文件夹进行操作。如果没有阅读过上一章节的同学&#xff0c;请跳转到 基于Smb协议实现网络文件传输&#xff0c;…

Axure教程—折叠面手风琴效果

上文中介绍了用Axure制作折叠面板的基础制作&#xff0c;这次介绍折叠面板手机风琴效果 效果 预览地址&#xff1a;https://e18rf6.axshare.com 功能 点击标题展开内容&#xff0c;点击另一标题&#xff0c;其展开的内容折叠 制作 拖入四个动态面板&#xff0c;分别命名为1、…

PHP流程控制与文件包含:基础与关键要点

目录 PHP流程控制 顺序结构&#xff1a; 分支结构&#xff1a; Switch分支&#xff1a; PHP循环结构 for循环 while循环 do-while循环 while和do-while的区别&#xff1a; 循环控制 流程控制代替语法 PHP文件包含 PHP文件包含的作用 PHP文件包含的四种形式 PHP文…

【spring cloud学习】3、Eureka Server注册中心

Eureka本身是Netflix开源的一款注册中心产品&#xff0c;并且Spring Cloud提供了相应的集成封装。选择Eureka作为注册中心实例来讲解是出于以下原因&#xff1a; &#xff08;1&#xff09;Eureka在业界的应用十分广泛&#xff0c;整个框架经受住了Netflix严酷生产环境的考验。…

Qt中的信号和信号槽(一)

目录 1. 信号和槽概述 信号和槽的关系 2. 标准信号槽使用 标准信号/槽 示例&#xff1a; 3. 自定义信号槽使用 自定义信号 自定义槽 示例&#xff1a; 1. 信号和槽概述 信号和槽是一种事件驱动的通信机制&#xff0c;广泛应用于Qt框架的事件处理、GUI编程、网络通信等…

如何在教育与科研领域使用ChatGPT

ChatGPT提示是您给予ChatGPT的一系列指示&#xff0c;以便它能够按需生成结果。由于ChatGPT是一种会话型人工智能&#xff0c;因此它需要明确的指示才能生成准确的结果。 ChatGPT提示的结构通常是以指令格式呈现的。它看起来像是您在与AI交流&#xff0c;给予它执行特定任务的…

基于树莓派4B的OpenCV安装与简单应用(真速通版)

前言&#xff1a;本文为手把手教学树莓派4B的OpenCV安装与简单应用&#xff08;真速通版本&#xff09;&#xff0c;树莓派4B最为目前最新款的树莓派家族一员深受创客和开发者喜爱。树莓派4B作为一款搭载 Cortex-A72 系列芯片的板载电脑&#xff0c;其不仅可以作为简单的 MCU 进…

第三方库介绍——Protobuf库(更高效的协议)

文章目录 protobuf综述传输协议与指令创建协议编译协议介绍addressbook.pb.h文件序列化与反序列化的接口 利用soctet实现客户端与服务端传输协议Linux&#xff08;Ubuntu&#xff09;安装protoc步骤编写案例代码Cartoon.prototcpsocket.hMyTcpsocket.hclient.cppserver.cppCMak…

01.4进程原理和系统调用--->经典的CFS调度器

进程的一些正常状态 什么是进程 操作系统作为硬件的使用层&#xff0c;提供使用硬件资源的能力&#xff0c;进程作为操作系统使用层&#xff0c; 提供使用操作系统抽象出的资源层的能力。 进程&#xff1a;是指计算机中已运行的程序。进程本身不是基本的运行单位&#xff0c;…

【微服务】springboot 通用限流方案设计与实现

目录 一、背景 二、限流概述 2.1 dubbo 服务治理模式 2.1.1 dubbo框架级限流 2.1.2 线程池设置 2.1.3 集成第三方组件 2.2 springcloud 服务治理模式 2.2.1 hystrix 2.2.2 sentinel 2.3 网关层限流 三、常用限流策略 3.1 限流常用的算法 3.1.1 令牌桶算法 3.1.2 …

2023最新Java面试八股文汇总(五十万字总结版)

写在前面 今年的疫情&#xff0c;让招聘面试变得雪上加霜。已经有不少大厂&#xff0c;如腾讯、字节跳动的招聘名额明显减少&#xff0c;面试门槛却一再拔高&#xff0c;如果不用心准备&#xff0c;很可能就被面试官怼得哑口无言&#xff0c;甚至失去了难得的机会。 现如今&a…

<Linux开发>驱动开发 -之- Linux RTC 驱动

&#xff1c;Linux开发&#xff1e;驱动开发 -之- Linux RTC 驱动 交叉编译环境搭建&#xff1a; &#xff1c;Linux开发&#xff1e; linux开发工具-之-交叉编译环境搭建 uboot移植可参考以下&#xff1a; &#xff1c;Linux开发&#xff1e; -之-系统移植 uboot移植过程详细…