4

Apple Support Community member Linc Davis developed this command to aide in diagnosing issues. The output gives a general overview of one's system and is very similar to the program etrecheck. But, it does so using a single command. I wish to break down how it functions since much of the syntax used cannot be found in the MAN pages. Again, this script is the property of Linc Davis. I simply wish to understand how it executes. Thank you in advance.

clear; shopt -s extglob; Fb='%s\n\t(%s)\n'; Fm='\n%s:\n\n%s\n'; Fs='\n%s: %s\n'; PB="/usr/libexec/PlistBuddy -c Print"; Pm () { [[ "$o" ]] && o=$(sed 's/^/ /' <<< "$o") && printf "$Fm" "$1" "$o"; }; Pc () { o=$(egrep -v '^[[:blank:]]*($|#)' "$2"); Pm "$1"; }; Pp () { o=$($PB "$2" | awk -F'= ' \/$3'/{print $2}'); Pm "$1"; }; Ps () { o="${o##+( )}"; [[ "$o" -ne 0 ]] && printf "$Fs" "$1" "$o"; }; a=$(id | grep -w '80(admin)'); r=1; [[ "$a" ]] && { sudo true; r=$?; }; { [[ "$a" ]] || echo $'No admin access\n'; [[ "$a" && "$r" -ne 0 ]] && echo $'No root access\n'; system_profiler SPSoftwareDataType | sed '8!d;s/^ *//'; o=$(system_profiler SPDiagnosticsDataType | sed '5,6!d'); fgrep -q P <<< "$o" && o=; Pm "POST"; o=$(nvram boot-args | awk '{$1=""; print}'); Ps "boot-args"; o=$(df -m / | awk 'NR==2 {print $4}'); [[ $o -lt 5120 ]] && Ps "Free space (MiB)"; o=$(($(vm_stat | awk '/Pageo/{sub("\\.",""); print $2}')/256)); o=$((o>=1024?o:0)); Ps "Pageouts (MiB)"; s=( $(sar -u 1 10 | sed '$!d') ); [[ ${s[4]} -lt 90 ]] && o=$(printf 'User %s%%\t\tSystem %s%%' ${s[1]} ${s[3]}) || o=; Pm "Total CPU usage" && o=$(ps acrx -o comm,ruid,%cpu | sed '2!d'); Pm "Max %CPU by process (name, UID, %)"; o=$(kextstat -kl | grep -v com\\.apple | cut -c53- | cut -d\< -f1); Pm "Loaded extrinsic kernel extensions"; o=$(launchctl list | sed 1d | awk '!/0x|com\.apple|org\.(x|openbsd)|\.[0-9]+$/{print $3}'); Pm "Loaded extrinsic user agents"; o=$(launchctl getenv DYLD_INSERT_LIBRARIES); Pm "Inserted libraries"; for f in crontab fstab launchd.conf sysctl.conf; do Pc $f /etc/$f; done; Pc "hosts" <(sed '1,10d' /etc/hosts); Pc "User crontab" <(crontab -l); Pc "User launchd" ~/.launchd; o=$(find {,/u*/lo*}/e*/periodic -type f -mtime -10d); Pm "Modified periodic scripts"; Pp "Global login items" /L*/P*/loginw* Path; Pp "User login items" L*/P*/*loginit* Name; Pp "Safari extensions" L*/Saf*/*/E*.plist Bundle | sed 's/\..*$//;s/-[1-9]$//'; o=$(find ~ $TMPDIR.. \( -flags +sappnd,schg,uappnd,uchg -o ! -user $UID -o ! -perm -600 \) | wc -l); Ps "Restricted user files"; cd; o=$(find -L /S*/L*/E* {/,}L*/{A*d,Compon,Ex,In,Keyb,Mail/Bu,P*P,Qu,Scripti,Servi,Spo}* -type d -name Contents -prune | while read d; do ID=$($PB\ :CFBundleIdentifier "$d/Info.plist") || ID="No bundle ID"; egrep -qv "^com\.apple\.[^x]|Accusys|ArcMSR|ATTO|HDPro|HighPoint|driver\.stex|hp-fax|\.hpio|JMicron|microsoft\.MDI|print|SoftRAID" <<< $ID && printf "$Fb" "${d%/Contents}" "$ID"; done); Pm "Extrinsic loadable bundles"; o=$(find /u*/{,*/}lib -type f -exec sh -c 'file -b "$1" | grep -qw shared && ! codesign -v "$1"' {} {} \; -print); Pm "Unsigned shared libraries"; o=$(system_profiler SPFontsDataType | egrep "Valid: N|Duplicate: Y" | wc -l); Ps "Font problems"; for d in {/,}L*/{La,Priv,Sta}*; do o=$(ls -A "$d" | egrep -v '\.DS_Store|^com\.apple'); Pm "$d"; done; o=$(ls /L*/L*/Dia*/*.panic | wc -l); Ps "Panics"; o=$(ls /L*/L*/Dia*/*.c* | tail); Pm "System crash logs"; o=$(ls L*/L*/Dia* | tail); Pm "User crash logs"; [[ "$r" -eq 0 ]] && { o=$(sudo profiles -P); Pm "Profiles"; o=$(sudo launchctl list | sed 1d | awk '!/0x|com\.(apple|openssh|vix\.cron)|org\.(amav|apac|calendarse|cups|dove|isc|ntp|post[fg]|x)/{print $3}'); Pm "Loaded extrinsic daemons"; o=$(sudo defaults read com.apple.loginwindow LoginHook); Pm "Login hook"; Pc "Root crontab" <(sudo crontab -l);}; o=$(syslog -F bsd -k Sender kernel -k Message CReq 'GPU |hfs: Ru|I/O e|n Cause: -|NVDA\(|pagin|timed? ?o' | tail -n25 | awk '/:/{$4=""; $5=""; print}'); Pm "Kernel messages"; } 2> /dev/null | pbcopy; exit

1 Answer 1

5

First thing to understand is that it is not actually a "single command", it is a single line only because it uses ';' to separate command lines rather than newlines.

So the first thing to do when attempting to understand it would be to make it more human readable by using your favourite text editor to replace ';' with a newline. I used Textmate and saved the result as 'linc.sh' so I got syntax highlighting. Then some judicious reformatting/prettying and I had this :

enter image description here

Once you've done that you will have a shell script and you can see that it is using shell variables and expansion to build the options before running a command then using grep, awk and sed to process to output and make it more readable before repeating the whole thing with another command. There are also some shell functions in there.

Get a good book on bash programming and with the help of that and the bash manual pages you'll understand it.

(BTW - this is one of the reasons I do as much of my system administration in IPython, makes for much easier programming and readable code.)

2
  • Thank you Tony, this is very helpful information. More specifically, "Fb/Fm/Fs," for example, where do I find documentation on this? Are these variables? I recently purchased O'Reilly: "Shell Scripting" and have yet to completely delve into it, but plan to soon. Thanks again.
    – njboot
    May 8, 2014 at 5:16
  • 1
    Yes, they are shell variables. Read the O'Reilly book from cover to cover and I'm sure you'll start to understand it all. Shell programming at this level is not easy. There's a lot of deep stuff happening in there. May 8, 2014 at 7:18

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .