Kleines Bechmark Skript

Deinorius

Commander
Registriert
Juni 2005
Beiträge
2.574
Servus miteinand!

Ich bastle gerade (etwas länger...) an einem Skript, mit dem ich gewisse Befehle mit s-tui benchmarken will. Grundsätzlich werden der Befehl und direkt dahinter s-tui in einem separaten Terminal Fenster ausgeführt (andersherum will nicht). Der while loop soll dafür sorgen, dass solange der erste Befehl noch aktiv ist, nicht unternommen werden soll. checkcp gibt währenddessen cp an, endet dieser erscheint grep und der loop sollte eigentlich erst dann enden, s-tui beenden und das Skript schließen. Mit letzterem sollte ich auch die Dauer des ersten Befehls erhalten.
Sieht derzeit folgendermaßen aus:

Bash:
#!/bin/bash

FSTYPE=ext4

cp -r dasda dahin &
kitty -c NONE s-tui --csv-file ~/Downloads/cptest/cp_$FSTYPE.csv &

sleep 3

checkcp=$(ps aux | grep -w "cp" | awk 'NR==1 {print $11}')

while [[ $checkcp == "cp" ]] ; do
   echo "It's there"
   if [[ $checkcp != "cp" ]] ; then
      break
   fi
pkill s-tui
echo "Not there"
sleep 1
done
exit 1

Die echo Befehle habe ich drin, um feststellen zu können, wo es hakt. Mit unterschiedlichen Varianten (break/continue - while :\n do\n if\n usw.) habe ich entweder beides direkt hintereinander wiederholend oder nur zweiteres wiederholend. s-tui wird beendet, aber praktisch sobald sleep 3 abgeschlossen ist, also der loop im Grunde nicht wartet.
checkcp passt hingegen, ich habe keine Ahnung, woran es liegen kann. Weiß jemand eine bessere Option?
 
Zuletzt bearbeitet:
Ich hab zwar nicht wirklich Ahnung, aber ich würde als erstes tippen, dass du ein paar && oder ; einfügen musst.

Z.B. hinter sleep 3 würde ich ein && einsetzen, damit der nächste Befehl erst ausgeführt wird, wenn die 3 Sekunden um sind.
 
Meinst du mit nächsten Befehl den while loop? Der wird eh erst nach 3 s ausgeführt. Daran liegt es nicht. Ohne sleep würde das noch weniger funktionieren.
Wo wären && bzw. ; denn noch nötig?
 
So wie ich das verstehe sollte hinter jeden Befehl eines von beiden stehen (unter anderen möglichen). && bewirkt, dass der nächste Befehl nur ausgeführt wird, wenn der vorangegangene erfolgreich ausgeführt wurde, ; bewirkt, dass der nächste Befehl auch ohne erfolgreiche Beendigung des vorangegangenen ausgeführt wird.

Wie gesagt, wirklich Ahnung habe ich selber nicht. Aber wenn du schon an solche eher komplexeren Scripte denkst, dann solltest du das auf jeden Fall mal selbst genauer nachschlagen.

Ich dachte nur, dass der Ansatz dich vielleicht auf die richtige Fährte führt.
 
Ich danke dir natürlich, aber ich haben kein Problem mit der Ausführung der Befehle. Das habe ich schon gelöst.
Mein Problem ist beim while loop. Es müsste eigentlich gehen, tut es aber nicht. Der loop lässt sich so erklären.

$checkcp zeigt an, ob cp, also der Kopiervorgang, aktiv ist. Ist das der Fall, wird cp angegeben. Wenn dem nicht mehr so ist, ist es grep.
Also: Während cp da ist, mach nichts bzw. gib It's there an. Das Nichtsmachen wird durch einen Doppelpunkt angegeben.
Ändert sich die Lage, wird cp also nicht angezeigt, brich den loop ab und beende den Prozess s-tui und beende das Skript.
 
Ok. Nur ein Gedanke noch. Sollte die Schleife nicht auch funktionieren, wenn man sie vereinfacht?

Code:
checkcp=$(ps aux | grep -w "cp" | awk 'NR==1 {print $11}')

while [[ $checkcp == "cp" ]]
do
   echo "It's there"
done

pkill s-tui
echo "Not there"
 
gio127 schrieb:
Z.B. hinter sleep 3 würde ich ein && einsetzen, damit der nächste Befehl erst ausgeführt wird, wenn die 3 Sekunden um sind.
Nein, das Skript geht erst weiter, wenn sleep vorbei ist. && ist nicht nötig.

Deinorius schrieb:
Es müsste eigentlich gehen, tut es aber nicht.
Nein, müsste nicht. Denn:

