FTPサーバで「ファイル受け取りイベントの検出」をしたくて、inotify-toolsを検証してみました。
inotify-toolsのインストール
sudo yum install inotify-tools
インストール後確認
[sooni@vm022 ~]$ sudo rpm -q inotify-tools
[sudo] sooni のパスワード:
inotify-tools-3.14-19.el8.x86_64
[sooni@vm022 ~]$ sudo yum list installed | grep inotify-tools
inotify-tools.x86_64 3.14-19.el8 @epel
[sooni@vm022 ~]$
- 新しいファイルを検出したときにS3にアップロードするスクリプトを作成します。
- スクリプトの作成
- 以下のようなシェルスクリプトを作成します。これは、FTPのアップロードディレクトリで新しいファイルが検出されたときに、そのファイルをS3にアップロードします。
#!/bin/bash
UPLOAD_DIR="/path/to/ftp/upload/dir"
S3_BUCKET="your-s3-bucket-name"
inotifywait -m -e create "$UPLOAD_DIR" |
while read path action file; do
if [[ "$file" != .* ]]; then
aws s3 cp "$UPLOAD_DIR/$file" "s3://$S3_BUCKET/$file"
echo "Uploaded $file to S3"
fi
done
スクリプトの実行
# スクリプトを実行可能にする
chmod +x /path/to/your/script.sh
# systemdサービスファイルを作成
sudo tee /etc/systemd/system/upload-to-s3.service << EOF
[Unit]
Description=Upload FTP Files to S3
[Service]
ExecStart=/path/to/your/script.sh
[Install]
WantedBy=multi-user.target
EOF
# サービスを開始して有効にする
sudo systemctl start upload-to-s3.service
sudo systemctl enable upload-to-s3.service
これにより、FTPサーバにファイルがアップロードされるたびに、そのファイルが自動的にS3にアップロードされるようになります。
注意点
- セキュリティ: S3バケットへの書き込み権限があるIAMロールやユーザーを適切に設定してください。
- エラーハンドリング: ファイルのアップロードが失敗した場合のリトライ機構などをスクリプトに追加することを検討してください。
#!/bin/bash
# ログファイルのベースパスを指定
LOGFILE_BASE="/var/log/folder_watcher"
# ソースディレクトリと対応するデスティネーションディレクトリを定義
SOURCE_BASE="/home/sooni/ftpdir"
DEST_BASE="/usr/local/share/work"
# フォルダごとの配列を定義
FOLDERS=("F01" "F02" "F03")
# トラップ設定
trap 'pkill -P $$; exit' EXIT
# デバウンス時間を指定(秒単位)
DEBOUNCE_TIME=2
# 起動時に古いデバウンスファイルとクールダウンファイルを削除
find /tmp/debounce_* /tmp/cooldown_* -type f -exec rm -f {} \;
# フォルダごとに独立して監視プロセスを開始
for FOLDER in "${FOLDERS[@]}"; do
SOURCE_DIR="$SOURCE_BASE/$FOLDER"
DEST_DIR="$DEST_BASE/$FOLDER"
LOGFILE="${LOGFILE_BASE}_${FOLDER}.log"
# ログに初期メッセージを追加
echo "$(date '+%Y-%m-%d %H:%M:%S') - folder_watcher for $FOLDER started!" >> "$LOGFILE"
# コピー先のディレクトリが存在しない場合は作成
if [ ! -d "$DEST_DIR" ]; then
mkdir -p "$DEST_DIR"
echo "$(date '+%Y-%m-%d %H:%M:%S') - Created destination directory: $DEST_DIR" >> "$LOGFILE"
fi
# フォルダの監視とファイルのコピー/削除
(
echo "$(date '+%Y-%m-%d %H:%M:%S') - Starting inotifywait for $FOLDER" >> "$LOGFILE"
inotifywait -m -r -e modify,create,delete --format '%w%f|%e' "$SOURCE_DIR" |
while IFS='|' read -r full_path event; do
#echo "$(date '+%Y-%m-%d %H:%M:%S') - Detected event: $event for file: $full_path" >> "$LOGFILE"
debounce_file="/tmp/debounce_$(echo -n "$full_path" | md5sum | awk '{print $1}')"
cooldown_file="/tmp/cooldown_$(echo -n "$full_path" | md5sum | awk '{print $1}')"
case "$event" in
DELETE)
DEST_PATH="$DEST_DIR/$(basename "$full_path")"
if [ -f "$DEST_PATH" ]; then
rm "$DEST_PATH"
echo "$(date '+%Y-%m-%d %H:%M:%S') - $event - Deleted $DEST_PATH" >> "$LOGFILE"
fi
;;
MODIFY|CREATE)
if [ ! -f "$cooldown_file" ]; then
touch "$debounce_file"
echo "$full_path" > "$debounce_file"
#echo "$(date '+%Y-%m-%d %H:%M:%S') - $event - Created debounce file: $debounce_file for $full_path" >> "$LOGFILE"
fi
;;
esac
done
) &
done
# デバウンスロジック
while true; do
sleep $DEBOUNCE_TIME
for debounce_file in /tmp/debounce_*; do
if [ -f "$debounce_file" ]; then
full_path=$(cat "$debounce_file")
cooldown_file="/tmp/cooldown_$(echo -n "$full_path" | md5sum | awk '{print $1}')"
if [ -f "$full_path" ]; then
size1=$(stat -c%s "$full_path")
sleep $DEBOUNCE_TIME
size2=$(stat -c%s "$full_path")
log_file="${LOGFILE_BASE}_$(basename "$(dirname "$full_path")").log"
echo "$(date '+%Y-%m-%d %H:%M:%S') - Checking file: $full_path, size1: $size1, size2: $size2" >> "$log_file"
if [ "$size1" -eq "$size2" ] && [ -f "$debounce_file" ] && [ ! -f "$cooldown_file" ]; then
DEST_PATH="$DEST_BASE/$(basename "$(dirname "$full_path")")/$(basename "$full_path")"
cp "$full_path" "$DEST_PATH"
echo "$(date '+%Y-%m-%d %H:%M:%S') - Copied $full_path to $DEST_PATH" >> "$log_file"
rm "$debounce_file"
touch "$cooldown_file"
echo "$full_path" > "$cooldown_file"
cooldown_timestamp=$(stat -c %y "$cooldown_file")
#echo "$(date '+%Y-%m-%d %H:%M:%S') - Removed debounce file: $debounce_file and created cooldown file: $cooldown_file with timestamp: $cooldown_timestamp" >> "$log_file"
fi
fi
fi
done
# クールダウンファイルのクリーンアップ
find /tmp/cooldown_* -type f -mmin +1 -exec rm {} \;
done