#!/bin/bash # # Script um die Laufzeit von Befehlszeilen auszuwerten. # # # laufzeit_messer.sh -b BEFEHLSDATEI [-d DURCHLAEUFE] [-a AUSGABEDATEI] [-g AUSGABEGROESSE] [-t] [--help] versioN='V 0.02' # Pfad in dem das Script liegt script_pfad="$(dirname `readlink -f $0`)" # Befehl zum Zeitmessen time_befehl="time" time_optionen="-fuser %U\nreal %e\nsys %S" # Wichtig! ^^^^^^ ^^^^^ ^^^^^ # Ausgabedatei ausgabedatei="$script_pfad/ausgabe.txt" # Temppfad temppfad="/tmp/" # Tempdatei tempdatei="$(mktemp -p "$temppfad" laufzeitmesser.XXXXXX)" # Datei fuer den Groessentest groessentestdatei="$(mktemp -p "$temppfad" laufzeitmesser_hash.XXXXXX)" groesse_fuer_groessentest=0 # Name fuer die Sammeldateien werte_sammeldatei="$temppfad/LM-wERte" # Name der Befehlsdatei befehlsdatei= befehls_arbeitsdatei="$temppfad/LM-bEFehle" # Anzahl der Durchlaeufe pro Befehl anzahl_durchlaeufe=10 anzahl_chars=10000 # Terminal zu ausfuehrung der Befehlszeilen terminal='xterm -e' # Kein extra Terminalfenster oeffnen kein_fenster=true # Funktionen ------------------------------------------------------------------- function Hilfe # ($1=Scriptname) { echo echo "${1##*/} -b BEFEHLSDATEI [-d DURCHLAEUFE] [-a AUSGABEDATEI] [-g AUSGABEGROESSE] [-t] [-h / --help]" echo -e '\n' echo "-b BEFEHLSDATEI | In dieser Datei befinden sich die Befehle, deren Laufzeit" echo " | gemessen werden sollen." echo " | (Leerzeilen und Kommentarzeilen erlaubt.)" echo " |" echo "-d DURCHLAEUFE | Anzahl, wie oft jede Befehlszeile getestet werden soll." echo " | (Vorgabe=$anzahl_durchlaeufe)" echo " |" echo "-a AUSGABEDATEI | In dieser Datei werden die Ergebnisse zusammengefasst." echo " | (Vorgabe=$ausgabedatei)" echo " |" echo "-g HASH | Hash der erwarteten ausgabe." echo " |" echo "-t | Fuer jeden Test ein extra Terminalfenster (${terminal%% *})" echo " | oeffnen in dem der Befehl ablaeuft. (Vorgabe=`$kein_fenster && echo nein || echo ja`)" echo " |" echo "-n NUMEROF# | Die Menge der #, die ein Befehl ausgeben muss." echo echo "$versioN" echo exit 0 } function hash { sha256sum "$1" | head | head -c 64 } function Zeit_messen # ($1=befehl, $2=zeilennummer) { local nochmal_fragen=true for d in `seq $anzahl_durchlaeufe` do printf '%4i/%i \r' $d $anzahl_durchlaeufe if $kein_fenster then echo "$befehl 2>/dev/null" >"$tempdatei" $time_befehl "$time_optionen" -ao "$werte_sammeldatei.`printf '%05i' $2`" /bin/bash "$tempdatei" >"$groessentestdatei" else echo "$befehl 2>/dev/null |tee $groessentestdatei" >"$tempdatei" $terminal $time_befehl "$time_optionen" -ao "$werte_sammeldatei.`printf '%05i' $2`" /bin/bash "$tempdatei" fi if $nochmal_fragen && test -n "$groesse_fuer_groessentest" then if test $(hash "$groessentestdatei") != "$groesse_fuer_groessentest" then echo -e "\aDie Ausgabe ist nicht korrekt!\nSoll = \"${groesse_fuer_groessentest}\"\nIst = \"`hash "$groessentestdatei"`\"" read -sn1 -p 'Script beenden (j/n/N) (ja / nein / Nicht nochmal fragen fuer diesen Befehl)' case "$REPLY" in 'j')Ende;; 'N')nochmal_fragen=false;; esac test -e "$groessentestdatei" && rm "$groessentestdatei" echo fi fi done } function Ende # ($1=leer=normal $1=Abbruch=Abruch durch benutzer) { test "$1" == "Abbruch" && echo -ne "\n\nAbbruch durch benutzer!" echo -e "\nRaeume auf..." test -e "$befehls_arbeitsdatei" && rm "$befehls_arbeitsdatei" test -e "$tempdatei" && rm "$tempdatei" test -e "$groessentestdatei" && rm "$groessentestdatei" test -e "$werte_sammeldatei.00001" && rm $werte_sammeldatei.[0-9][0-9][0-9][0-9][0-9] test -e "$temppfad" && test -n "$madedir" && rmdir "$temppfad" echo -e "Fertig.\n" exit 0 } # Optionen auswerten ----------------------------------------------------------- test -z "$1" && Hilfe "$0" while test -n "$1" do case "${1:0:2}" in '-b') # Befehlsdatei if test -n "${1:2}" then befehlsdatei="${1:2}" else shift befehlsdatei="$1" fi ;; '-a') # Ausgabedatei if test -n "${1:2}" then ausgabedatei="${1:2}" else shift ausgabedatei="$1" fi ;; '-n') # Durchlaeufe if test -n "${1:2}" then anzahl_chars="${1:2}" else shift anzahl_chars="$1" fi ;; '-d') # Durchlaeufe if test -n "${1:2}" then anzahl_durchlaeufe="${1:2}" else shift anzahl_durchlaeufe="$1" fi ;; '-g') # Ausgabegroessentest if test -n "${1:2}" then groesse_fuer_groessentest="${1:2}" else shift groesse_fuer_groessentest="$1" fi ;; '-t') kein_fenster=false ;; *) Hilfe "$0" ;; esac shift done # Optionen testen echo -e "\nTeste Optionen...\n" # Befehlsdatei if ! test -s "$befehlsdatei" then echo -e "\aBefehlsdatei >$befehlsdatei< existiert nicht oder ist leer!" exit 1 fi # Ausgabedatei if test -e "$ausgabedatei" then echo -e "\aAusgabedatei >$ausgabedatei< existiert bereits!\nUeberschreiben (j/n)" read -sn1 test "$REPLY" != 'j' && exit 1 rm "$ausgabedatei" fi # Anzahl der Durchlaeufe if test -n "`tr -d '[:digit:]' <<<$anzahl_durchlaeufe`" then echo -e "\aAnzahl der Durchlaeufe >$anzahl_durchlaeufe< enthaelt ungueltige Zeichen!" exit 1 fi if test $anzahl_durchlaeufe -lt 0 then echo -e "\aAnzahl der Durchlaeufe >$anzahl_durchlaeufe< muss min. 1 sein!" exit 1 fi # Hauptteil #################################################################### # [strg]+c und "Fenster schliessen" abfangen um noch ordentlich aufzuraeumen trap 'Ende Abbruch' 1 2 # Temppfad anlegen if test ! -d "$temppfad" then madedir=true; mkdir "$temppfad" fi # Befehlsdatei saeubern (leere Zeilen und Zeilen mit einem # am Anfang entfernen) grep -ve '^$' -e '^#' "$befehlsdatei" >"$befehls_arbeitsdatei" # Laufzeit der Befehle messen echo -e "\nLaufzeiten der Befehle werden gemessen...\n" anzahl_der_befehle=`wc -l <"$befehls_arbeitsdatei"` zeile=1 for zeile in `seq $anzahl_der_befehle` do befehl="`ed -s "$befehls_arbeitsdatei" <<<$zeile 2>/dev/null | sed s,%numcharsHX,$anzahl_chars,1`" echo "[Zeile $zeile von $anzahl_der_befehle] $befehl" Zeit_messen "$befehl" "$zeile" done echo " " # Zeiten mitteln echo -e "\nDurchschnitt der Zeiten werden ermittelt...\n" for zeile in `seq $anzahl_der_befehle` do z0=`printf '%05i' $zeile` sort -g $werte_sammeldatei.$z0|uniq >"$tempdatei" user=( `grep -e 'user' "$tempdatei" |cut -b6-` ) echo -n "user " >"$werte_sammeldatei.$z0" echo "scale=6;(`tr ' ' '+' <<<${user[*]}`)/${#user[*]}"|bc >>"$werte_sammeldatei.$z0" real=( `grep -e 'real' "$tempdatei" |cut -b6-` ) echo -n "real " >>"$werte_sammeldatei.$z0" echo "scale=6;(`tr ' ' '+' <<<${real[*]}`)/${#real[*]}"|bc >>"$werte_sammeldatei.$z0" sys=( `grep -e 'sys' "$tempdatei" |cut -b6-` ) echo -n "sys " >>"$werte_sammeldatei.$z0" echo "scale=6;(`tr ' ' '+' <<<${sys[*]}`)/${#sys[*]}"|bc >>"$werte_sammeldatei.$z0" done # Ausgabe erstellen echo -e "\nErstelle Ausgabedatei >$ausgabedatei<\n" echo "Jeder Befehl wurde $anzahl_durchlaeufe mal ausgefuehrt." >"$ausgabedatei" yes -|head -n 79|tr -d '\n' >>"$ausgabedatei" echo >>"$ausgabedatei" # Durchschnittszeiten ermitteln test -e "$tempdatei" && rm "$tempdatei" for zeile in `seq $anzahl_der_befehle` do z0=`printf '%05i' $zeile` echo -n "$zeile " >>"$tempdatei" echo "scale=6;(`cut -b6- "$werte_sammeldatei.$z0"|tr '\n' '+'`0)/3"|bc >>"$tempdatei" done # Liste Sortieren sort -nk2 "$tempdatei" -o "$tempdatei" # Ausgabedatei schreiben for zeile in `seq $anzahl_der_befehle` do lesezeile=`ed -s "$tempdatei" <<<$zeile` echo "Platz $zeile:" >>"$ausgabedatei" ed -s "$befehls_arbeitsdatei" <<<${lesezeile%% *} >>"$ausgabedatei" cat "$werte_sammeldatei.`printf '%05i' ${lesezeile%% *}`" >>"$ausgabedatei" yes -|head -n 79|tr -d '\n' >>"$ausgabedatei" echo >>"$ausgabedatei" done Ende