4 votos

¿Cómo funciona este complejo shell BASH script?

Miembro de la Comunidad de Soporte Técnico de Apple Linc Davis desarrolló este comando para ayudar en el diagnóstico de problemas. La salida da una visión general del sistema de uno y es muy similar al programa etrecheck . Pero, lo hace usando un solo comando. Deseo desglosar su funcionamiento ya que gran parte de la sintaxis utilizada no se encuentra en las páginas de MAN. De nuevo, este script es propiedad de Linc Davis. Simplemente deseo 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

5voto

Tony Williams Puntos 4903

Lo primero que hay que entender es que no se trata en realidad de un "comando único", sino de una línea única porque utiliza ';' para separar las líneas de comando en lugar de las nuevas líneas.

Así que lo primero que hay que hacer al intentar entenderlo sería hacerlo más legible para los humanos usando tu editor de texto favorito para sustituir ';' por una nueva línea. Utilicé Textmate y guardé el resultado como 'linc.sh', así que conseguí resaltar la sintaxis. Luego, un juicioso reformateo/interpretación y obtuve esto:

enter image description here

Una vez hecho esto, tendrás un shell script y podrás ver que está usando variables de shell y expansión para construir las opciones antes de ejecutar un comando y luego usando grep, awk y sed para procesar la salida y hacerla más legible antes de repetir todo con otro comando. También hay algunas funciones de shell ahí.

Consigue un bueno libro sobre la programación del bash y con la ayuda de eso y las páginas del manual del bash lo entenderás.

(BTW - esta es una de las razones por las que hago la mayor parte de mi administración de sistemas en IPython, hace mucho más fácil la programación y la lectura del código).

0 votos

Gracias Tony, es una información muy útil. Más concretamente, "Fb/Fm/Fs", por ejemplo, ¿dónde puedo encontrar documentación al respecto? ¿Son variables? Recientemente he comprado O'Reilly "Shell Scripting" y aún no he profundizado completamente en él, pero planeo hacerlo pronto. Gracias de nuevo.

1 votos

Sí, son variables de shell. Lee el libro de O'Reilly de cabo a rabo y seguro que empiezas a entenderlo todo. La programación shell a este nivel es no fácil. Hay un montón de cosas profundas sucediendo allí.

AppleAyuda.com

AppleAyuda es una comunidad de usuarios de los productos de Apple en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X