Deinorius schrieb:
$checkcp zeigt an, ob cp, also der Kopiervorgang, aktiv ist. Ist das der Fall, wird cp angegeben. Wenn dem nicht mehr so ist, ist es grep.
Du weist $checkcp nur ein einziges Mal etwas zu, und zwar vor der Schleife. Du änderst aber innerhalb der Schleife nicht dessen Inhalt, folglich wird sich nie etwas an der Schleifenbedinung ändern.
Außerdem prüfst du auf einen cp-Befehl. Wo kommt der überhaupt her, von kitty?

Vielleicht solltest du auch das grep-Konstrukt etwas robuster gestalten. Zum Beispiel mit pgrep, das nur im eigentlichen Kommando sucht:
Code:
while pgrep -x cp > /dev/null; do
  sleep 1
done
pkill s-tui
Kein if und break oder so nötig.
 
  • Gefällt mir
Reaktionen: Deinorius und gio127
Uridium schrieb:
Setze ein set -x zum debuggen.
Danke für den Hinweis, das hilft auf alle Fälle allgemein. Ich kenne noch lange nicht alle Befehle.

Donnerkind schrieb:
Du weist $checkcp nur ein einziges Mal etwas zu, und zwar vor der Schleife.
Inwiefern? Vor der Schleife gebe ich an, was checkcp sein soll, die eigentliche Ausführung beginnt erst mit der Schleife? Mit dem darauffolgenden Satz hast du natürlich recht.
Auch hatte ich das Problem, dass die Abfrage von checkcp so schnell abgelaufen ist, dass 1 Thread komplett ausgelastet wurde und das hätte den Benchmark völlig verfälscht.

Donnerkind schrieb:
Außerdem prüfst du auf einen cp-Befehl. Wo kommt der überhaupt her, von kitty?
Steht am Anfang des Skriptes.

Donnerkind schrieb:
Vielleicht solltest du auch das grep-Konstrukt etwas robuster gestalten. Zum Beispiel mit pgrep, das nur im eigentlichen Kommando sucht:
Ha! Danke! Jetzt klappt es! Ich kannte pgrep noch gar nicht. Das hätte einige Stunden Recherche verkürzt.
Jetzt läuft es genauso, wie ich es von Anfang an wollte.
 
Deinorius schrieb:
Inwiefern? Vor der Schleife gebe ich an, was checkcp sein soll, die eigentliche Ausführung beginnt erst mit der Schleife?
Du hast in der Zuweisung stehen, dass die Ausgabe des Befehls in $() an checkcp übergeben wird. Und zwar zu genau diesem Zeitpunkt der Ausführung. Ab da wird mit $checkcp nur noch auf diesen Ausgabe-Text referenziert, aber der Befehl nicht mehr ausgeführt. Wenn du das jedes Mal ausführen willst, dann musst der $()-Teil auch tatsächlich nach dem while stehen. Eine Alternative ist, den Text in den Klammern der Variablen zuzuweisen und diesen dann mit eval auszuwerten. Eval nimmt einen String entgegen und führt ihn aus, was ja im Prinzip genau das ist, was du ursprünglich erreichen wolltest. Folgender Code ist ungetestet, ich habe selber noch nie wirklich mit eval gearbeitet:
Bash:
checkcp="ps aux | grep -w 'cp' | awk 'NR==1 {print $11}'"
...
if [ eval "$checkcp" = "grep" ] ...

Oder, und das ist viel eleganter und expliziter, du packst es in eine Funktion:
Bash:
checkcp() {
  local result=$(ps aux | grep -w "cp" | awk 'NR==1 {print $11}')
  [ "$result" = "cp" ] && return 0
  return 1
}

while checkcp; do
  sleep 1
done
Ein Returnwert von 0 bedeutet in einer Shell "OK" und alles ungleich 0 ist ein Fehler. Wenn man etwas mit if oder while auswertet, dann muss das 0 zurückgeben, damit die Bedingung wahr ist.

Deinorius schrieb:
Steht am Anfang des Skriptes.
Das habe ich fast befürchtet. ;-) Dieses cp wird nämlich auch erst komplett ausgeführt und solange das noch am Arbeiten ist, geht dein Skript nicht weiter. D.h. wenn du die Schleife erreichst, ist das cp in jedem Fall nicht mehr aktiv. Du müsstest das cp daher in den Hintergrund schicken mit einem einfachen & hinten dran.
Ergänzung ()

Donnerkind schrieb:
Dieses cp wird nämlich auch erst komplett ausgeführt und solange das noch am Arbeiten ist, geht dein Skript nicht weiter.
Bzw. es kann sein -- je nachdem wie komplex und umfangreich deine zu kopierenden Daten sind --, das der cp-Prozess fertig ist und beendet wird, aber der Kernel im Hintergrund noch die Daten aus dem RAM-Cache auf den Datenträger schreibt.
 
Zurück
Oben