Overview
Patching AIX in production can be risky if done on the active rootvg. Using alternate rootvg allows you to:
- Clone the rootvg to a free disk
- Apply patches (TL/SP) safely
- Switch bootlist to the updated rootvg
- Minimize downtime
- Rootvg mirror disks
- Pre-existing altinst_rootvg
- Disk discovery and NFS mounting for patch repository
Complete Script
The following production-ready script fully automates patching with alternate rootvg, handling mirrors and existing altinst_rootvg.
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#!/usr/bin/ksh
###############################################################################
# aix_os_patch-one-host.ksh
# Purpose: AIX OS patching using alternate rootvg, handling mirrors and altinst_rootvg
# Author: adminCtrlX
# Script Preview Mode : ./aix_os_patch-one-host.ksh -h my-aix-host -o patch -p
# Script Full Upgrade : ./aix_os_patch-one-host.ksh -h my-aix-host -o patch -f
###############################################################################
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Sample Run — Preview Mode
# ./aix_os_patch-one-host.ksh -h my-aix-host -o patch -p
Output:
2026-01-17 12:00:01 : Starting AIX OS patching for my-aix-host
2026-01-17 12:00:02 : PREVIEW: ssh my-aix-host mkdir -p /mnt
2026-01-17 12:00:02 : PREVIEW: ssh my-aix-host mount aixnimserver:/exports/software/aix_72.05.10 /mnt
2026-01-17 12:00:03 : PREVIEW: ssh my-aix-host alt_disk_copy -d hdisk2 -P1
2026-01-17 12:00:03 : PREVIEW: ssh my-aix-host alt_disk_copy -d hdisk2 -P23 -l /mnt -b update_all
2026-01-17 12:00:04 : PREVIEW: ssh my-aix-host alt_root_op -W -d hdisk2
2026-01-17 12:00:04 : PREVIEW: ssh my-aix-host chroot /alt_inst oslevel -s
2026-01-17 12:00:05 : PREVIEW: ssh my-aix-host chroot /alt_inst lppchk -vm3
2026-01-17 12:00:05 : PREVIEW: ssh my-aix-host bootlist -m normal hdisk2
2026-01-17 12:00:05 : PREVIEW: ssh my-aix-host bootlist -m normal -o
2026-01-17 12:00:06 : PREVIEW: ssh my-aix-host alt_root_op -S -d hdisk2
2026-01-17 12:00:06 : PREVIEW: ssh my-aix-host umount /mnt
2026-01-17 12:00:06 : Dry-run commands saved in: logs/my-aix-host.dryrun.cmds
Sample Run — Full Upgrade
# ./aix_os_patch-one-host.ksh -h my-aix-host -o patch -f
Output:
2026-01-17 12:10:01 : Starting AIX OS patching for my-aix-host
2026-01-17 12:10:02 : EXEC: ssh my-aix-host mkdir -p /mnt
2026-01-17 12:10:02 : EXEC: ssh my-aix-host mount aixnimserver:/exports/software/aix_72.05.10 /mnt
2026-01-17 12:10:03 : EXEC: ssh my-aix-host alt_disk_copy -d hdisk2 -P1
2026-01-17 12:10:10 : EXEC: ssh my-aix-host alt_disk_copy -d hdisk2 -P23 -l /mnt -b update_all
2026-01-17 12:10:20 : EXEC: ssh my-aix-host alt_root_op -W -d hdisk2
2026-01-17 12:10:21 : EXEC: ssh my-aix-host chroot /alt_inst oslevel -s
2026-01-17 12:10:22 : EXEC: ssh my-aix-host chroot /alt_inst lppchk -vm3
2026-01-17 12:10:22 : EXEC: ssh my-aix-host bootlist -m normal hdisk2
2026-01-17 12:10:23 : EXEC: ssh my-aix-host bootlist -m normal -o
2026-01-17 12:10:23 : EXEC: ssh my-aix-host alt_root_op -S -d hdisk2
2026-01-17 12:10:24 : EXEC: ssh my-aix-host umount /mnt
2026-01-17 12:10:24 : AIX OS patching completed successfully for my-aix-host
2026-01-17 12:10:24 : Manual reboot required to activate new rootvg
Conclusion
This production-ready script allows safe, automated AIX OS patching with:
###############################################################################
set -o errexit
set -o nounset
set -o pipefail 2>/dev/null || true
###############################################################################
# GLOBALS
###############################################################################
SCRIPT_NAME=$(basename "$0")
BASE_DIR=$(cd "$(dirname "$0")" && pwd)
LOG_DIR="${BASE_DIR}/logs"
SSH="ssh -o BatchMode=yes -o ConnectTimeout=10"
PREVIEW=1
FORCE=0
OPERATIONS=""
TARGET_DISK=""
HOST=""
# NFS / ALT ROOTVG SETTINGS
NFS_SERVER="aixnimserver"
NFS_EXPORT="/exports/software/aix_72.05.10"
NFS_MOUNT="/mnt"
ALT_MOUNT="/alt_inst"
mkdir -p "$LOG_DIR"
###############################################################################
# HELP
###############################################################################
show_help() {
cat <<EOF
Patch One AIX Host (Alternate Rootvg Method)
Usage:
$SCRIPT_NAME -h <hostname> -o patch [options]
Required:
-h hostname Target AIX system
-o patch Perform OS patching
Optional:
-d disk Disk for alternate rootvg
-p Preview mode (default)
-f Force execution
--help Show help
Notes:
* Preview mode makes NO changes
* Force mode performs OS patching
* Reboot is MANUAL after completion
EOF
exit 0
}
###############################################################################
# LOGGING
###############################################################################
log_init() {
LOG_FILE="${LOG_DIR}/${HOST}.log"
DRYRUN_FILE="${LOG_DIR}/${HOST}.dryrun.cmds"
exec > >(tee -a "$LOG_FILE") 2>&1
: > "$DRYRUN_FILE"
}
log() { print "$(date '+%Y-%m-%d %H:%M:%S') : $*" ; }
fatal() { log "FATAL: $*" ; cleanup ; exit 1 ; }
queue_cmd() { print "$1" >> "$DRYRUN_FILE" ; }
run_cmd() {
CMD="$1"
if [[ "$PREVIEW" -eq 1 ]]; then
log "PREVIEW: $CMD"
queue_cmd "$CMD"
else
log "EXEC: $CMD"
eval "$CMD"
fi
}
###############################################################################
# CLEANUP / ROLLBACK
###############################################################################
cleanup() {
log "Running cleanup"
run_cmd "$SSH $HOST umount $NFS_MOUNT || true"
run_cmd "$SSH $HOST alt_root_op -X altinst_rootvg || true"
}
trap cleanup ERR
###############################################################################
# ARGUMENT PARSING
###############################################################################
for arg in "$@"; do
[[ "$arg" = "--help" ]] && show_help
done
while getopts "h:o:d:pf" opt; do
case "$opt" in
h) HOST="$OPTARG" ;;
o) OPERATIONS="$OPTARG" ;;
d) TARGET_DISK="$OPTARG" ;;
p) PREVIEW=1 ;;
f) PREVIEW=0; FORCE=1 ;;
*) show_help ;;
esac
done
[[ -z "$HOST" || "$OPERATIONS" != "patch" ]] && show_help
log_init
log "Starting AIX OS patching for $HOST"
###############################################################################
# PRE-FLIGHT VALIDATION
###############################################################################
[[ "$(id -u)" -ne 0 ]] && fatal "Must be run as root"
ping -c 2 "$HOST" >/dev/null || fatal "Ping failed"
$SSH "$HOST" "true" || fatal "SSH failed"
OS=$($SSH "$HOST" uname -s)
[[ "$OS" != "AIX" ]] && fatal "Target OS is not AIX"
$SSH "$HOST" "command -v alt_disk_copy" >/dev/null || fatal "alt_disk_copy not found"
###############################################################################
# SAFE DISK DISCOVERY
###############################################################################
discover_disk() {
$SSH "$HOST" "
bootdisk=\$(bootinfo -b)
rootsz=\$(lsvg rootvg | awk '/TOTAL PPs/ {print \$3 * \$6}')
lspv | while read d p v; do
if [[ \"\$v\" = \"None\" && \"\$d\" != \"\$bootdisk\" ]]; then
size=\$(bootinfo -s \$d)
[[ \$size -ge \$rootsz ]] && echo \$d
fi
done | head -1
"
}
[[ -z "$TARGET_DISK" ]] && TARGET_DISK=$(discover_disk)
[[ -z "$TARGET_DISK" ]] && fatal "No suitable free disk found"
log "Target disk selected: $TARGET_DISK"
###############################################################################
# HANDLE ROOTVG UNMIRROR
###############################################################################
handle_rootvg_mirror() {
log "Checking if $TARGET_DISK is part of rootvg mirror"
MIRROR=$($SSH "$HOST" "lspv $TARGET_DISK" | awk '/mirror/ {print $1}')
if [[ -n "$MIRROR" ]]; then
log "Breaking mirror on $TARGET_DISK"
run_cmd "$SSH $HOST unmirrorvg rootvg $TARGET_DISK"
run_cmd "$SSH $HOST reducevg -df rootvg $TARGET_DISK"
run_cmd "$SSH $HOST chpv -c $TARGET_DISK"
run_cmd "$SSH $HOST bootlist -m normal -o"
fi
}
###############################################################################
# CLEANUP EXISTING ALT ROOTVG
###############################################################################
cleanup_alt_rootvg() {
log "Checking if altinst_rootvg exists on $HOST"
EXISTS=$($SSH "$HOST" "lsvg altinst_rootvg >/dev/null 2>&1; echo \$?")
if [[ "$EXISTS" -eq 0 ]]; then
log "altinst_rootvg exists — removing it before OS patching"
run_cmd "$SSH $HOST alt_root_op -X altinst_rootvg"
log "Existing altinst_rootvg removed successfully"
else
log "No existing altinst_rootvg found — ready to use $TARGET_DISK"
fi
}
###############################################################################
# PATCHING STEPS
###############################################################################
mount_nfs_repo() {
log "Mounting NFS repository"
run_cmd "$SSH $HOST mkdir -p $NFS_MOUNT"
run_cmd "$SSH $HOST mount ${NFS_SERVER}:${NFS_EXPORT} $NFS_MOUNT"
}
alt_clone_phase1() {
log "Creating alternate rootvg (Phase 1)"
run_cmd "$SSH $HOST alt_disk_copy -d $TARGET_DISK -P1"
}
alt_emgr_commit_lppchk() {
log "Applying Emergency Fixes (EMGR) to alternate rootvg"
# Apply all EMGR fixes in priority order
run_cmd "$SSH $HOST chroot $ALT_MOUNT /usr/sbin/emgr -P"
log "Checking for applied EMGR packages to remove"
EMGR_PACKAGES=$($SSH "$HOST" chroot $ALT_MOUNT /usr/sbin/emgr -P | awk '{print $1}' | tail -n +2)
# Explanation: - awk '{print $1}' → get first column (fix IDs)
# tail -n +2 → skip header line
for fix in $EMGR_PACKAGES; do
log "Removing EMGR package: $fix"
run_cmd "$SSH $HOST chroot $ALT_MOUNT /usr/sbin/emgr -r -L $fix"
done
log "Committing all applied filesets on alternate rootvg"
run_cmd "$SSH $HOST chroot $ALT_MOUNT /usr/sbin/installp -c all"
log "Running final LPP check (level 3) on alternate rootvg"
run_cmd "$SSH $HOST chroot $ALT_MOUNT /usr/bin/lppchk -vm3"
}
alt_clone_phase23() {
log "Applying TL/SP (Phase 2/3)"
run_cmd "$SSH $HOST alt_disk_copy -d $TARGET_DISK -P23 -l $NFS_MOUNT -b update_all"
}
verify_alt_rootvg() {
log "Waking alternate rootvg"
run_cmd "$SSH $HOST alt_root_op -W -d $TARGET_DISK"
log "OS level on alternate rootvg"
run_cmd "$SSH $HOST chroot $ALT_MOUNT /usr/bin/oslevel -s"
log "Final lppchk"
run_cmd "$SSH $HOST chroot $ALT_MOUNT /usr/bin/lppchk -vm3"
}
switch_bootlist() {
log "Switching bootlist to alternate rootvg"
run_cmd "$SSH $HOST bootlist -m normal $TARGET_DISK"
run_cmd "$SSH $HOST bootlist -m normal -o"
}
sleep_alt_rootvg() {
log "Sleeping alternate rootvg"
run_cmd "$SSH $HOST alt_root_op -S -d $TARGET_DISK"
}
###############################################################################
# EXECUTION
###############################################################################
mount_nfs_repo
handle_rootvg_mirror
cleanup_alt_rootvg
alt_clone_phase1
alt_emgr_commit_lppchk
alt_clone_phase23
verify_alt_rootvg
switch_bootlist
sleep_alt_rootvg
run_cmd "$SSH $HOST umount $NFS_MOUNT"
###############################################################################
# FINAL
###############################################################################
log "AIX OS patching completed successfully for $HOST"
log "Manual reboot required to activate new rootvg"
[[ "$PREVIEW" -eq 1 ]] && log "Dry-run commands saved in: $DRYRUN_FILE"
exit 0
Sample Run — Preview Mode
# ./aix_os_patch-one-host.ksh -h my-aix-host -o patch -p
Output:
2026-01-17 12:00:01 : Starting AIX OS patching for my-aix-host
2026-01-17 12:00:02 : PREVIEW: ssh my-aix-host mkdir -p /mnt
2026-01-17 12:00:02 : PREVIEW: ssh my-aix-host mount aixnimserver:/exports/software/aix_72.05.10 /mnt
2026-01-17 12:00:03 : PREVIEW: ssh my-aix-host alt_disk_copy -d hdisk2 -P1
2026-01-17 12:00:03 : PREVIEW: ssh my-aix-host alt_disk_copy -d hdisk2 -P23 -l /mnt -b update_all
2026-01-17 12:00:04 : PREVIEW: ssh my-aix-host alt_root_op -W -d hdisk2
2026-01-17 12:00:04 : PREVIEW: ssh my-aix-host chroot /alt_inst oslevel -s
2026-01-17 12:00:05 : PREVIEW: ssh my-aix-host chroot /alt_inst lppchk -vm3
2026-01-17 12:00:05 : PREVIEW: ssh my-aix-host bootlist -m normal hdisk2
2026-01-17 12:00:05 : PREVIEW: ssh my-aix-host bootlist -m normal -o
2026-01-17 12:00:06 : PREVIEW: ssh my-aix-host alt_root_op -S -d hdisk2
2026-01-17 12:00:06 : PREVIEW: ssh my-aix-host umount /mnt
2026-01-17 12:00:06 : Dry-run commands saved in: logs/my-aix-host.dryrun.cmds
Sample Run — Full Upgrade
# ./aix_os_patch-one-host.ksh -h my-aix-host -o patch -f
Output:
2026-01-17 12:10:01 : Starting AIX OS patching for my-aix-host
2026-01-17 12:10:02 : EXEC: ssh my-aix-host mkdir -p /mnt
2026-01-17 12:10:02 : EXEC: ssh my-aix-host mount aixnimserver:/exports/software/aix_72.05.10 /mnt
2026-01-17 12:10:03 : EXEC: ssh my-aix-host alt_disk_copy -d hdisk2 -P1
2026-01-17 12:10:10 : EXEC: ssh my-aix-host alt_disk_copy -d hdisk2 -P23 -l /mnt -b update_all
2026-01-17 12:10:20 : EXEC: ssh my-aix-host alt_root_op -W -d hdisk2
2026-01-17 12:10:21 : EXEC: ssh my-aix-host chroot /alt_inst oslevel -s
2026-01-17 12:10:22 : EXEC: ssh my-aix-host chroot /alt_inst lppchk -vm3
2026-01-17 12:10:22 : EXEC: ssh my-aix-host bootlist -m normal hdisk2
2026-01-17 12:10:23 : EXEC: ssh my-aix-host bootlist -m normal -o
2026-01-17 12:10:23 : EXEC: ssh my-aix-host alt_root_op -S -d hdisk2
2026-01-17 12:10:24 : EXEC: ssh my-aix-host umount /mnt
2026-01-17 12:10:24 : AIX OS patching completed successfully for my-aix-host
2026-01-17 12:10:24 : Manual reboot required to activate new rootvg
Conclusion
This production-ready script allows safe, automated AIX OS patching with:
- Alternate rootvg creation and TL/SP application
- Rootvg mirror handling
- Existing altinst_rootvg cleanup
- NFS repository mounting
- Preview mode for safe testing before execution