Wie führe ich einen Befehl mit der Bash-Shell mehrmals aus?

153

Gibt es eine Möglichkeit, einen Befehl (z. B. ps aux|grep someprocess) n- mal auszuführen ?

So etwas wie:

run -n 10  'ps aux|grep someprocess'

Ich möchte es interaktiv nutzen, bitte keine Skripte posten.

Update: Der Grund dafür ist, dass ich auf vielen Rechnern arbeite und nicht alle meine angepassten Skripte usw. in jede Box importieren möchte, um auf allen Rechnern die gleiche Funktionalität zu erhalten.

mahatmanich
quelle

Antworten:

197

Ich glaube nicht, dass es dafür einen Befehl oder eine Shell gibt, da dies eine triviale Teilmenge dessen ist, wofür die Bourne-Shell- forSchleife entwickelt wurde, und die Implementierung eines solchen Befehls selbst daher recht einfach ist.

Für den Anfang können Sie eine Dummy- forSchleife verwenden:

for i in `seq 10`; do command; done

Oder entsprechend dem Vorschlag von JimB, den eingebauten Bash-Code zum Generieren von Sequenzen zu verwenden:

for i in {1..10}; do command; done

Dies wird commandjedes Mal zehnmal wiederholt - es kann sich um eine Pipe oder eine Reihe von Befehlen handeln, die durch ;oder getrennt sind &&. Sie können die $iVariable verwenden, um zu ermitteln, in welcher Iteration Sie sich befinden.

Wenn Sie diesen Einzeiler für ein Skript halten und dies aus einem nicht näher definierten (aber möglicherweise gültigen) Grund unerwünscht ist, können Sie ihn als Befehl implementieren, möglicherweise in etwa so auf Ihrer .bashrc-Datei (ungetestet):

#function run
run() {
    number=$1
    shift
    for i in `seq $number`; do
      $@
    done
}

Verwendungszweck:

run 10 command

Beispiel:

run 5 echo 'Hello World!'
Eduardo Ivanec
quelle
16
@ Mahatmanich, Eine Schleife ist kein Skript. Nichts hindert Sie daran, ... an einem interaktiven Terminal zu verwenden.
Zoredache
3
Nun, der Einzeiler oben ist die Art von Standardmethode und es ist ziemlich einfach. Warum ist es nicht gut für dich? Möglicherweise stellen Sie die falsche Frage? Was ist das Hauptziel Ihrer Skripte oder Ihrer Aktionen, die Sie mehrmals wiederholen möchten? Vielleicht gibt es eine bessere Lösung, wenn wir das Problem anders formulieren.
Patkos Csaba
6
@mahatmanich - for ist die eingebaute Bash zum Iterieren.
JimB
3
@Eduardo Ivanec - Zu Ihrer Information, bash hat eine eingebaute Reichweite wie seq: {1..10}
JimB
1
Es scheint, dass die eingebaute Klammersequenz keine Variablensubstitution unterstützt (siehe stackoverflow.com/a/3737773/713554 ). Die Funktion, die Sie angegeben haben, funktioniert einwandfrei, wenn sie in .bashrcif gestellt {1..$number} ist, wird jedoch gegen if ausgetauscht `seq $number`.
Leo
29

ps aux | grep someprocessSieht so aus, als ob Sie Änderungen eines Programms für eine bestimmte Zeit sehen möchten. Eduardo gab eine Antwort, die Ihre Frage genau beantwortete, aber es gibt eine Alternative watch:

watch 'ps aux | grep someprocess'

Beachten Sie, dass ich den Befehl in einfache Anführungszeichen gesetzt habe, um zu vermeiden, dass die Shell den Befehl als "run watch ps aux" interpretiert und das Ergebnis weiterleitet grep someprocess. Eine andere Möglichkeit, den vorherigen Befehl auszuführen, wäre:

watch ps aux \| grep someprocess

Standardmäßig werden watchalle zwei Sekunden Aktualisierungen durchgeführt, die mit der -nOption geändert werden können . Zum Beispiel, wenn Sie ein Intervall von 1 Sekunde haben wollen:

watch -n 1 'ps aux | grep someprocess'
Lekensteyn
quelle
21

Nur zum Spaß

