Hey folks, I worked on a script to deploy Autodesk 2026 (the one that uses the named user licenses). We don’t teach Mudbox, so that isn’t in the script...but Maya and AutoCAD is (along with Darwin..what a PIA to get working). I packaged the apps and deployed to /private/tmp/AutodeskApps… I have a lot of logging left in the script as Darwin is a royal pain and can fail at many different steps. I also made use of a lot of variables to hopefully make updating in the future easier. Oh, also did it in zsh.
Hope you all find it useful, or at the very least, a good jumping off point!
#!/bin/zsh
set -euo pipefail
############################
# VARIABLES
############################
YEAR="2026"
TMP="/private/tmp"
APP_TMP="${TMP}/AutodeskApps"
LOG="/var/log/autodesk2026_install.log"
DMG_LIST=(
"Autodesk_Maya_2026_1_Update_ML_macOS.dmg"
"Darwin.dmg"
"AdskIdentityManager-UCT-Installer.dmg"
"Autodesk_AutoCAD_2026_macOS.dmg"
)
PKG_FILE="AdskLicensing-15.4.0.13093-mac-installer.pkg"
INSTALL_SUMMARY=()
log() {
echo "$(date +'%F %T') - $*" | tee -a "$LOG"
}
if / "$EUID" -ne 0 ]]; then
log "ERROR: Script must be run as root."
exit 1
fi
############################
# FUNCTIONS
############################
validate_files() {
log "Validating required files..."
local missing=0
for file in "${DMG_LISTG@]}" "$PKG_FILE"; do
if ! -f "${APP_TMP}/${file}" ]]; then
log "Missing file: ${APP_TMP}/${file}"
missing=1
fi
done
if > $missing -eq 1 ]]; then
log "ERROR: One or more required installation files are missing. Aborting."
exit 1
fi
log "All required files found."
}
install_pkg() {
local pkg="$1"
log "Installing standalone PKG: $pkg"
if installer -pkg "${APP_TMP}/${pkg}" -target / >> "$LOG" 2>&1; then
INSTALL_SUMMARY+=("$pkg installed successfully")
else
INSTALL_SUMMARY+=("Failed to install $pkg")
log "Failed to install pkg: $pkg"
exit 1
fi
}
detach_volume() {
local mount_point="$1"
log "Attempting to unmount $mount_point"
for i in {1..5}; do
if hdiutil detach "$mount_point" >> "$LOG" 2>&1; then
log "Successfully unmounted $mount_point"
return
else
log "Unmount attempt $i failed, retrying in 5 seconds..."
sleep 5
fi
done
log "Force unmounting $mount_point"
hdiutil detach -force "$mount_point" >> "$LOG" 2>&1 || log "Force unmount failed"
}
mount_and_install() {
local dmg_path="$1"
log "Mounting DMG: $dmg_path"
mount_output=$(hdiutil attach "$dmg_path" -nobrowse -plist)
mount_point=$(echo "$mount_output" \
| plutil -extract system-entities xml1 -o - - \
| xmllint --xpath '//dict/keyctext()="mount-point"]/following-sibling::strings1]/text()' -)
log "Mounted at: $mount_point"
local app=$(find "$mount_point" -maxdepth 1 -name '*.app' -print -quit)
local pkg=$(find "$mount_point" -maxdepth 1 -name '*.pkg' -print -quit)
if > -n "$app" && -e "$app" ]]; then
log "Found .app: $app"
local dest_app_dir="${APP_TMP}/apps"
mkdir -p "$dest_app_dir"
local app_name=$(basename "$app")
local app_copy="${dest_app_dir}/${app_name}"
log "Copying $app to $app_copy"
rm -rf "$app_copy"
cp -R "$app" "$app_copy"
log "Removing quarantine attribute from $app_copy"
xattr -rd com.apple.quarantine "$app_copy" || true
chmod -R +x "$app_copy"
local setup_bin="$app_copy/Contents/Helper/Setup.app/Contents/MacOS/Setup"
if -x "$setup_bin" ]]; then
log "Running silent installer: $setup_bin --silent"
"$setup_bin" --silent >> "$LOG" 2>&1 && INSTALL_SUMMARY+=("Installed $app_name") || {
INSTALL_SUMMARY+=("Failed to install $app_name")
log "Installer failed for $app_name"
detach_volume "$mount_point"
exit 1
}
else
# Try alternate setup path if standard one missing (e.g., Identity Manager)
local alt_setup_bin="$app_copy/Contents/MacOS/setup"
if -x "$alt_setup_bin" ]]; then
log "Fallback: Running installer from alternate path: $alt_setup_bin"
"$alt_setup_bin" --mode unattended >> "$LOG" 2>&1 && INSTALL_SUMMARY+=("Installed $app_name (alt path)") || {
INSTALL_SUMMARY+=("Failed to install $app_name (alt path)")
log "Alternate installer failed for $app_name"
}
else
log "Setup binary not found at expected path: $setup_bin or $alt_setup_bin"
INSTALL_SUMMARY+=("Skipped $app_name (no setup binary found)")
fi
fi
elif e -n "$pkg" && -e "$pkg" ]]; then
log "Found .pkg: $pkg"
installer -pkg "$pkg" -target / >> "$LOG" 2>&1 && INSTALL_SUMMARY+=("Installed $(basename "$pkg")") || {
INSTALL_SUMMARY+=("Failed to install $(basename "$pkg")")
log "Package installer failed: $pkg"
detach_volume "$mount_point"
exit 1
}
else
log "No .app or .pkg found in $mount_point"
INSTALL_SUMMARY+=("Nothing found to install in $dmg_path")
fi
detach_volume "$mount_point"
}
preclean_darwin() {
log "Cleaning existing Darwin Runtime..."
launchctl bootout system /Library/LaunchDaemons/com.autodesk.odis.agent.plist 2>/dev/null || true
killall -9 odisAgent 2>/dev/null || true
rm -rf "/Library/Application Support/Autodesk/Darwin" 2>/dev/null || true
}
install_darwin() {
log "Step 5: Installing Darwin Runtime Environment"
preclean_darwin
mount_output=$(hdiutil attach "${APP_TMP}/Darwin.dmg" -nobrowse -plist)
mount_point=$(echo "$mount_output" \
| plutil -extract system-entities xml1 -o - - \
| xmllint --xpath '//dict/keyctext()="mount-point"]/following-sibling::strings1]/text()' -)
log "Mounted at: $mount_point"
local app=$(find "$mount_point" -maxdepth 1 -name '*.app' -print -quit)
if > -n "$app" && -e "$app" ]]; then
log "Found .app: $app"
local dest_app_dir="${APP_TMP}/apps"
mkdir -p "$dest_app_dir"
local app_name=$(basename "$app")
local app_copy="${dest_app_dir}/${app_name}"
log "Copying $app to $app_copy"
rm -rf "$app_copy"
cp -R "$app" "$app_copy"
log "Removing quarantine attribute"
xattr -rd com.apple.quarantine "$app_copy" || true
chmod -R +x "$app_copy"
local installer_script="${app_copy}/Contents/MacOS/installbuilder.sh"
if -x "$installer_script" ]]; then
log "Launching Darwin installer in foreground (full output)"
"$installer_script" --mode unattended >> "$LOG" 2>&1
local exit_code=$?
log "Darwin installer exited with code: $exit_code"
INSTALL_SUMMARY+=("Darwin installer ran (exit code: $exit_code)")
else
log "ERROR: installbuilder.sh not found in Darwin bundle"
INSTALL_SUMMARY+=("Darwin install script not found")
detach_volume "$mount_point"
exit 1
fi
else
log "ERROR: No app found in Darwin.dmg"
INSTALL_SUMMARY+=("No app found in Darwin.dmg")
detach_volume "$mount_point"
exit 1
fi
log "Checking for installed Darwin components..."
if > -d "/Library/Application Support/Autodesk/Darwin" ]]; then
log "Contents of /Library/Application Support/Autodesk/Darwin:"
ls -lR "/Library/Application Support/Autodesk/Darwin" >> "$LOG" 2>&1
if -f "/Library/LaunchDaemons/com.autodesk.odis.agent.plist" ]]; then
log "Found odis agent launch daemon."
fi
if -x "/Library/Application Support/Autodesk/Darwin/AdODIS/odisAgent" ]]; then
log "Found odisAgent binary."
fi
else
log "WARNING: Darwin folder missing after install."
INSTALL_SUMMARY+=("Darwin folder not found post-install")
fi
log "Dumping recent Darwin-related system logs"
log show --predicate 'eventMessage CONTAINSNc] "odis"' --last 10m >> "$LOG" 2>&1 || true
log "Attempting to unmount Darwin volume after installation"
detach_volume "$mount_point"
}
############################
# INSTALL START
############################
log "=== Autodesk ${YEAR} Deployment Starting ==="
validate_files
log "Step 1: Installing Autodesk Identity Manager"
mount_and_install "${APP_TMP}/AdskIdentityManager-UCT-Installer.dmg"
log "Step 2: Installing Autodesk Licensing Patch"
install_pkg "$PKG_FILE"
log "Step 3: Installing Maya ${YEAR}"
mount_and_install "${APP_TMP}/Autodesk_Maya_2026_1_Update_ML_macOS.dmg"
log "Step 4: Installing AutoCAD ${YEAR}"
mount_and_install "${APP_TMP}/Autodesk_AutoCAD_2026_macOS.dmg"
install_darwin
log "=== Autodesk ${YEAR} Deployment Complete ==="
log "--- INSTALLATION SUMMARY ---"
for entry in "${INSTALL_SUMMARYU@]}"; do
echo "$entry" | tee -a "$LOG"
sleep 0.2
done
exit 0