配置SFTP服务
useradd sftps20
useradd sftpg20
passwd sftps20
passwd sftpg20
mkdir -p /data/sftp/sftps20
mkdir -p /data/sftp/sftpg20
chmod 755 /data/sftp
chown sftps20:sftps20 /data/sftp/sftps20
chown sftpg20:sftpg20 /data/sftp/sftpg20
chmod 775 /data/sftp/sftps20
chmod 775 /data/sftp/sftpg20
cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak.250805
vi /etc/ssh/sshd_config
Subsystem sftp internal-sftp
Match User sftps20,sftpg20
ChrootDirectory /data/sftp
ForceCommand internal-sftp
AllowTcpForwarding no
X11Forwarding no
sshd -t
systemctl restart sshd
验证 SFTP 服务
sftp sftps20@localhost
put test.txt /upload/
exit
安装inotify-tools
cd /tmp/
mv inotify-tools-3.13.tar.gz /data/
cd /data/
tar -zxvf inotify-tools-3.13.tar.gz
cd inotify-tools-3.13/
./configure --prefix= /usr/local
cd /usr/local/
cd /data/inotify-tools-3.13/
make
make install
inotifywait -h
自动修改权限脚本
cd /data/zz/
vi sftpfilechmod.sh
WATCH_DIR = "/data/sftp"
LOG_FILE = "/var/log/sftp_permissions.log"
if [ ! -d "$WATCH_DIR " ] ; then
echo "错误:监控目录 $WATCH_DIR 不存在!"
exit 1
fi
if [ ! -f "$LOG_FILE " ] ; then
touch "$LOG_FILE "
chmod 644 "$LOG_FILE "
fi
echo "[$( date +'%Y-%m-%d %H:%M:%S' ) ] 启动SFTP权限监控脚本,监控目录:$WATCH_DIR " >> "$LOG_FILE "
inotifywait -m -r -e close_write,create,moved_to --format "%e %w%f" "$WATCH_DIR " | while read EVENT FILE; do
if [ -f "$FILE " ] ; then
chmod 755 "$FILE "
echo "[$( date +'%Y-%m-%d %H:%M:%S' ) ] 处理文件:$FILE ,事件:$EVENT ,设置权限为775" >> "$LOG_FILE "
elif [ -d "$FILE " ] ; then
chmod 755 "$FILE "
echo "[$( date +'%Y-%m-%d %H:%M:%S' ) ] 处理目录:$FILE ,事件:$EVENT ,设置权限为775" >> "$LOG_FILE "
fi
done
封装服务/etc/systemd/system/sftp-permissions.service
chmod 775 sftpfilechmod.sh
tee /etc/systemd/system/sftp-permissions.service << EOF
[Unit]
Description=SFTP Upload Permissions Controller
After=network.target
[Service]
Type=simple
ExecStart=/data/zz/sftpfilechmod.sh
Restart=always
User=root
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable sftp-permissions
systemctl start sftp-permissions
自动同步远端服务器脚本
vi /data/zz/zsync.sh
#!/bin/bash
MONITOR_DIR = "/data/sftp/sftpn21"
REMOTE_RSYNC_USER = "rsync"
REMOTE_IP = "10.12.8.37"
REMOTE_RSYNC_MODULE = "lotus_nexchip"
PASSWORD_FILE = "/etc/rsyncd.pass"
LOG_DIR = "/var/log/sftp_sync"
SYNC_DELETE = "false"
EXCLUDE_TMP_FILES = "true"
check_dependency ( ) {
local cmd = $1
if ! command -v $cmd &> /dev/null; then
echo "[$( date +'%Y-%m-%d %H:%M:%S' ) ] 错误:未安装依赖工具 $cmd ,请先执行:yum install -y $cmd "
exit 1
fi
}
check_dependency "inotifywait"
check_dependency "rsync"
if [ ! -d "$MONITOR_DIR " ] ; then
echo "[$( date +'%Y-%m-%d %H:%M:%S' ) ] 错误:本地监控目录 $MONITOR_DIR 不存在,请先创建!"
exit 1
fi
if [ ! -f "$PASSWORD_FILE " ] ; then
echo "[$( date +'%Y-%m-%d %H:%M:%S' ) ] 错误:rsync密码文件 $PASSWORD_FILE 不存在,请先创建!"
exit 1
fi
if [ "$( stat -c %a "$PASSWORD_FILE " ) " -ne 600 ] ; then
chmod 600 "$PASSWORD_FILE "
echo "[$( date +'%Y-%m-%d %H:%M:%S' ) ] 提示:已自动将密码文件 $PASSWORD_FILE 权限设置为600(rsync要求)"
fi
check_remote_rsync ( ) {
rsync -avz --list-only "${REMOTE_RSYNC_USER} @${REMOTE_IP} ::${REMOTE_RSYNC_MODULE} /" \
--password-file= "${PASSWORD_FILE} " &> /dev/null
if [ $? -ne 0 ] ; then
echo "[$( date +'%Y-%m-%d %H:%M:%S' ) ] 错误:远端rsync服务不可达!请检查:"
echo "1. 远端IP(${REMOTE_IP} )是否正确;2. 远端rsync模块(${REMOTE_RSYNC_MODULE} )是否存在;"
echo "3. 密码文件(${PASSWORD_FILE} )中的密码是否正确;4. 远端rsync服务是否已启动"
exit 1
fi
}
check_remote_rsync
if [ ! -d "$LOG_DIR " ] ; then
mkdir -p "$LOG_DIR "
chmod 755 "$LOG_DIR "
echo "[$( date +'%Y-%m-%d %H:%M:%S' ) ] 提示:已自动创建日志目录 $LOG_DIR "
fi
LOG_FILE = "${LOG_DIR} /sftp_sync_daemon_$( date +%Y%m%d) .log"
write_log ( ) {
local level = $1
local message = $2
echo "[$( date +'%Y-%m-%d %H:%M:%S' ) ] [${level} ] ${message} " >> "$LOG_FILE "
echo "[$( date +'%Y-%m-%d %H:%M:%S' ) ] [${level} ] ${message} "
}
sync_file_or_dir ( ) {
local event = $1
local path = $2
if [ "$SYNC_DELETE " = "false" ] && [ [ "$event " = ~ DELETE ] ] ; then
local target_type = $( if [ -d "$path " ] ; then echo "目录" ; else echo "文件" ; fi )
write_log "INFO" "检测到${target_type} 删除操作(SYNC_DELETE=false),仅记录日志:事件=${event} ,路径=${path} "
return 0
fi
if [ "$EXCLUDE_TMP_FILES " = "true" ] && [ -f "$path " ] ; then
if [ [ "$path " = ~ \ .( swp| tmp| swx| bak| ~) $ ] ] ; then
write_log "INFO" "跳过临时文件:${path} (事件:${event} )"
return 0
fi
fi
local target_type = $( if [ -d "$path " ] ; then echo "目录" ; else echo "文件" ; fi )
local relative_path = "${path# $MONITOR_DIR/ } "
local remote_target = "${REMOTE_RSYNC_USER} @${REMOTE_IP} ::${REMOTE_RSYNC_MODULE} /${relative_path} "
local rsync_args = "-avz --progress --no-group --no-owner --no-times --no-perms"
if [ "$SYNC_DELETE " = "true" ] && [ [ "$event " = ~ DELETE ] ] ; then
rsync_args = "${rsync_args} --delete"
write_log "WARN" "开启同步删除模式,将删除远端${target_type} :${remote_target} "
fi
write_log "INFO" "开始同步${target_type} :事件=${event} ,本地路径=${path} "
write_log "INFO" "执行命令:rsync ${rsync_args} '${path} ' '${remote_target} ' --password-file='${PASSWORD_FILE} '"
rsync ${rsync_args} "${path} " "${remote_target} " \
--password-file= "${PASSWORD_FILE} " &>> "$LOG_FILE "
if [ $? -eq 0 ] ; then
write_log "INFO" "${target_type} 同步成功:远端目标=${remote_target} "
else
write_log "ERROR" "${target_type} 同步失败:请查看日志文件 ${LOG_FILE} 中的详细错误信息"
fi
}
write_log "INFO" "==================== SFTP同步服务启动 ===================="
write_log "INFO" "本地监控目录:${MONITOR_DIR} "
write_log "INFO" "远端rsync模块:${REMOTE_RSYNC_USER} @${REMOTE_IP} ::${REMOTE_RSYNC_MODULE} /"
write_log "INFO" "密码文件路径:${PASSWORD_FILE} "
write_log "INFO" "日志文件路径:${LOG_FILE} "
write_log "INFO" "同步模式:同步监控到的文件(创建/修改)和目录(创建/修改)"
write_log "INFO" "同步删除模式:$( if [ "$SYNC_DELETE " = "true" ] ; then echo "开启" ; else echo "关闭(删除操作仅记录日志)" ; fi ) "
write_log "INFO" "---------------------------------------------------------"
inotifywait -mrq \
--format '%e %w%f' \
-e create,modify,moved_to,delete \
"$MONITOR_DIR " | while read -r event path; do
sync_file_or_dir "$event " "$path "
done
封装服务/usr/lib/systemd/system/sftprsync.service
vi /usr/lib/systemd/system/sftprsync.service
[ Unit]
Description = SFTP Directory Sync Service
After = network.target local-fs.target
[ Service]
Type = simple
User = root
Group = root
WorkingDirectory = /data/zz
ExecStart = /data/zz/zsync.sh
Restart = always
RestartSec = 5
KillMode = control-group
StandardOutput = journal
StandardError = journal
[ Install]
WantedBy = multi-user.target