兰生幽谷,不为莫服而不芳;

君子行义,不为莫知而止休。

生产场景:在AI接口引入的情况下,完成Linux下各种服务任务的架设。

顶层设计:让AI将Linux常用的任务封装成函数,将这些函数导入函数库,然后用shell脚本来调用这些库文件,完成特定的服务。由于Linux系统非常复杂,我将库函数大致分为系统管理、文件管理、网络管理、安全管理、通用库等。vscode登录远程Linux服务器,到自己要完成的目录下。

下面是系统架构示例:

目录结构

shell_deploy/

├── config

│   └── config.ini

├── deploy_example.sh

├── deployTask

│   └── deploy_ftp_dnf.sh

├── deploy_with_config.sh

├── lib

│   ├── common_functions.sh

│   ├── config_parser.sh

│   ├── file_operations.sh

│   ├── network_utils.sh

│   └── package_manager.sh

├── logs

└── modules

    ├── mount_shared_folder.sh

    ├── setup_ftp_source.sh

    ├── setup_http_source.sh

    └── system_init.sh

1.直接将这个结构丢给AI接口,让AI生成init_project.sh,并运行生成系统目录结构:

#!/bin/bash

# ================================================================

# Script Name:   init_project.sh

# Description:   init_project.sh 功能描述:按用户要求生成目录结构

#                                        

#                

# Author:        root

# Created:       2026-05-16

# Last Modified: 2026-05-16

# Version:       v1.0

# License:       wzz@CQIE

# Syntax:        用法

# ================================================================

# 定义项目根目录名称

PROJECT_NAME="auto_ops_project"

# 定义需要创建的目录列表(使用 Bash 数组)

# 利用 mkdir -p 的特性,即使父目录不存在也能一并创建

DIRS=(

    "${PROJECT_NAME}/config"

    "${PROJECT_NAME}/deployTask"

    "${PROJECT_NAME}/lib"

    "${PROJECT_NAME}/logs"

    "${PROJECT_NAME}/modules"

)

# 定义需要创建的空文件列表

FILES=(

    "${PROJECT_NAME}/config/config.ini"

    "${PROJECT_NAME}/deploy_example.sh"

    "${PROJECT_NAME}/deployTask/deploy_ftp_dnf.sh"

    "${PROJECT_NAME}/deploy_with_config.sh"

    "${PROJECT_NAME}/lib/common_functions.sh"

    "${PROJECT_NAME}/lib/config_parser.sh"

    "${PROJECT_NAME}/lib/file_operations.sh"

    "${PROJECT_NAME}/lib/network_utils.sh"

    "${PROJECT_NAME}/lib/package_manager.sh"

    "${PROJECT_NAME}/modules/mount_shared_folder.sh"

    "${PROJECT_NAME}/modules/setup_ftp_source.sh"

    "${PROJECT_NAME}/modules/setup_http_source.sh"

    "${PROJECT_NAME}/modules/system_init.sh"

)

# 【函数封装】打印带颜色的日志信息

log_info() {

    echo -e "\033[32m[INFO]\033[0m $1"

}

log_error() {

    echo -e "\033[31m[ERROR]\033[0m $1"

}

# 【主逻辑函数】执行目录和文件的创建

create_structure() {

    log_info "开始创建项目目录结构..."

   

    # 1. 循环创建所有目录

    for dir in "${DIRS[@]}"; do

        # -p 参数确保如果目录已存在不会报错,且能递归创建多级目录

        if ! mkdir -p "$dir"; then

            log_error "创建目录失败: $dir"

            exit 1

        fi

    done

    log_info "目录结构创建完成。"

    log_info "开始创建项目基础文件..."

   

    # 2. 循环创建所有空文件

    for file in "${FILES[@]}"; do

        # 使用 touch 命令创建空文件,如果文件已存在则只更新访问时间

        if ! touch "$file"; then

            log_error "创建文件失败: $file"

            exit 1

        fi

    done

    log_info "基础文件创建完成。"

   

    log_info "✅ 项目 '$PROJECT_NAME' 初始化成功!"

}

# 执行主函数

create_structure

赋权运行,验证:

11:29:23 [root@fire vscodeshell]# sh init_project.sh

[INFO] 开始创建项目目录结构...

[INFO] 目录结构创建完成。

[INFO] 开始创建项目基础文件...

[INFO] 基础文件创建完成。

[INFO] ✅ 项目 'auto_ops_project' 初始化成功!

验证一下:

11:29:36 [root@fire vscodeshell]# tree

