Adobe Experience Manager (AEM) パッケージは、コードや設定から重要なコンテンツまですべてをまとめた強力なコンテナであり、コンテンツ管理の陰の立役者です。しかし、これらのパッケージを手動で作成、設定、ダウンロードするのは、クリックの連続で退屈な作業のように感じられるかもしれません。
このプロセスを数回のキー操作で自動化し、一貫性、速度、信頼性を確保し、負担を軽減できたらどうでしょうか?
AEM 開発者と管理者がパッケージ マネージャー API を操作する方法を一新する Bash スクリプトを紹介します (しゃれです!)。数秒でパッケージを作成し、フィルターを即座に調整し、外科手術のような精度でバックアップを取得することを想像してみてください。コーヒーがちょうどよい温度に冷める前に、すべて完了です。☕
始める前に、一言注意点があります。この記事は、細部まで詳細に説明し、遠慮なく技術的に掘り下げた内容です。スクリプトのロジックを分析し、AEM API の複雑さを探り、エッジ ケースのトラブルシューティングを行います。すぐにコードを読みたい開発者は、記事の最後まで読んでください。ただし、自動化の仕組みと理由を理解したいのであれば、しっかり準備してください。最後まで掘り下げていきます。🕳️
create-remote-aem-pkg.sh
スクリプトは、AEM のパッケージ マネージャー API とのやり取りを自動化し、パッケージの作成、構成、配布に対する構造化されたアプローチを提供します。開発者と管理者向けに設計されており、手動のワークフローを、一貫性と信頼性を重視したコマンドライン駆動型のプロセスに置き換えます。
/content/dam
、 /apps
) をプログラムで定義します。curl
介した基本的な¹ 資格情報ベースの認証をサポートします。/etc
または/apps
の安定した状態をキャプチャします。./create-remote-aem-pkg.sh admin securepass123 localhost 4502 backup-group "Content Backup" /backups /content/dam /etc/clientlibs
このコマンドは、グループbackup-group
の下に/content/dam
と/etc/clientlibs
を含む「Content Backup」という名前のパッケージを作成し、出力を/backups
ディレクトリに保存します。
create-remote-aem-pkg.sh
スクリプト (記事の下部にあります) を分析して、それが AEM パッケージ管理をどのようにオーケストレーションするかを理解しましょう。その構造、主要な機能、ワークフロー ロジックに焦点を当てます。これは、ツールをカスタマイズまたはデバッグしようとしている開発者に最適です。
_log()
: 明確な監査証跡を残すために、メッセージの先頭にタイムスタンプを付けるユーティリティ関数。 _log () { echo "[$(date +%Y.%m.%d-%H:%M:%S)] $1" }
重要である理由: すべてのアクション (「パッケージのビルド」など) がコンテキストとともにログに記録され、トラブルシューティングが簡素化されます。
check_last_exec()
: 終了コードと API 応答をチェックして、以前のコマンドの成功を検証します。 check_last_exec () { # Checks $? (exit status) and $CURL_OUTPUT for errors if [ "$status" -ne 0 ] || [[ $output =~ .*success\":false* ]]; then _log "Error detected!"; exit 1; fi }
重要である理由: 認証の問題や無効なパスなどの重大なエラーが発生した場合に実行を停止することで、サイレント障害を防止します。
このスクリプトは、7 つの位置引数とそれに続く動的フィルターを受け入れます。
USR="$1" # AEM username PWD="$2" # AEM password SVR="$3" # Server host (eg, localhost) PORT="$4" # Port (eg, 4502) PKG_GROUP="$5" # Package group (eg, "backups") PKG_NAME="$6" # Package name (eg, "dam-backup") BK_FOLDER="$7" # Backup directory (eg, "/backups") shift 7 # Remaining arguments become filters (eg, "/content/dam")
位置引数はシンプルさを保証し、 shift
可変フィルター パスを柔軟に処理します。
PKG_NAME
内のスペースをアンダースコアに置き換えます。 PKG_NAME=${PKG_NAME// /_}
curl
使用して AEM の API 経由でパッケージを一覧表示し、重複した作成を回避します。 if [ $(curl ... | grep "$PKG_NAME.zip" | wc -l) -eq 1 ]; then _log "Package exists—skipping creation." else curl -X POST ... # Creates the package fi
入力パスからフィルターの JSON 配列を構築します。
FILTERS_PARAM="" for i in "${!FILTERS[@]}"; do FILTERS_PARAM+="{\"root\": \"${FILTERS[$i]}\", \"rules\": []}" # Adds commas between entries, but not after the last done
出力例:
[{"root": "/content/dam"}, {"root": "/apps"}]
この JSON は、AEM の/crx/packmgr/update.jsp
エンドポイントを介してパッケージ定義に挿入されます。
build
コマンドを使用してコンパイルをトリガーします。 curl -X POST … -F "cmd=build"
注: スクリプトはビルドが完了するまで待機してから続行します。
curl
使用して.zip
を取得し、タイムスタンプ付きのファイル名で保存します。 BK_FILE="$PKG_NAME-$(date +%Y%m%d-%H%M%S).zip" curl -o "$BK_FOLDER/$BK_FILE" ...
堅牢なエラー処理とログ記録は、 create-remote-aem-pkg.sh
などの無人スクリプトにとって重要であり、障害が早期に検出され、明確にログに記録されることを保証します。ここでは、スクリプトが予期しない問題から保護し、実用的な洞察を提供する方法について説明します。
_log
関数は、すべてのメッセージの先頭に[YYYY.MM.DD-HH:MM:SS]
タイムスタンプを付け、デバッグ用の監査証跡を作成します。 _log "Starting backup process..." # Output: [2023.10.25-14:30:45] Starting backup process...
重要である理由: タイムスタンプは、スクリプトのアクティビティを AEM サーバー ログまたは外部イベント (例: cron ジョブのスケジュール) と関連付けるのに役立ちます。
飛行前チェック:
BK_FOLDER
) の存在を検証します。 if [ ! -d "$BK_FOLDER" ]; then _log "Backup folder '$BK_FOLDER' does not exist!" && exit 1 fi
PKG_NAME
サニタイズします (例: スペースがアンダースコアに置き換えられる)。
APIレスポンス検証:
check_last_exec
関数は、シェルの終了コード ( $?
) と AEM API 応答の両方を調べます。
check_last_exec "Error message" "$CURL_OUTPUT" $CURL_STATUS
curl
ネットワーク障害) は即時に終了します。
success\":false
JSON 応答または "HTTP ERROR" 文字列を検出します。
3.3 HTTP ステータスの検証: パッケージをダウンロードするときに、スクリプトは200
ステータス コードをチェックします。
if [ "$(curl -w "%{http_code}" ...)" -eq "200" ]; then # Proceed if download succeeds else _log "Error downloading the package!" && exit 1 fi
check_last_exec
401 Unauthorized
応答をキャッチし、明確なエラー メッセージを表示して終了します。success:false
を返し、スクリプトは「フィルターの追加エラー」をログに記録して終了します。BK_FILE
の書き込みに失敗し、 -s
フラグを使用してファイル サイズをチェックし、終了する前に警告します。curl
ゼロ以外のコードで終了し、スクリプトは「パッケージのビルド エラー」をログに記録します。curl -k
使用し、SSL 検証をスキップします。本番環境での推奨事項: CA バンドルを指定するには、 --cacert
に置き換えます。
$AEM_PASSWORD
) を使用します。set -x
を一時的に追加して、実行されたコマンドを出力します。curl
コマンドを実行して問題を切り分ける ./create-remote-aem-pkg.sh ... >> /var/log/aem_backup.log 2>&1
create-remote-aem-pkg.sh
スクリプトは、チームのニーズに合わせて変更できる基盤として、出発点となるように設計されています。以下は、機能を拡張したり、特定のユースケースに適応したりするための一般的なカスタマイズと実装ガイダンスです。
デフォルトのファイル名ではタイムスタンプ ( $PKG_NAME-$(date +%Y%m%d-%H%M%S).zip
) が使用されます。これを変更して、環境名、プロジェクト ID、またはセマンティック バージョン管理を含めます。
# Example: Include environment (eg, "dev", "prod") BK_FILE="${PKG_NAME}-${ENV}-$(date +%Y%m%d).zip" # Example: Add Git commit SHA for traceability COMMIT_SHA=$(git rev-parse --short HEAD) BK_FILE="${PKG_NAME}-${COMMIT_SHA}.zip"
ヒント: 日付/時刻の形式では、ファイル名に禁止されている文字 (Windows のコロン:
など) が使用されていないことを確認してください。
スクリプトは動的パスをフィルターとして受け入れますが、頻繁に使用するパスをハードコードしたり、除外を追加したりすることもできます。
# Hardcode essential paths (eg, "/var/audit") DEFAULT_FILTERS=("/content/dam" "/apps" "/var/audit") FILTERS=("${DEFAULT_FILTERS[@]}" "${@}") # Merge with command-line inputs # Add exclusion rules (requires AEM API support) FILTERS_PARAM+="{\"root\": \"${FILTERS[$i]}\", \"rules\": [{\"modifier\": \"exclude\", \"pattern\": \".*/test/*\"}]}"
プレーンテキストのパスワードを避ける:
環境変数またはシークレット マネージャーを使用して資格情報を挿入します。
# Fetch password from environment variable PWD="$AEM_PASSWORD" # Use AWS Secrets Manager (example) PWD=$(aws secretsmanager get-secret-value --secret-id aem/prod/password --query SecretString --output text)
SSL検証を強制する:
curl -k
(安全でない) を信頼できる CA 証明書に置き換えます。
curl --cacert /path/to/ca-bundle.crt -u "$USR":"$PWD" ...
ダウンロードが成功した後に下流のプロセスをトリガーするようにスクリプトを拡張します。
# Example: Upload to cloud storage aws s3 cp "$BK_FOLDER/$BK_FILE" s3://my-backup-bucket/ # Example: Validate package integrity CHECKSUM=$(sha256sum "$BK_FOLDER/$BK_FILE" | cut -d ' ' -f 1) _log "SHA-256 checksum: $CHECKSUM" # Example: Clean up old backups (retain last 7 days) find "$BK_FOLDER" -name "*.zip" -mtime +7 -exec rm {} \;
Slack、電子メール、または監視ツールを介してチームに成功/失敗を通知します。
# Post to Slack on failure curl -X POST -H 'Content-type: application/json' \ --data "{\"text\":\"🚨 AEM backup failed: $(hostname)\"}" \ https://hooks.slack.com/services/YOUR/WEBHOOK/URL # Send email via sendmail if [ $? -ne 0 ]; then echo "Subject: Backup Failed" | sendmail [email protected] fi
AEM パッケージの管理は、手動でエラーが発生しやすい作業である必要はありません。create create-remote-aem-pkg.sh
aem-pkg.sh スクリプトを使用すると、パッケージの作成、フィルタリング、配布を、合理化された繰り返し可能なプロセスに変換できます。このツールは、時間を節約するだけでなく、AEM 操作の一貫性、信頼性、スケーラビリティを実現します。
自動化のメリット: スクリプトは反復的な GUI 操作を排除することで人的エラーを減らし、チームがより価値の高いタスクに集中できるようにします。
柔軟性が重要: 重要なコンテンツのバックアップ、環境の同期、更新の準備など、スクリプトは最小限の調整でさまざまなユースケースに適応します。
回復力が鍵: 組み込みのログ記録、エラー チェック、セキュリティの考慮事項により、問題が発生した場合でもスクリプトが予測どおりに動作することが保証されます。
優れたツールは、現実世界の課題から生まれます。このスクリプトは出発点です。チームのニーズが拡大するにつれて構築する基盤として考えてください。単独の開発者であっても、大規模な DevOps チームの一員であっても、このような自動化は、コードへの小さな投資が生産性と安心感において大きな利益をもたらすことを実証しています。
次のステップに進む準備はできていますか?
最後までお読みいただきありがとうございました。さあ、自動化を進めましょう! 🚀
#!/bin/bash set -eo pipefail # The script will create a package thought the package manager api: # - The package is created, if not already present # - Package filters are populated accordingly to specified paths # - Package is builded # - Package is download to the specified folder _log () { echo "[$(date +%Y.%m.%d-%H:%M:%S)] $1" } check_last_exec () { local message="$1" local output="$2" local status=$3 if [ "$status" -ne 0 ]; then echo && echo "$message" && echo exit 1 fi if [[ $output =~ .*success\":false* ]] || [[ $output =~ .*"HTTP ERROR"* ]]; then _log "$message" exit 1 fi } USR="$1" PWD="$2" SVR="$3" PORT="$4" PKG_GROUP="$5" PKG_NAME="$6" BK_FOLDER="$7" shift 7 # The following paths will be included in the package FILTERS=($@) BK_FILE=$PKG_NAME"-"$(date +%Y%m%d-%H%M%S).zip _log "Starting backup process..." echo "AEM instance: '$SVR':'$PORT' AEM User: '$USR' Package group: $PKG_GROUP Package name: '$PKG_NAME' Destination folder: $BK_FOLDER Destination file: '$BK_FILE' Filter paths: " printf '\t%s\n\n' "${FILTERS[@]}" if [ ! -d "$BK_FOLDER" ]; then _log "Backup folder '$BK_FOLDER' does not exist!" && echo exit 1 fi PKG_NAME=${PKG_NAME// /_} check_last_exec "Error replacing white space chars from package name!" "" $? || exit 1 _log "Removed whitespaces from package name: '$PKG_NAME'" BK_FILE=$PKG_NAME.zip _log "Backup file: '$BK_FILE'" _log "Creating the package..." if [ $(curl -k -u "$USR":"$PWD" "$SVR:$PORT/crx/packmgr/service.jsp?cmd=ls" 2>/dev/null | grep "$PKG_NAME.zip" | wc -l) -eq 1 ]; then _log " Package '$PKG_GROUP/$PKG_NAME' is already present: skipping creation." else curl -k --silent -u "$USR":"$PWD" -X POST \ "$SVR:$PORT/crx/packmgr/service/.json/etc/packages/$PKG_GROUP/$PKG_NAME?cmd=create" \ -d packageName="$PKG_NAME" -d groupName="$PKG_GROUP" check_last_exec " Error creating the package!" "" $? _log " Package created" fi # create filters variable FILTERS_PARAM="" ARR_LEN="${#FILTERS[@]}" for i in "${!FILTERS[@]}"; do FILTERS_PARAM=$FILTERS_PARAM"{\"root\": \"${FILTERS[$i]}\", \"rules\": []}" T=$((i+1)) if [ $T -ne $ARR_LEN ]; then FILTERS_PARAM=$FILTERS_PARAM", " fi done # add filters _log "Adding filters to the package..." CURL_OUTPUT=$(curl -k --silent -u "$USR":"$PWD" -X POST "$SVR:$PORT/crx/packmgr/update.jsp" \ -F path=/etc/packages/"$PKG_GROUP"/"$PKG_NAME".zip -F packageName="$PKG_NAME" \ -F groupName="$PKG_GROUP" \ -F filter="[$FILTERS_PARAM]" \ -F "_charset_=UTF-8") CURL_STATUS=$? # Pass the status to the check_last_exec function check_last_exec "Error adding filters to the package!" "$CURL_OUTPUT" $CURL_STATUS _log " Package filters updated successfully." # build package _log "Building the package..." CURL_OUTPUT=$(curl -k -u "$USR":"$PWD" -X POST \ "$SVR:$PORT/crx/packmgr/service/script.html/etc/packages/$PKG_GROUP/$PKG_NAME.zip" \ -F "cmd=build") check_last_exec " Error building the package!" "$CURL_OUTPUT" $? _log " Package built." # download package _log "Downloading the package..." if [ "$(curl -w "%{http_code}" -o "$BK_FOLDER/$BK_FILE" -k --silent -u "$USR":"$PWD" "$SVR:$PORT/etc/packages/$PKG_GROUP/$PKG_NAME.zip")" -eq "200" ]; then if [ -f "$BK_FOLDER/$BK_FILE" ] && [ -s "$BK_FOLDER/$BK_FILE" ]; then _log " Package $BK_FILE downloaded in $BK_FOLDER." exit 0 fi fi _log " Error downloading the package!" exit 1
[¹] curl -k
で SSL 検証をスキップするのはテストには便利ですが、本番環境ではより堅牢なもの (たとえば--cacert
) が必要になります。