👏

複数サーバー間でのJOBの流れをコントロール(WORKFLOW)単純にFLAGファイルでやってみた

2024/12/20に公開

複数サーバー間でJOBの流れをコントロールするやり方にはいろいろありますが、まあ通常はAWSのSQSとか、オンプレであればRedis、さらにRabbitMQなど利用してQUEUEを参照してJOBの起動のタイミングを制御やり方が王道(でそのほうが美しい)かと思います。あるいはもっとレトロ?にcronで時間見積方式でやる。今回は2つ以上のサーバー間で簡単にSSH(SFTP, SCP)のポートのみ(あるいはFTPS)が空いているような環境で簡単に構築するということで、ファイルの作成を検知してJOBを発火する方法を忘備録としてかいてみました。使うのはinotify-tools なんおことはない、CRONが時間でJOBを起動するのに対して、これはファイルの生成などを検知するツールです。

  • まずはともあれインストール
# apt install inotify-tools

そしてらできあがりです!

  • 生成されるファイル名で分岐したJOBを発火
    以下のようなBASHでファイル名のパターンをチェックして、JOBを条件分岐で実行できます
#!/bin/bash

# 監視対象ディレクトリ(サブディレクトリは含まない)
WATCH_DIR="/opt/datafromotherserver/"
ARCHIVE_DIR = "/opt/archive/"
# ファイル作成イベントを監視(サブディレクトリは監視せず、WATCH_DIRのみ監視)
inotifywait -m -e create --format '%w%f' "$WATCH_DIR" | while read FILE
do
    echo "New file detected: $FILE"
    sleep 15
    # ファイル名のパターンを確認
    if [[ "$FILE" == "$WATCH_DIR"A*.csv ]]; then
        # Do Operation A
        python3 A.py 
    elif [[ "$FILE" == "$WATCH_DIR"B*.csv ]]; then
        # Do Operation B
        python3 B.py 
    elif [[ "$FILE" == "$WATCH_DIR"C*.csv ]]; then
        # Do Operation C
        python3 C.py 
    else
        echo "File $FILE does not match any specified pattern."
    fi
    mv $FILE $ARCHIVE_DIR
done

- 特定ファイルの中身に指令を書いて実行
もちろん、ファイルの中身をみて、それに応じて実行するPROGRAMの制御も可能です。

#!/bin/bash

# 監視対象ディレクトリ
WATCH_DIR="/opt/datafromotherserver/"
ARCHIVE_DIR="/opt/archive/"

# ファイル作成イベントを監視
inotifywait -m -e create --format '%w%f' "$WATCH_DIR" | while read FILE
do
    echo "New file detected: $FILE"
    sleep 5  # ファイルが完全に書き込まれるまで待機

    # ファイル名が「命令.txt」の場合のみ処理
    if [[ "$(basename "$FILE")" == "命令.txt" ]]; then
        echo "Processing $FILE as 命令.txt"

        # ファイルの中身を読み取って分岐処理
        while IFS= read -r LINE || [ -n "$LINE" ]; do
            echo "Executing command: $LINE"

            case "$LINE" in
                "指令A")
                    echo "Executing 指令A..."
                    python3 A.py
                    ;;
                "指令B")
                    echo "Executing 指令B..."
                    python3 B.py
                    ;;
                "指令C")
                    echo "Executing 指令C..."
                    python3 C.py
                    ;;
                *)
                    echo "Unknown command: $LINE"
                    ;;
            esac
        done < "$FILE"

        # 処理が完了したらファイルをアーカイブ
        mv "$FILE" "$ARCHIVE_DIR"
        echo "$FILE archived to $ARCHIVE_DIR"
    else
        echo "File $FILE is not 命令.txt. Skipping."
    fi
done

所感として、

  • 別サーバーでの転送予定のファイル生成完了の時間が変動が大きいためCRONを使いづらい時
  • サーバー数が少ない環境、例えばサーバー例えば2台のサーバーでのファイル送信の検知
  • 完全に閉じたイントラネット内の環境でサーバーのPORTの開放が限定されている
    ようなところで手軽に使えるものかと思いました。

Discussion