.

├── auto_ops_project

│   ├── config

│   │   └── config.ini

│   ├── deploy_example.sh

│   ├── deployTask

│   │   └── deploy_ftp_dnf.sh

│   ├── deploy_with_config.sh

│   ├── lib

│   │   ├── common_functions.sh

│   │   ├── config_parser.sh

│   │   ├── file_operations.sh

│   │   ├── network_utils.sh

│   │   └── package_manager.sh

│   ├── logs

│   └── modules

│       ├── mount_shared_folder.sh

│       ├── setup_ftp_source.sh

│       ├── setup_http_source.sh

│       └── system_init.sh

└── init_project.sh

确实生成了文件结构,不过这些文件都是空的。还需要你慢慢完成。

不过,右边不是有AI接口吗?好好描述,叫它去完成。然后照单收货就行了。下面是我点验的各种脚本(均由AI生成):

#!/bin/bash

# 公共函数库lib/common_functions.sh

LOG_DIR="../logs"

LOG_FILE="$LOG_DIR/deploy_$(date +%Y%m%d).log"

# 初始化日志目录

init_log() {

    mkdir -p "$LOG_DIR"

}

# 写日志

log() {

    local level=$1

    shift

    local msg="$@"

    echo "[$(date '+%Y-%m-%d %H:%M:%S')] [$level] $msg" | tee -a "$LOG_FILE"

}

info()  { log "INFO" "$@"; }

warn()  { log "WARN" "$@"; }

error() { log "ERROR" "$@"; exit 1; }

# 颜色输出

red()    { echo -e "\033[31m$@\033[0m"; }

green()  { echo -e "\033[32m$@\033[0m"; }

yellow() { echo -e "\033[33m$@\033[0m"; }

# 检查是否为 root 用户

check_root() {

    if [[ $EUID -ne 0 ]]; then

        red "请使用 root 权限执行本脚本"

        exit 1

    fi

}

#!/bin/bash

# 配置文件解析器lib/config_parser.sh

# 用法: get_config <section> <key> <config_file>

get_config() {

    local section=$1

    local key=$2

    local file=$3

    awk -F '=' -v sec="[$section]" -v k="$key" '

        $0 ~ /^$/ { in_sec = ($0 == sec) }

        in_sec && $1 ~ /^[[:space:]]*'"$key"'[[:space:]]*$/ {

            gsub(/^[[:space:]]+|[[:space:]]+$/, "", $2)

            print $2

            exit

        }

    ' "$file"

}

#!/bin/bash

# 文件操作函数库lib/file_operations.sh

# 安全创建目录

create_dir() {

    local dir=$1

    if [[ ! -d "$dir" ]]; then

        mkdir -p "$dir"

        info "创建目录: $dir"

    else

        info "目录已存在: $dir"

    fi

}

# 备份文件(若存在)

backup_file() {

    local src=$1

    if [[ -f "$src" ]]; then

        cp "$src" "${src}.bak.$(date +%Y%m%d%H%M%S)"

        info "已备份: $src"

    fi

}

# 设置目录所有者及权限

set_owner_perm() {

    local path=$1

    local owner=$2

    local perm=$3

    chown -R "$owner" "$path"

    chmod "$perm" "$path"

    info "设置 $path 所有者=$owner 权限=$perm"

}

#!/bin/bash

# 网络工具函数库lib/network_utils.sh

# 获取本机第一个非 lo 的 IPv4 地址

get_local_ip() {

    ip -4 addr show | grep -v '127.0.0.1' | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | head -1

}

# 测试 TCP 端口连通性

test_port() {

    local host=$1

    local port=$2

    timeout 2 bash -c "echo >/dev/tcp/$host/$port" 2>/dev/null && return 0 || return 1

}

# 软件包管理函数库lib/package_manager.sh

# 检查包是否已安装

is_installed() {

    rpm -q "$1" &>/dev/null

}

# 安装指定软件包

install_pkg() {

    local pkg=$1

    if is_installed "$pkg"; then

        info "$pkg 已安装,跳过"

    else

        info "正在安装 $pkg ..."

        dnf install -y "$pkg" || error "安装 $pkg 失败"

    fi

}

#!/bin/bash

# 系统初始化模块modules/system_init.sh

