要实现 Linux 下使用 inotifywait 结合 FTP 实时下载文件,需要理解一个关键点:inotifywait 只能监控本地文件系统的变化,无法直接监控远程 FTP 服务器的变化。
因此,这里有两种实现方案:
方案一:使用 FTP 挂载 + inotifywait(推荐)
将 FTP 服务器挂载到本地文件系统,然后监控这个挂载目录。
1. 安装必要工具
# Debian/Ubuntu
sudo apt-get install curlftpfs inotify-tools lftp
# RHEL/CentOS
sudo yum install fuse curlftpfs inotify-tools lftp
2. 创建挂载点和脚本
#!/bin/bash
# ftp_monitor.sh
# 配置参数
FTP_SERVER="ftp.example.com"
FTP_USER="username"
FTP_PASS="password"
REMOTE_DIR="/remote/path"
LOCAL_DIR="/local/download/path"
MOUNT_POINT="/mnt/ftp_mount"
# 创建目录
mkdir -p "$MOUNT_POINT" "$LOCAL_DIR"
# 挂载 FTP(使用 curlftpfs)
curlftpfs "$FTP_USER:$FTP_PASS@$FTP_SERVER" "$MOUNT_POINT" -o allow_other
# 监控 FTP 挂载目录
inotifywait -m -r -e create,moved_to --format '%w%f' "$MOUNT_POINT/$REMOTE_DIR" |
while read file
do
echo "检测到新文件: $file"
# 提取文件名
filename=$(basename "$file")
# 使用 lftp 下载文件(比 cp 更稳定)
lftp -u "$FTP_USER,$FTP_PASS" "$FTP_SERVER" <<EOF
cd "$REMOTE_DIR"
get "$filename" -o "$LOCAL_DIR/$filename"
bye
EOF
echo "文件已下载: $LOCAL_DIR/$filename"
done
方案二:定期检查 + FTP 同步
如果没有挂载 FTP 的权限,可以使用定期检查的方式:
#!/bin/bash
# ftp_sync.sh
# 配置参数
FTP_SERVER="ftp.example.com"
FTP_USER="username"
FTP_PASS="password"
REMOTE_DIR="/remote/path"
LOCAL_DIR="/local/download/path"
SYNC_INTERVAL=5 # 检查间隔(秒)
# 创建本地目录
mkdir -p "$LOCAL_DIR"
# 获取初始文件列表
lftp -u "$FTP_USER,$FTP_PASS" "$FTP_SERVER" <<EOF > /tmp/ftp_files.old
cd "$REMOTE_DIR"
ls
bye
EOF
while true; do
sleep $SYNC_INTERVAL
# 获取当前文件列表
lftp -u "$FTP_USER,$FTP_PASS" "$FTP_SERVER" <<EOF > /tmp/ftp_files.new
cd "$REMOTE_DIR"
ls
bye
EOF
# 比较文件差异
new_files=$(comm -13 <(sort /tmp/ftp_files.old) <(sort /tmp/ftp_files.new) | grep -v '^\.')
if [ ! -z "$new_files" ]; then
echo "发现新文件: $new_files"
# 下载新文件
for file in $new_files; do
lftp -u "$FTP_USER,$FTP_PASS" "$FTP_SERVER" <<EOF
cd "$REMOTE_DIR"
get "$file" -o "$LOCAL_DIR/$file"
bye
EOF
echo "已下载: $file"
done
# 更新文件列表
mv /tmp/ftp_files.new /tmp/ftp_files.old
fi
done
方案三:使用 inotifywait 监控本地,自动上传到 FTP(反向)
如果你需要监控本地目录,然后自动上传到 FTP:
#!/bin/bash
# upload_to_ftp.sh
# 配置参数
LOCAL_WATCH_DIR="/local/watch/path"
FTP_SERVER="ftp.example.com"
FTP_USER="username"
FTP_PASS="password"
REMOTE_DIR="/remote/upload/path"
# 监控本地目录
inotifywait -m -r -e close_write,moved_to --format '%w%f' "$LOCAL_WATCH_DIR" |
while read file
do
echo "检测到新文件: $file"
# 提取文件名
filename=$(basename "$file")
# 上传到 FTP
lftp -u "$FTP_USER,$FTP_PASS" "$FTP_SERVER" <<EOF
cd "$REMOTE_DIR"
put "$file"
bye
EOF
echo "文件已上传: $filename"
done
安装和使用步骤
- 安装依赖:
sudo apt-get install inotify-tools lftp curlftpfs
- 创建脚本:
nano ftp_monitor.sh
# 粘贴上述脚本内容
chmod +x ftp_monitor.sh
-
配置 FTP 凭据:
编辑脚本,设置正确的 FTP 服务器信息。 -
运行脚本:
# 方案一
./ftp_monitor.sh
# 或作为服务运行
nohup ./ftp_monitor.sh > /var/log/ftp_monitor.log 2>&1 &
- 配置 systemd 服务(可选):
sudo nano /etc/systemd/system/ftp-monitor.service
[Unit]
Description=FTP Monitor Service
After=network.target
[Service]
Type=simple
User=yourusername
ExecStart=/path/to/ftp_monitor.sh
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
注意事项
-
安全性:不要在脚本中硬编码密码,可以考虑使用:
- 密码文件:
~/.netrc - 环境变量
- 配置文件
- 密码文件:
-
错误处理:添加适当的错误处理:
# 在关键操作后检查返回值
if [ $? -ne 0 ]; then
echo "错误: 下载失败"
# 重试或记录日志
fi
- 日志记录:建议添加日志记录:
log_file="/var/log/ftp_sync.log"
echo "$(date): 开始同步" >> "$log_file"
- 性能考虑:
- 对于大量文件,使用
lftp mirror命令更高效 - 调整
inotifywait的事件类型避免重复触发
- 对于大量文件,使用
选择哪种方案取决于你的具体需求。方案一最接近实时,但需要挂载 FTP;方案二更通用但有一定延迟;方案三适用于上传场景。
评论区