FileMakerのオブジェクトをS3にアップロードするのその後だが、アップロードに時間がかかるので(10,000件で4時間)速くなる方法がないかAIに聞いたらxargsを使うとコマンドを並列処理できるらしい。以下がそのコード。
upload_objects_to_s3.sh
#!/bin/bash
# 言語環境をen_US.UTF-8に設定
export LC_ALL=en_US.UTF-8
# cronで実行に必要
PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
export PATH
# ログファイルのパス
LOG_FILE="/Users/iwaninc/Documents/tmp/upload_script.log"
# 停止ファイルのパス
STOP_FILE="/Users/iwaninc/Documents/tmp/stop_upload_script"
# ロックファイルのパス
LOCK_FILE="/Users/iwaninc/Documents/tmp/upload_script.lock"
# ロックファイルのチェックと作成
if [ -e "$LOCK_FILE" ]; then
echo "$(date) Another instance is already running. Exiting." >> "$LOG_FILE"
exit 1
else
touch "$LOCK_FILE"
fi
# 終了時にロックファイルを削除する関数
cleanup() {
rm -f "$LOCK_FILE"
echo "$(date) Script finished, lock file removed." >> "$LOG_FILE"
}
# スクリプト終了時にcleanup関数を呼び出す
trap cleanup EXIT
# グローバル変数で停止フラグを設定
stop_flag=0
# シグナルハンドラ
trap 'stop_flag=1; echo "$(date) Received stop signal. Stopping gracefully..." >> "$LOG_FILE"' SIGINT SIGTERM
# 停止ファイルをチェックする関数
check_stop_file() {
if [ -f "$STOP_FILE" ]; then
echo "$(date) Stop file detected. Stopping process..." >> "$LOG_FILE"
stop_flag=1
rm -f "$STOP_FILE" # 停止ファイルを削除
fi
}
echo "$(date) Start..." >> "$LOG_FILE"
# アップロード先のS3バケット名
S3_BUCKET="<バケット名>"
# ディレクトリとプレフィックスの配列
DIRECTORIES=("/Users/iwaninc/Documents/object" "/Users/iwaninc/Documents/object2" "/Users/iwaninc/Documents/object3")
PREFIXES=("<プレフィックス1>" "<プレフィックス2>" "<プレフィックス3>")
# 並列処理の数(同時にアップロードするファイルの数)
PARALLEL_JOBS=10
upload_and_delete() {
local file="$1"
local bucket="$2"
local prefix="$3"
local filename=$(basename "$file")
# 停止フラグをチェック
if [ $stop_flag -eq 1 ]; then
echo "$(date) Stopping process for file: $file" >> "$LOG_FILE"
return
fi
if aws s3 cp "$file" "s3://$bucket/$prefix/$filename" --quiet; then
echo "$(date) Uploaded: $file" >> "$LOG_FILE"
rm "$file"
echo "$(date) Deleted local file: $file" >> "$LOG_FILE"
else
echo "$(date) Upload failed: $file" >> "$LOG_FILE"
fi
}
export -f upload_and_delete
export stop_flag
export LOG_FILE
for i in "${!DIRECTORIES[@]}"; do
# 停止フラグをチェック
check_stop_file
if [ $stop_flag -eq 1 ]; then
echo "$(date) Stopping process before processing directory: ${DIRECTORIES[$i]}" >> "$LOG_FILE"
break
fi
DIR="${DIRECTORIES[$i]}"
PREFIX="${PREFIXES[$i]}"
echo "$(date) Processing directory: $DIR" >> "$LOG_FILE"
# 並列処理でファイルをアップロード
find "$DIR" -type f -print0 | xargs -0 -P "$PARALLEL_JOBS" -I {} bash -c '
if [ $stop_flag -eq 0 ]; then
upload_and_delete "{}" "$0" "$1"
fi
' "$S3_BUCKET" "$PREFIX"
echo "$(date) Finished processing directory: $DIR" >> "$LOG_FILE"
done
echo "$(date) Upload and deletion completed or stopped." >> "$LOG_FILE"
4時間以上かかっていたのが30分ほどになり10倍くらい速くなった。並列数はPARALLEL_JOBSで調整できるがMac Studio (M1 Max メモリ64GB)で60で実行するとCPUモニタはこんな感じになる(黒い部分が全くない)。
処理が終わるとこんな感じ。
がんばっていただいてました。