system_init() {

    info "开始系统初始化..."

    # 关闭 SELinux(临时 + 永久)

    setenforce 0

    sed -i 's/^SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config

    info "SELinux 已关闭"

    # 配置防火墙,开放 ftp 服务

    firewall-cmd --add-service=ftp --permanent

    firewall-cmd --reload

    info "防火墙已开放 FTP 服务"

    # 设置本地时间(避免 FTP 时间差)

    sed -i 's/^#use_localtime=YES/use_localtime=YES/' /etc/vsftpd/vsftpd.conf 2>/dev/null || true

}

创建ftp网站所需配置config/config.ini

[ftp]

public_dir=/srv/ftp/public

dept_dirs_base=/srv/ftp/depts

virtual_user_file=/etc/vsftpd/vusers.txt

pam_service=vsftpd.virtual

guest_username=ftpvirtual

[departments]

行政部 admin_dept

设计部 design_dept

开发部 dev_dept

[public_account]

username=pubuser

readonly=yes

完成了上面库函数建设之后,可以给右边的AI提非分要求:

图403- 1

下面我们看看git给出的结果:

#!/bin/bash

# PXE 自动部署 openEuler 24.03 最小化系统脚本

# 适用网段:192.168.100.0/24

# 依赖项目函数库:common_functions.sh config_parser.sh file_operations.sh network_utils.sh package_manager.sh

set -euo pipefail

SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)

PROJECT_DIR=$(dirname "$SCRIPT_DIR")

source "$PROJECT_DIR/lib/common_functions.sh"

source "$PROJECT_DIR/lib/config_parser.sh"

source "$PROJECT_DIR/lib/file_operations.sh"

source "$PROJECT_DIR/lib/network_utils.sh"

source "$PROJECT_DIR/lib/package_manager.sh"

# 默认参数,可通过环境变量覆盖

ISO_PATH=${ISO_PATH:-/root/openEuler-24.03-x86_64-dvd.iso}

SERVER_IP=${SERVER_IP:-$(get_local_ip)}

TFTP_ROOT=${TFTP_ROOT:-/var/lib/tftpboot}

HTTP_ROOT=${HTTP_ROOT:-/var/www/html/openeuler}

ISO_MOUNT=${ISO_MOUNT:-/mnt/openeuler_iso}

DHCP_CONF=${DHCP_CONF:-/etc/dhcp/dhcpd.conf}

KS_FILE=${KS_FILE:-$HTTP_ROOT/ks.cfg}

PXE_CFG=${PXE_CFG:-$TFTP_ROOT/pxelinux.cfg/default}

DHCP_RANGE_START=${DHCP_RANGE_START:-192.168.100.100}

DHCP_RANGE_END=${DHCP_RANGE_END:-192.168.100.200}

GATEWAY=${GATEWAY:-192.168.100.1}

DNS_SERVERS=${DNS_SERVERS:-114.114.114.114,8.8.8.8}

HTTP_PACKAGE=${HTTP_PACKAGE:-httpd}

usage() {

    cat <<EOF

Usage: $0 [ISO_PATH]

示例:

  ISO_PATH=/root/openEuler-24.03-x86_64-dvd.iso $0

环境变量可覆盖默认值:

  SERVER_IP        PXE 服务器 IP

  TFTP_ROOT        TFTP 根目录

  HTTP_ROOT        HTTP 根目录

  ISO_MOUNT        ISO 挂载目录

  DHCP_RANGE_START DHCP 起始地址

  DHCP_RANGE_END   DHCP 结束地址

  GATEWAY          网关

  DNS_SERVERS      DNS 地址

EOF

    exit 1

}

if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then

    usage

fi

