Linux installation vsftpd and configuration

Install vsftpd

1. yum installation

Check if installed

rpm -qa | grep vsftpd

Uninstall vsftpd

yum remove vsftpd

yum installation

# Installation
yum install vsftpd

2. Start

# enable
service vsftpd start
# closure
service vsftpd stop
# Restart
service vsftpd restart

# boot
chkconfig vsftpd on

3. Create user

# Create user useradd -d directory username
useradd -d /usr/noobmantest noobmantest

# Set user password
passwd noobmantest

Modify user information

# Change user home directory usermod -d directory username
usermod -d /user/newFold noobmantest

# Limit the user ftpuser not to telnet, but only to ftp
usermod -s /sbin/nologin ftpuser
 
#Of course, if you want to return to a normal user, you can execute the following command:
usermod -s /sbin/bash ftpuser

4. Modify the configuration file

Modify /etc/vsftpd/vsftpd.conf as follows:
 
anonymous_enable=NO //Anonymous users are not allowed to access, the default is allowed.
 
chroot_local_user=NO
 
chroot_list_enable=YES
//Open this comment
chroot_list_file=/etc/vsftpd/chroot_list
 
//Add restricted directory address (optional)
local_root = /opt/FTP

Create a user directory that prohibits adjustments

touch chroot_list
Configuration instructions
anonymous_enable=YES #Set whether to allow anonymous users to log in
local_enable=YES #Set whether to allow local users to log in
local_root=/home #Set the root directory of the local user
write_enable=YES #Whether the user is allowed to have write permissions
local_umask=022 #Set the umask value when local users create files
anon_upload_enable=YES #Set whether to allow anonymous users to upload files
anon_other_write_enable=YES #Set whether anonymous users have modification permissions
anon_world_readable_only=YES #When it is YES, other people in the file must have read permissions to allow anonymous users to download. If the owner is ftp and has read permissions, they cannot download. Others must also have read permissions to allow downloading.
download_enbale=YES #Whether downloading is allowed
chown_upload=YES #Set the anonymous user to modify the owner of the file after uploading it
chown_username=ftpuser #Used in conjunction with the above options, it means that the modified owner is ftpuser
ascii_upload_enable=YES #Set whether to allow uploading files in ASCII mode
ascii_download_enable=YES #Set whether to allow downloading files in ASCII mode

Python accesses the ftp server and copies files to the local computer

# -*- coding: UTF8 -*-

import time
from ftplib import FTP
import os

# Where to save logs
log_path = r'D:/file'
log_file = 'log.txt'
#Local save directory
remote_path = 'c'
local_path = ''
"""For FTP connections"""
ftp_server = '' # IP address corresponding to the ftp site
username = '' # Username
password = '' # Password


if not os.path.exists(log_path):
    os.makedirs(log_path)

# connect
def ftp_connect():
    ftp = FTP()
    ftp.set_debuglevel(0) # A higher level is easier to troubleshoot problems
    ftp.connect(ftp_server, 21)
    ftp.login(username, password)
    # ftp.encoding = 'utf-8'
    return ftp

# download file
def download_file(ftp, local_path, local_file, remote_path, remote_file):
    if not os.path.exists(local_path):
        os.makedirs(local_path)
    fp = open(local_path + "/" + local_file, 'wb')
    ftp.cwd(remote_path)
    ftp.set_debuglevel(0) # A higher level is easier to troubleshoot problems
    # ftp.retrbinary('RETR ' + remote_file, fp.write, 1024)
    # ftp.retrbinary("RETR filename.txt",file_handel,bufsize) #Download FTP files
    ftp.retrbinary('RETR {<!-- -->0}'.format(remote_file), fp.write, 1024)


# Determine whether it already exists locally
def is_local_exist(ftp, remote_path, local_path, file_name):
    # Determine whether it exists
    if not os.path.exists(local_path):
        os.makedirs(local_path)
    files = os.listdir(local_path)
    if file_name in files:
        cur_path = local_path + "/" + file_name
        if os.path.isdir(cur_path):
            # print(cur_path + " it's a directory")
            return False
        elif os.path.isfile(cur_path):
            # print(cur_path + " it's a normal file")
            # If the file size is the same, it is considered to be the same file, otherwise it is not
            if os.stat(cur_path).st_size == ftp.size(remote_path + "/" + file_name):
                return True
            else:
                return False
        else:
            log("Error access")
            return False
    else:
        return False

# Recursive download
def download_dir(ftp, remote_path, local_path):
    ftp.cwd(remote_path)
    nlst_test = ftp.nlst()

    dirs = []
    ftp.dir(".", dirs.append)

    transcodeUTF8(dirs=nlst_test)
    transcodeUTF8(dirs=dirs)

    for i in range(len(dirs)):
        try:
            # Distinguish between files and folders
            if("drwxr-xr-x" in dirs[i]):
                log("Scan directory: " + remote_path + "/" + nlst_test[i])
                # print("Scan directory: " + nlst_test[i])
                download_dir(ftp, remote_path=remote_path + "/" +
                            nlst_test[i], local_path=local_path + '/' + nlst_test[i])
            else:
                # Download if it does not exist locally
                if not is_local_exist(ftp=ftp, remote_path=remote_path, local_path=local_path, file_name=nlst_test[i]):
                    log("File:" + remote_path + "/" +
                        nlst_test[i] + 'download to' + local_path)
                    # print("File:" + nlst_test[i] + 'Download to' + local_path)
                    download_file(ftp=ftp, local_path=local_path,
                                local_file=nlst_test[i], remote_path=remote_path, remote_file=nlst_test[i])
        except Exception as e:
            log(str(e))
            log('File download failed, file name: ')
            log(dirs[i])
            continue

# Logging tool
def log(log_content):
    print(log_content)
    with open(log_path + "/" + log_file, 'a') as f:
        f.write(
            '\
' + time.strftime("%Y/%m/%d %H:%M:%S") + str(log_content))

# Convert latin1 to uft8 to solve the problem of reading file names
def transcodeUTF8(dirs):
    for i in range(len(dirs)):
        try:
            dirs[i] = dirs[i].encode('latin1').decode('utf-8')
        except Exception as e:
            # print(e)
            log(str(e))
            log('File name transcoding error')
            # log(dirs[i])


if __name__ == '__main__':
    log("Program starts!")
    ftp = ftp_connect()
    download_dir(ftp=ftp, remote_path=remote_path,
                 local_path=local_path)
    ftp.close