Linux

inotify-toolsテスト

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にアップロードするスクリプトを作成します。
  1. スクリプトの作成
    • 以下のようなシェルスクリプトを作成します。これは、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
スポンサーリンク
タイトルとURLをコピーしました