if [[ $# -ge 1 ]]; then

    ISO_PATH=$1

fi

init_log

check_root

if [[ ! -f "$ISO_PATH" ]]; then

    error "找不到 ISO 镜像:$ISO_PATH"

fi

if [[ -z "$SERVER_IP" ]]; then

    error "无法自动获取本机 IP,请通过 SERVER_IP 环境变量指定"

fi

info "PXE 服务器 IP: $SERVER_IP"

info "使用 ISO: $ISO_PATH"

# 安装基础服务

install_pkg dhcp-server

install_pkg tftp-server

install_pkg syslinux

install_pkg "$HTTP_PACKAGE"

# 创建目录

create_dir "$TFTP_ROOT"

create_dir "$HTTP_ROOT"

create_dir "$ISO_MOUNT"

create_dir "$(dirname "$PXE_CFG")"

# 挂载 ISO,并在 HTTP 根目录创建软链接或挂载

if mount | grep -q " $ISO_MOUNT "; then

    info "ISO 已挂载在 $ISO_MOUNT"

else

    mount -o loop "$ISO_PATH" "$ISO_MOUNT"

    info "已挂载 ISO 到 $ISO_MOUNT"

fi

# 如果 HTTP_ROOT 目录为空,则直接挂载 ISO 到 HTTP_ROOT

if [[ -z "$(ls -A "$HTTP_ROOT" 2>/dev/null)" ]]; then

    umount "$HTTP_ROOT" 2>/dev/null || true

    mount -o loop "$ISO_PATH" "$HTTP_ROOT"

    info "已挂载 ISO 到 HTTP 根目录 $HTTP_ROOT"

fi

# 复制 PXE 引导文件

PXELINUX_BIN=$(find /usr/share -name pxelinux.0 | head -n 1 || true)

MENU_C32_BIN=$(find /usr/share -name menu.c32 | head -n 1 || true)

if [[ -z "$PXELINUX_BIN" ]]; then

    error "未找到 pxelinux.0,请确认 syslinux 包已正确安装"

fi

cp -f "$PXELINUX_BIN" "$TFTP_ROOT/"

info "已复制 pxelinux.0 到 $TFTP_ROOT"

if [[ -n "$MENU_C32_BIN" ]]; then

    cp -f "$MENU_C32_BIN" "$TFTP_ROOT/"

    info "已复制 menu.c32 到 $TFTP_ROOT"

else

    warn "未找到 menu.c32,PXE 菜单可能不可用"

fi

# 复制内核和 initrd

if [[ ! -f "$ISO_MOUNT/images/pxeboot/vmlinuz" || ! -f "$ISO_MOUNT/images/pxeboot/initrd.img" ]]; then

    error "ISO 中未找到 images/pxeboot/vmlinuz 或 initrd.img,请检查镜像是否为 openEuler 24.03 安装镜像"

fi

cp -f "$ISO_MOUNT/images/pxeboot/vmlinuz" "$TFTP_ROOT/"

cp -f "$ISO_MOUNT/images/pxeboot/initrd.img" "$TFTP_ROOT/"

info "已复制内核和 initrd 到 $TFTP_ROOT"

# 生成 PXE 配置

cat > "$PXE_CFG" <<EOF

DEFAULT menu.c32

PROMPT 0

TIMEOUT 100

ONTIMEOUT openeuler

LABEL openeuler

  MENU LABEL ^Install openEuler 24.03 Minimal

  KERNEL vmlinuz

  APPEND initrd=initrd.img inst.repo=http://$SERVER_IP/openeuler/ inst.ks=http://$SERVER_IP/ks.cfg ip=dhcp inst.text

EOF

info "已生成 PXE 配置 $PXE_CFG"

# 生成 Kickstart 文件

cat > "$KS_FILE" <<EOF

#version=DEVEL

#install

text

url --url=http://$SERVER_IP/openeuler/

lang zh_CN.UTF-8

keyboard us

network --bootproto=dhcp --device=link --activate --onboot=on

rootpw --plaintext 1q2w3e4r

firewall --enabled --service=ssh

selinux --disabled

timezone Asia/Shanghai --isUtc

bootloader --location=mbr --boot-drive=sda

clearpart --all --initlabel

autopart --type=lvm

firstboot --disable

reboot

%packages

@core

@base

openssh-server

chrony

NetworkManager

%end

EOF

info "已生成 Kickstart 文件 $KS_FILE"

# 生成 DHCP 配置

cat > "$DHCP_CONF" <<EOF

default-lease-time 600;

max-lease-time 7200;

option domain-name-servers $DNS_SERVERS;

option routers $GATEWAY;

option broadcast-address 192.168.100.255;

option subnet-mask 255.255.255.0;

subnet 192.168.100.0 netmask 255.255.255.0 {

  range $DHCP_RANGE_START $DHCP_RANGE_END;

  option routers $GATEWAY;

  option domain-name-servers $DNS_SERVERS;

  next-server $SERVER_IP;

  filename "pxelinux.0";

}

EOF

info "已生成 DHCP 配置 $DHCP_CONF"

# 配置服务

if systemctl list-unit-files | grep -q '^dhcpd\.service'; then

    systemctl enable --now dhcpd.service

else

    systemctl enable --now dhcpd

fi

if systemctl list-unit-files | grep -q '^tftp\.socket'; then

    systemctl enable --now tftp.socket

else

    systemctl enable --now tftp

fi

systemctl enable --now "$HTTP_PACKAGE".service || systemctl enable --now httpd

# 防火墙

if command -v firewall-cmd >/dev/null 2>&1; then

    firewall-cmd --permanent --add-service=dhcp

    firewall-cmd --permanent --add-service=tftp

    firewall-cmd --permanent --add-service=http

    firewall-cmd --reload

    info "已在防火墙中开放 DHCP/TFTP/HTTP 服务"

fi

green "PXE openEuler 24.03 最小化部署已就绪"

info "请确认以下内容:"

echo "  - PXE 服务器 IP: $SERVER_IP"

echo "  - HTTP 安装源: http://$SERVER_IP/openeuler/"

echo "  - Kickstart 地址: http://$SERVER_IP/ks.cfg"

echo "  - DHCP 范围: $DHCP_RANGE_START ~ $DHCP_RANGE_END"

echo "  - PXE 配置文件: $PXE_CFG"

echo

info "请确保客户端从网段 192.168.100.0/24 的网卡通过 PXE 启动,即可自动安装最小化 openEuler 24.03。"

也可以在这个基础上,叫AI完成下面的任务:

完成基本功能函数封装,然后部署一个ftp网站部署验证一下。某企业为了实现文件资源的共享,需要建设FTP文件服务。

基本需求:         

行政部、设计部、开发部有独立账号         

独立账号访问,默认目录为部门目录         

所有账号能够仅能够访问本部门目录,且具有读写权限         

提供公共账号,仅允许读取公共目录的资源         

禁止匿名账号访问

下面是AI创建的脚本:

FTP 自动化部署脚本 deployTask/deploy_ftp_dnf.sh

该脚本调用上述函数库,完成 vsftpd 安装、虚拟用户创建、目录隔离、权限设置等全部工作。

#!/bin/bash

# FTP 服务器自动化部署(虚拟用户模式)

# 适用系统:openEuler 24.03

set -e

# 引入函数库

SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)

PROJECT_DIR=$(dirname "$SCRIPT_DIR")

source "$PROJECT_DIR/lib/common_functions.sh"

source "$PROJECT_DIR/lib/config_parser.sh"

source "$PROJECT_DIR/lib/file_operations.sh"

source "$PROJECT_DIR/lib/network_utils.sh"

source "$PROJECT_DIR/lib/package_manager.sh"

source "$PROJECT_DIR/modules/system_init.sh"

# 初始化日志

init_log

check_root

# 加载配置

CONFIG_FILE="$PROJECT_DIR/config/config.ini"

PUBLIC_DIR=$(get_config ftp public_dir "$CONFIG_FILE")

DEPT_BASE=$(get_config ftp dept_dirs_base "$CONFIG_FILE")

VUSER_FILE=$(get_config ftp virtual_user_file "$CONFIG_FILE")

PAM_SERVICE=$(get_config ftp pam_service "$CONFIG_FILE")

GUEST_USER=$(get_config ftp guest_username "$CONFIG_FILE")

PUB_USER=$(get_config public_account username "$CONFIG_FILE")

# 解析部门列表(格式:部门名 账号名)

declare -A DEPT_MAP

while read -r dept_name dept_user; do

    DEPT_MAP["$dept_name"]="$dept_user"

done < <(awk -F '=' '/^\[departments$/{flag=1; next} /^\[/{flag=0} flag && NF{print $2}' "$CONFIG_FILE" | while read line; do echo $line; done)

info "========== 开始部署 FTP 服务 =========="

# 1. 系统初始化

system_init

# 2. 安装必要软件包

install_pkg vsftpd

install_pkg db4-utils        # 用于生成虚拟用户数据库

install_pkg ftp              # 客户端测试工具

# 3. 创建虚拟用户映射的系统用户

if ! id "$GUEST_USER" &>/dev/null; then

    useradd -d /nonexistent -s /sbin/nologin "$GUEST_USER"

    info "创建映射系统用户: $GUEST_USER"

fi

# 4. 创建目录结构

create_dir "$PUBLIC_DIR"

create_dir "$DEPT_BASE"

for dept in "${!DEPT_MAP[@]}"; do

    create_dir "$DEPT_BASE/$dept"

done

# 5. 设置目录权限

# 公共目录:root 所有,755,允许所有人读取

set_owner_perm "$PUBLIC_DIR" root:root 755

# 部门目录:由对应的虚拟用户拥有(通过 guest_username 映射,实际所有者设为 root,权限 700 或 750,但 vsftpd 以 guest 身份运行,需保证 guest 有读写权限)

# 这里将部门目录所有者设为 root:root,权限 770,并将 guest 用户加入 root 组(或直接设为 guest 所有)

# 简单方案:将部门目录所有者设为 $GUEST_USER,权限 700,这样只有 guest 能读写,而不同虚拟用户通过 chroot 隔离

for dept in "${!DEPT_MAP[@]}"; do

    set_owner_perm "$DEPT_BASE/$dept" "$GUEST_USER:$GUEST_USER" 700

done

# 6. 生成虚拟用户密码文件(明文)

info "生成虚拟用户列表..."

> "$VUSER_FILE"

# 部门用户

for dept in "${!DEPT_MAP[@]}"; do

    user="${DEPT_MAP[$dept]}"

    # 生成随机密码(12位)

    pass=$(openssl rand -base64 12)

    echo "$user" >> "$VUSER_FILE"

    echo "$pass" >> "$VUSER_FILE"

    info "虚拟用户 $user (部门:$dept) 密码: $pass"

done

# 公共只读用户

pub_pass=$(openssl rand -base64 12)

echo "$PUB_USER" >> "$VUSER_FILE"

echo "$pub_pass" >> "$VUSER_FILE"

info "公共用户 $PUB_USER 密码: $pub_pass"

# 生成 Berkeley DB 文件

db_load -T -t hash -f "$VUSER_FILE" /etc/vsftpd/vusers.db

chmod 600 /etc/vsftpd/vusers.db

info "虚拟用户数据库已生成"

# 7. 配置 PAM 认证

info "配置 PAM 认证..."

cat > /etc/pam.d/$PAM_SERVICE <<EOF

auth required pam_userdb.so db=/etc/vsftpd/vusers

account required pam_userdb.so db=/etc/vsftpd/vusers

EOF

# 8. 配置 vsftpd.conf

info "配置 vsftpd..."

backup_file /etc/vsftpd/vsftpd.conf

cat > /etc/vsftpd/vsftpd.conf <<EOF

# 基础设置

listen=YES

listen_ipv6=NO

anonymous_enable=NO

local_enable=YES

write_enable=YES

local_umask=022

dirmessage_enable=YES

xferlog_enable=YES

connect_from_port_20=YES

xferlog_std_format=YES

chroot_local_user=YES

allow_writeable_chroot=YES

hide_ids=YES

userlist_enable=YES

userlist_deny=NO

userlist_file=/etc/vsftpd/user_list

# 虚拟用户设置

guest_enable=YES

guest_username=$GUEST_USER

virtual_use_local_privs=YES

user_config_dir=/etc/vsftpd/vusers_config

pam_service_name=$PAM_SERVICE

# 被动模式端口范围

pasv_enable=YES

pasv_min_port=50000

pasv_max_port=51000

pasv_address=$(get_local_ip)

EOF

# 9. 创建虚拟用户独立配置目录

create_dir /etc/vsftpd/vusers_config

# 部门用户配置:限制在家目录,允许读写

for dept in "${!DEPT_MAP[@]}"; do

    user="${DEPT_MAP[$dept]}"

    cat > "/etc/vsftpd/vusers_config/$user" <<EOF

local_root=$DEPT_BASE/$dept

write_enable=YES

anon_upload_enable=YES

anon_mkdir_write_enable=YES

anon_other_write_enable=YES

EOF

done

# 公共用户配置:只读,锁定在公共目录

cat > "/etc/vsftpd/vusers_config/$PUB_USER" <<EOF

local_root=$PUBLIC_DIR

write_enable=NO

anon_upload_enable=NO

anon_mkdir_write_enable=NO

anon_other_write_enable=NO

download_enable=YES

EOF

# 10. 创建 user_list 白名单(允许登录的虚拟用户)

> /etc/vsftpd/user_list

for dept in "${!DEPT_MAP[@]}"; do

    echo "${DEPT_MAP[$dept]}" >> /etc/vsftpd/user_list

done

echo "$PUB_USER" >> /etc/vsftpd/user_list

# 11. 启动服务并设置开机自启

systemctl enable vsftpd --now

systemctl restart vsftpd

info "vsftpd 服务已启动"

# 12. 验证测试

LOCAL_IP=$(get_local_ip)

info "FTP 服务器地址: ftp://$LOCAL_IP"

info "========== 部署完成 =========="

green "请使用以下账号测试:"

for dept in "${!DEPT_MAP[@]}"; do

    echo "  部门: $dept  账号: ${DEPT_MAP[$dept]}"

done

echo "  公共只读账号: $PUB_USER"

稍稍修改一下,完全可以部署成功。

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