Ang mga package ng Adobe Experience Manager (AEM) ay ang mga unsung heroes ng content management — mga makapangyarihang container na nagsasama ng lahat mula sa code at mga configuration hanggang sa kritikal na content. Ngunit aminin natin: ang manu-manong paggawa, pag-configure, at pag-download ng mga paketeng ito ay parang nakakapagod na sayaw ng mga pag-click.
Paano kung maaari mong i-automate ang prosesong ito gamit ang ilang mga keystroke, tinitiyak ang pare-pareho, bilis, pagiging maaasahan, at hindi gaanong mabigat na pag-angat?
Magpapakita ako sa iyo ng isang Bash script na nag-flip sa script (pun intended!) sa kung paano gumagana ang mga developer at admin ng AEM sa Package Manager API. Mag-isip tungkol sa paggawa ng mga pakete sa ilang segundo, pag-aayos ng mga filter sa mabilisang, at pag-snagging ng mga backup nang may katumpakan sa operasyon — lahat bago lumamig ang iyong kape sa perpektong temperatura ng paghigop. ☕
Bago tayo sumisid, isang mabilis na paalala : Ang artikulong ito ay isang malalim na pagsisid, masinsinang detalyado at walang patawad na teknikal. Susuriin namin ang lohika ng script, tuklasin ang mga intricacies ng AEM API, at i-troubleshoot ang mga gilid ng kaso. Para sa mga developer na sabik na tumalon nang diretso sa code, maaari kang pumunta sa ibaba ng artikulo. Ngunit kung narito ka upang maunawaan kung paano at bakit sa likod ng automation, strap in — pupunta tayo hanggang sa rabbit hole. 🕳️
Ang script create-remote-aem-pkg.sh
ay nag-o-automate ng mga pakikipag-ugnayan sa Package Manager API ng AEM, na nag-aalok ng isang structured na diskarte sa paggawa, pagsasaayos, at pamamahagi ng package. Dinisenyo para sa mga developer at administrator, pinapalitan nito ang mga manual na daloy ng trabaho ng prosesong hinihimok ng command-line na nagbibigay-diin sa pagkakapare-pareho at pagiging maaasahan.
/content/dam
, /apps
) na isasama sa package.curl
./etc
o /apps
bago ilapat ang mga update sa system. ./create-remote-aem-pkg.sh admin securepass123 localhost 4502 backup-group "Content Backup" /backups /content/dam /etc/clientlibs
Lumilikha ang command na ito ng package na pinangalanang “Content Backup” sa ilalim ng group backup-group
, kasama /content/dam
at /etc/clientlibs
, at sine-save ang output sa /backups
directory.
Hatiin natin ang script ng create-remote-aem-pkg.sh
(makikita mo ito sa ibaba ng artikulo) upang maunawaan kung paano nito inaayos ang pamamahala ng package ng AEM. Magtutuon kami sa istruktura nito, mga pangunahing pag-andar, at lohika ng daloy ng trabaho—mahusay para sa mga developer na gustong i-customize o i-debug ang tool.
_log()
: Isang utility function na naglalagay ng prefix sa mga mensahe na may mga timestamp para sa malinaw na audit trail. _log () { echo "[$(date +%Y.%m.%d-%H:%M:%S)] $1" }
Bakit ito mahalaga : Tinitiyak na ang bawat aksyon (hal., "Package built") ay naka-log na may konteksto, na nagpapasimple sa pag-troubleshoot.
check_last_exec()
: Pinapatunayan ang tagumpay ng mga naunang command sa pamamagitan ng pagsuri sa mga exit code at mga tugon sa 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 }
Bakit ito mahalaga : Pinipigilan ang mga tahimik na pagkabigo sa pamamagitan ng paghinto sa pagpapatupad sa mga kritikal na error tulad ng mga isyu sa pagpapatotoo o di-wastong mga landas.
Tumatanggap ang script ng pitong positional na argumento na sinusundan ng mga dynamic na filter:
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")
Tinitiyak ng mga posisyong argumento ang pagiging simple, habang shift
ay humahawak sa mga variable na path ng filter nang may kakayahang umangkop.
PKG_NAME
ng mga underscore upang maiwasan ang mga isyu sa URL. PKG_NAME=${PKG_NAME// /_}
curl
para maglista ng mga package sa pamamagitan ng AEM's API, na umiiwas sa mga paulit-ulit na paggawa. if [ $(curl ... | grep "$PKG_NAME.zip" | wc -l) -eq 1 ]; then _log "Package exists—skipping creation." else curl -X POST ... # Creates the package fi
Bumubuo ng JSON array ng mga filter mula sa mga input path:
FILTERS_PARAM="" for i in "${!FILTERS[@]}"; do FILTERS_PARAM+="{\"root\": \"${FILTERS[$i]}\", \"rules\": []}" # Adds commas between entries, but not after the last done
Halimbawang output :
[{"root": "/content/dam"}, {"root": "/apps"}]
Ang JSON na ito ay ini-inject sa kahulugan ng package sa pamamagitan ng AEM's /crx/packmgr/update.jsp
endpoint.
build
command ng AEM: curl -X POST … -F "cmd=build"
Tandaan : Hinihintay ng script na makumpleto ang build bago magpatuloy.
curl
para kunin ang .zip
at i-save ito gamit ang timestamped na filename: BK_FILE="$PKG_NAME-$(date +%Y%m%d-%H%M%S).zip" curl -o "$BK_FOLDER/$BK_FILE" ...
Ang matatag na paghawak ng error at pag-log ay kritikal para sa mga hindi binabantayang script tulad ng create-remote-aem-pkg.sh
, tinitiyak na ang mga pagkabigo ay maagang nahuhuli at malinaw na naka-log. Narito kung paano pinangangalagaan ng script ang mga hindi inaasahang isyu at nagbibigay ng mga naaaksyunan na insight.
_log
function ay naglalagay ng prefix sa bawat mensahe na may [YYYY.MM.DD-HH:MM:SS]
timestamp, na lumilikha ng audit trail para sa pag-debug: _log "Starting backup process..." # Output: [2023.10.25-14:30:45] Starting backup process...
Bakit ito mahalaga : Nakakatulong ang mga timestamp na iugnay ang aktibidad ng script sa mga log ng server ng AEM o mga panlabas na kaganapan (hal., mga iskedyul ng trabaho ng cron).
Mga Pagsusuri bago ang Paglipad :
BK_FOLDER
) bago magpatuloy: if [ ! -d "$BK_FOLDER" ]; then _log "Backup folder '$BK_FOLDER' does not exist!" && exit 1 fi
PKG_NAME
upang maiwasan ang mga isyu sa URL (hal., ang mga puwang ay pinalitan ng mga underscore).
Pagpapatunay ng Tugon sa API :
Sinusuri ng function check_last_exec
ang parehong mga shell exit code ( $?
) at mga tugon ng AEM API:
check_last_exec "Error message" "$CURL_OUTPUT" $CURL_STATUS
curl
network failures) ay nagti-trigger ng mga agarang paglabas.
success\":false
na mga tugon ng JSON o mga string ng "HTTP ERROR" sa output ng AEM.
3.3 Pag-verify ng Katayuan ng HTTP : Kapag nagda-download ng package, sinusuri ng script ang 200
status code:
if [ "$(curl -w "%{http_code}" ...)" -eq "200" ]; then # Proceed if download succeeds else _log "Error downloading the package!" && exit 1 fi
check_last_exec
ay nakakuha ng 401 Unauthorized
tugon at lumabas na may malinaw na mensahe ng error.success:false
, ang script ay nag-log ng "Error sa pagdaragdag ng mga filter" at nagwawakas.BK_FILE
, sinusuri ang laki ng file gamit ang -s
flag at mga alerto bago lumabas.curl
exits with a non-zero code, the script logs "Error building the package".curl -k
para sa pagiging simple, na lumalampas sa pag-verify ng SSL. Rekomendasyon para sa Produksyon : Palitan ng --cacert
para tumukoy ng CA bundle.
$AEM_PASSWORD
).set -x
sa simula ng script upang mag-print ng mga naisagawang command.curl
command sa labas ng script ./create-remote-aem-pkg.sh ... >> /var/log/aem_backup.log 2>&1
Ang script ng create-remote-aem-pkg.sh
ay idinisenyo upang maging isang panimulang punto—isang pundasyon na maaari mong baguhin upang iayon sa mga pangangailangan ng iyong koponan. Nasa ibaba ang mga karaniwang pag-customize, kasama ang gabay sa pagpapatupad, upang palawigin ang functionality nito o iakma ito sa mga partikular na sitwasyon ng paggamit.
Gumagamit ang default na filename ng timestamp ( $PKG_NAME-$(date +%Y%m%d-%H%M%S).zip
). Baguhin ito upang isama ang mga pangalan ng kapaligiran, project ID, o semantic versioning:
# 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"
Tip : Tiyaking maiiwasan ng mga format ng petsa/oras ang mga character na ipinagbabawal sa mga filename (hal., mga colon :
sa Windows).
Tumatanggap ang script ng mga dynamic na path bilang mga filter ngunit maaari ka ring mag-hardcode ng mga madalas na ginagamit na path o magdagdag ng mga pagbubukod:
# 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/*\"}]}"
Iwasan ang mga Plaintext na Password :
Gumamit ng mga variable ng kapaligiran o isang secret manager para mag-inject ng mga kredensyal:
# 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)
Ipatupad ang SSL Validation :
Palitan curl -k
(insecure) ng pinagkakatiwalaang CA certificate:
curl --cacert /path/to/ca-bundle.crt -u "$USR":"$PWD" ...
Palawakin ang script upang ma-trigger ang mga downstream na proseso pagkatapos ng matagumpay na pag-download:
# 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 {} \;
Abisuhan ang mga koponan ng tagumpay/pagkabigo sa pamamagitan ng Slack, email, o mga tool sa pagsubaybay:
# 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
Ang pamamahala sa mga pakete ng AEM ay hindi kailangang maging isang manu-mano, madaling gawaing may error. Gamit ang script create-remote-aem-pkg.sh
, maaari mong baguhin ang paggawa, pag-filter, at pamamahagi ng package sa isang streamlined, nauulit na proseso. Ang tool na ito ay hindi lamang tungkol sa pagtitipid ng oras, ito ay tungkol sa pagpapagana ng pagkakapare-pareho, pagiging maaasahan, at scalability sa iyong mga pagpapatakbo ng AEM.
Panalo ang Automation : Sa pamamagitan ng pag-aalis ng mga paulit-ulit na pakikipag-ugnayan sa GUI, binabawasan ng script ang error ng tao at pinalalaya ang mga koponan na tumuon sa mga gawaing may mas mataas na halaga.
Mga Mahalaga sa Flexibility : Nagba-back up man ng kritikal na content, nagsi-sync ng mga environment, o naghahanda para sa mga update, umaangkop ang script sa magkakaibang sitwasyon ng paggamit na may kaunting tweaking.
Ang Resilience is Key : Ang built-in na pag-log, mga pagsusuri sa error, at mga pagsasaalang-alang sa seguridad ay tinitiyak na ang script ay kumikilos nang predictably, kahit na ang mga bagay-bagay ay pumunta patagilid.
Ang mga mahuhusay na tool ay ipinanganak mula sa mga hamon sa totoong mundo. Ang script na ito ay isang panimulang punto; isipin ito bilang isang pundasyon na dapat itayo habang lumalaki ang mga pangangailangan ng iyong koponan. Solo developer ka man o bahagi ng isang malaking koponan ng DevOps, ang automation na tulad nito ay nagpapakita kung paano ang maliliit na pamumuhunan sa code ay maaaring magbunga ng napakalaking kita sa pagiging produktibo at kapayapaan ng isip.
Handa nang gawin ang susunod na hakbang?
Salamat sa pagsubaybay — ngayon pumunta at mag-automate! 🚀
#!/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
[¹] Ang paglaktaw sa pag-verify ng SSL gamit ang curl -k
ay madaling gamitin para sa pagsubok, ngunit gugustuhin mo ang isang bagay na mas matibay sa produksyon (halimbawa --cacert
)!