pgrep ssh ;!!;!!;!!;!!;!!;!!
hdaz
quelle
Kann das bitte jemand erklären? Sieht sehr faszinierend aus.
Daniel Vartanov
4
; ist nur ein Befehlstrennzeichen. !! Wiederholen Sie den letzten Befehl in der Bash. Also starte 'pgrep ssh' und spiele es dann 6 mal ab.
Piotr Kukielka
Das ist zwar lehrreich, aber nicht sehr intuitiv. Einzeiler forscheint der beste Weg. Trotzdem danke für die Antwort.
erm3nda
1
Wird cmd ;!!in einer Zeile nicht einfach der vor der aktuellen Zeile eingegebene Befehl wiederholt ? Es müssten zwei separate historyEinträge sein.
Joel Purra
ersetzen ;mit &&, um beim ersten Ausfall anzuhalten.
User881300
16

Ähnlich wie bei vorherigen Antworten, erfordert jedoch keine for-Schleife:

seq 10 | xargs -I -- echo "hello"

Pipe-Ausgabe von seq an xargs ohne Argumente oder Optionen

nils-holmberg
quelle
2
Dies führt nur eine Ausführung aus echo "hello" 1 2 3 4 5 6 7 8 9 10. Sie müssen xargs mit -n 1für einen Prozess für jede Eingabe (Nummer) und mit -P 10für die parallele Ausführung (10 parallele Prozesse) ausführen. Am Ende mit seq 10 | xargs -n 1 -P 10 echo.
Alexander Klimetschek
16

Versuche dies:

yes ls | head -n5 | bash

Dies setzt voraus, dass der Befehl in einer Sub-Shell ausgeführt wird, was eine leichte Leistungsbeeinträchtigung darstellt. YMMV. Grundsätzlich erhalten Sie den Befehl "yes", um die Zeichenfolge "ls" N-mal zu wiederholen. während "head -n5" die Schleife bei 5 Wiederholungen beendete. Die letzte Pipe sendet den Befehl an die Shell Ihrer Wahl.

Übrigens haben cshähnliche Shells einen eingebauten repeatBefehl. Sie könnten das benutzen, um Ihren Befehl in einer bash-Sub-Shell auszuführen!

android42
quelle
5

POSIX Weg

http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_04_01

x=10
while [ $x -gt 0 ]; do
    command
    x=$(($x-1))
done

Das könnte natürlich zu einem Einzeiler gemacht werden:

x=10; while [ $x -gt 0 ]; do command; x=$(($x-1)); done

und scheint der portabelste Weg zu sein, und daher ist es weniger wahrscheinlich, dass Sie Programme installieren.

Die folgenden sind weniger portabel:

  • Klammererweiterung {1..10}: bash-spezifisch und würde eine große Zeile erzeugen, wenn das Argument groß ist
  • seq: GNU
  • yes: GNU

Und wenn Sie die Portabilität satt haben, ziehen Sie GNU in Betracht parallel:

sudo apt-get install parallel
seq 100 | parallel echo {}

Das führt Befehle parallel aus und hat viele coole Optionen.

Siehe auch: https://stackoverflow.com/questions/169511/how-do-i-iterate-over-a-range-of-numbers-defined-by-variables-in-bash

Ciro Santilli ist ein Schauspieler
quelle
GNU Parallel ist sehr portabel. sh, zsh, kshund bashwerden auf den meisten Plattformen gut unterstützt. csh, tcsh, fishhat etwas Unterstützung. Mithilfe von können parallel --embedSie sogar ein Skript erstellen, das leicht auf ein anderes System verschoben werden kann, auf dem GNU Parallel nicht installiert ist.
Ole Tange
2

Eine Fischschalenimplementierung von @ eduardo-ivanecs runFunktion oben

function run
  set number $argv[1]
  for i in (seq $number)
    eval $argv[2..-1]
  end
end
masukomi
quelle
0

Das wäre 'watch' - sollte Teil fast jedes Unix-Systems sein, das procps verwendet

Sie können Änderungen oder andere interessante Bewegungen in einem System sehen. Zum Beispiel,

watch "df -hP | grep /tmp" 

Setzen Sie einfach Ihre Befehle als Argument (siehe man watch)

Chris Arnu
quelle
Es gibt bereits eine Antwort mit Uhr ... siehe rechts unten ...
Mahatmanich
0

Unter macOS können Sie den repeatBefehl verwenden.

repeat 10 ps aux | grep someprocess
Neil
quelle