¿Cómo funciona este script de shell BASH complejo?

4

El miembro de la Comunidad de soporte de Apple Linc Davis desarrolló este comando para ayudar a diagnosticar problemas. La salida proporciona una visión general del sistema y es muy similar al programa etrecheck . Pero, lo hace usando un solo comando. Deseo desglosar cómo funciona, ya que gran parte de la sintaxis utilizada no se puede encontrar en las páginas MAN. Una vez más, este guión es propiedad de Linc Davis. Simplemente quiero entender cómo se ejecuta. Gracias de antemano.

  

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

    
pregunta njboot 08.05.2014 - 04:37

1 respuesta

5

Lo primero que hay que entender es que no es en realidad un "comando único", es una sola línea solo porque usa ';' para separar las líneas de comando en lugar de nuevas líneas.

Por lo tanto, lo primero que debe hacer cuando intente comprenderlo sería hacerlo más legible para el ser humano utilizando su editor de texto favorito para reemplazar ';' con una nueva linea. Usé Textmate y guardé el resultado como 'linc.sh', así que obtuve resaltado de sintaxis. Luego un poco de cambio de formato / bonito y tuve esto:

Una vez que hayas hecho eso, tendrás un script de shell y podrás ver que está utilizando las variables de shell y la expansión para crear las opciones antes de ejecutar un comando y luego usar grep, awk y sed para procesar y generar más. legible antes de repetir todo con otro comando. También hay algunas funciones de shell allí.

Obtenga un buen libro sobre programación de bash y con la ayuda de eso y las páginas de manual de bash lo entenderá.

(Por cierto, esta es una de las razones por las que hago la mayor parte de la administración de mi sistema en IPython, lo que facilita la programación y el código legible.)

    
respondido por el Tony Williams 08.05.2014 - 07:05

Lea otras preguntas en las etiquetas