AIX machine parsable outputs

For single-line outputs, some standardization could be good here, specifically, perhaps adding the -F flag to LVM and VPD queries.

Device commands do have a standardized way to get this:

#################
For lsdev, you can use -F
#################
# lsdev -H -Ccadapter -F 'name;class;subclass;type;location;physloc;description'
name;class;subclass;type;location;physloc;description
ent0;adapter;pciex;df1020e2e304;02-00;U78D2.001.XXXXXXX-P1-C9-T1;PCIe3 4-Port 10GbE SR Adapter (df1020e21410e304)

#################
For lsattr, you can do the same
#################
#lsattr -El sys0 -H -F 'attribute:value:description:user_settable'
attribute:value:description:user_settable

SW_dist_intr:false:Enable SW distribution of interrupts:True
autorestart:true:Automatically REBOOT OS after a crash:True
boottype:disk:N/A:False
capacity_inc:0.01:Processor capacity increment:False
capped:false:Partition is capped:False
chown_restrict:true:Chown Restriction Mode:True
clouddev:0:Recreate ODM devices on next boot:True
conslogin:enable:System Console Login :False
cpuguard:enable:CPU Guard:True


However, VPD is less standardized.


#################
lscfg -vl is brutal to parse, and ODM does not have all of this. You can get useful data with:
#################

# lsvpd | while read type data ; do if [[ "${type}" == "*YL" ]] ; then echo "" ; fi ; echo "$type $data" ; done | more | grep -p fcs0
*YL U78D2.001.XXXXXXX-P1-C9-T4
*FC ????????
*DS PCIe3 4-Port 16Gb FC Adapter (df1000e314101406)
*AX fcs0
*PL 03-00
*CD 10140614
*PN 01FT695
*SN Y050HY95A012
*EC P14609
*CC 578E
*MF 001D
*FN 01FT699
*ZM 3
*Z0 0000000C
*Z1 00000001
*Z2 00000000
*Z3 08090000
*Z4 01000001
*Z5 2E343135
*Z6 2E343135
*Z7 C0022C40
*Z8 20000010XXXXXXXX
*Z9 11.4.415.5
*ZA 11.4.415.5
*ZB 00000000
*ZC 00040000
*ZD 000000FF

In this case, it’s missing “Network Address”, but you can usually convert Z8. This doesn’t work on virtual though. I usually do something more like this to get the data I want:

for fcs in lsdev -C | grep fcs | cut -f 1 -d \ ; do
fscsi=lsdev -p$fcs | grep -i scsi | cut -f 1 -d \ ; hn=hostname;
echo $hostname lscfg -vsl $fcs | egrep 'fcs|Address' | tr . \ | tr -s [:space:] FC ID: lsattr -a scsi_id -F value -El $fscsi ; done

vio2a fcs0 U78AE 001 XXXXXXX-P1-C19-L1-T1 Network Address 10000090FXXXXXXX FC ID: 0x450200
vio2a fcs1 U78AE 001 XXXXXXX-P1-C19-L1-T2 Network Address 10000090FXXXXXXX FC ID: 0x460200

That works on virtual hosts also.


LVM is the worst, and requires transformation


Other than cutting out specific data that you need, the AIX way is to use mkvgdata, and then parse the image.data file it produces.

Alternatively, you can do something like this:

# (lsvg rootvg | cut -c 1-45 ; lsvg rootvg | cut -c 46-999 ) | cut -f 1 -d ( | tr -d \ | tr : \ | while read variable value ; do echo ${variable}=${value} ; done | egrep -v '=$' | sort -r
VOLUMEGROUP=rootvg
VGSTATE=active
VGPERMISSION=read/write
VGIDENTIFIER=00XXXXX00000YYYYY0000ZZZZZZZZZZZ

This same works with lslv, or often you can get key info from “lsvg -l rootvg” or similar.


AIX 2020 PCMPATH Replacement

With AIX PCM, we no longer have pcmpath or datapath.
Most of the info you’d want for disks is from lsmpio or lspath.
For some adapter queries, you’re stuck. Here is a simulated output generator.
This is not super efficient, but it’s on par with the kind of things many AIX scripts do.

pcmpath_query() {
  printf "%-8s %8s %15s %6s %6s %6s\n" Adapter Status Selects Errors Paths Failed 
  for fscsi in $(lsdev -C | grep fscsi | cut -f 1 -d \  ) ; do
    enabled=$(lspath -p $fscsi | grep Enabled | wc -l)
    failed=$(lspath -p $fscsi | grep -v Enabled | wc -l)
    if [[ $(( $enabled + $failed )) -eq 0 ]] ; then status=UNUSED ; 
    elif [[ $failed -eq 0 ]] ; then status=NORMAL 
    elif [[ $enabled -eq 0 ]]; then status=FAILED
    else status=DEGRADED; fi
    fcs=$(lsdev -CFparent -l $fscsi)
    selects=$(fcstat $fcs | grep Requests | tr -d \  | cut -f 2 -d : | paste -sd+ - | bc)
    errors=$(lsmpio -ae  | grep -p $fscsi | grep Total | tr -d \  | cut -f 2 -d : )
    paths=$(lsmpio -ar | grep -p $fscsi | grep 0x | wc -l)
    failed=$(lsmpio -ar | grep -p fscsi0 | grep 0x | awk '{print $3 "\n" $4 "\n" $5;}' | paste -sd+ - | bc)
    printf "%-8s %8s %15s %6s %6s %6s\n" $fscsi $status $selects $errors $paths $failed
  done
}

AIX JFS2 autoresize

computersarefun put in a request for AIX to auto-grow/shrink filesystems.
Ref: https://www.ibm.com/developerworks/rfe/execute?use_case=viewRfe&CR_ID=114789

This seems more like a monitoring thing than an operating system thing.
Also, handling this as a thin LUN is probably better where possible.
Here is an example script.

Potential improvements:
* Notifications on exceptions
* Config file to track different settings per filesystem
* Also check iused / ifree to handle tiny-files
* Run as a daemon vs from cron.
* Explicit lists of filesystems, or include/exclude lists

#!/bin/ksh
###########
# Run this from cron every minute to automatically resize JFS2 filesystems
# Incorrect limits could cause size flapping for small filesystems.
# We skip things we cannot reduce.

MINFREEPCT=10
MAXFREEPCT=70
MINPPFREE=10

LVLIST=`mount | grep jfs2 | grep /dev/ | awk ‘{print $1;}’ | cut -f 3 -d /`
for lv in $LVLIST ; do
df -gv 2>/dev/null | grep $lv | read device size used free pct iused ifree ipct mountpoint || continue
FREEPCT=$(( $used * 100 / $size ))
VG=`lslv $lv 2>/dev/null | grep “VOLUME GROUP:” | awk ‘{print $6;}’`
PPSIZE=`lsvg $VG 2>/dev/null | grep ‘PP SIZE’ | awk ‘{print $6;}’`
[[ $PPSIZE -gt 0 ]] || continue
#
if [[ $FREEPCT -lt $MINFREEPCT ]] ; then
FREEPPS=`lsvg $VG | grep FREE | awk ‘{print $6;}’`
[[ $FREEPPS -gt $MINFREEPPS ]] && chfs -a size=+1 $mountpoint
continue
fi
#
[[ $FREEPCT -gt $MAXFREEPCT ]] && chfs -a size=-$PPSIZE $mountpoint
#
done