Frage Wie führe ich einen Befehl mehrmals mit bash shell aus?


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

So etwas wie:

run -n 10  'ps aux|grep someprocess'

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

Update: Der Grund, warum ich das frage, ist, dass ich an vielen Maschinen arbeite und nicht alle meine Skripte in jede Box importieren möchte, um die gleiche Funktionalität für jeden Rechner zu erhalten.


132
2018-05-24 15:55


Ursprung


Wunderbar, dass die Antwort so viele Upvotes ohne die Frage bekommt, sogar einen zu erhalten. Lass uns das ändern +1 :) - Lekensteyn
@ Lekensteyn danke - mahatmanich
stackoverflow.com/questions/3737740/... - Ciro Santilli 新疆改造中心 六四事件 法轮功


Antworten:


Ich glaube nicht, dass ein Befehl oder eine Shell dafür existiert, da es eine triviale Teilmenge dessen ist, was die Bourne-Shell ist for Loop ist so konzipiert und implementiert einen Befehl wie dieser selbst ist also ziemlich einfach.

Für Anfänger können Sie einen Dummy verwenden for Schleife:

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

Oder äquivalent nach JimBs Vorschlag, den Bash-Butin für das Erzeugen von Sequenzen zu verwenden:

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

Dies iteriert zehn Mal ausgeführt command jedes Mal - es kann eine Pipe oder eine Reihe von Befehlen sein, getrennt durch ; oder &&. Du kannst den ... benutzen $i Variable, um zu wissen, in welcher Iteration Sie sich befinden.

Wenn Sie dieses Einzeiler-Skript betrachten und es aus irgendeinem nicht spezifizierten (aber vielleicht gültigen) Grund unerwünscht ist, können Sie es als Befehl implementieren, vielleicht so etwas in Ihrer .bashrc (ungetestet):

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

Verwendungszweck:

run 10 command

Beispiel:

run 5 echo 'Hello World!'

170
2018-05-24 15:57



@ mahatmanich, Eine Schleife ist kein Skript. Es gibt nichts, was Sie davon abhält, für ... an einem interaktiven Terminal zu verwenden. - Zoredache
Nun, der One-Liner oben ist die Art von Standard-Weg, es zu tun, und es ist ziemlich einfach. Warum ist es nicht gut für dich? Vielleicht fragst du die falsche Frage? Was ist das Hauptziel Ihrer Skripts oder Ihrer Aktionen, die Sie mehrmals wiederholen möchten? Vielleicht gibt es eine bessere Lösung, wenn wir das Problem anders stellen. - Patkos Csaba
@ mahatmanich - for  ist die Bash-Funktion zum Iterieren. - JimB
@ Eduardo Ivanec - FYI, Bash hat eingebaute Reichweite wie seq: {1..10} - JimB
Es scheint, dass die eingebaute Klammersequenz die Variablensubstitution nicht unterstützt (siehe stackoverflow.com/a/3737773/713554). Die Funktion, die Sie angegeben haben, funktioniert perfekt, wenn Sie sie eingeben .bashrc ob {1..$number} wird ausgetauscht `seq $number` obwohl. - Leo


ps aux | grep someprocess Es sieht so aus, als ob Sie Änderungen eines Programms für eine bestimmte Zeit sehen möchten. Eduardo hat eine Antwort gegeben, die genau auf deine Frage antwortet, 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 übergibt grep someprocess. Eine andere Möglichkeit, den vorherigen Befehl auszuführen, wäre:

watch ps aux \| grep someprocess

Standardmäßig, watch wird alle zwei Sekunden aktualisiert, dies kann mit der Taste geändert werden -n Möglichkeit. Zum Beispiel, wenn Sie ein Intervall von 1 Sekunde haben wollen:

watch -n 1 'ps aux | grep someprocess'

29
2018-05-26 15:07



Ja, das funktioniert wie ein Zauber. - Jānis Gruzis


Nur zum Spaß

pgrep ssh ;!!;!!;!!;!!;!!;!!

21
2018-06-27 13:04



Kann das bitte jemand erklären? Sieht sehr faszinierend aus. - Daniel Vartanov
; ist nur Befehl Trennzeichen. !! Wiederhole den letzten Befehl in bash. Also lauf 'pgrep ssh' und wiederhole es dann 6 mal. - Piotr Kukielka
Das ist zwar lehrreich, aber nicht intuitiv. Einzeiler for scheint der beste Weg. Trotzdem danke für die Antwort. - erm3nda
Gewohnheit cmd ;!! in einer Zeile wiederholen Sie einfach den eingegebenen Befehl Vor die aktuelle Zeile? Es müsste zwei getrennte sein history Einträge. - Joel Purra


Versuche dies:

yes ls | head -n5 | bash

Dies erfordert, dass der Befehl in einer Subshell ausgeführt wird, was zu einer leichten Leistungseinbuße führt. YMMV. Im Grunde erhalten Sie den "Ja" -Befehl, um die Zeichenkette "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 cshähnliche Schalen haben eine eingebaute repeat Befehl. Sie könnten das verwenden, um Ihren Befehl in einer Bash-Subshell auszuführen!


14
2018-01-31 00:04





ähnelt früheren Antworten, benötigt aber keine for-Schleife:

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

Pipe-Ausgabe von Seq zu Xargs ohne Argumente oder Optionen


11
2017-11-18 14:36



Dies wird nur eine Ausführung machen echo "hello" 1 2 3 4 5 6 7 8 9 10. Sie müssen Xargs mit ausführen -n 1 für einen Prozess für jede Eingabe (Anzahl) und mit -P 10 für parallele Ausführung (10 parallele Prozesse). Schluss mit seq 10 | xargs -n 1 -P 10 echo. - Alexander Klimetschek


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

was natürlich zu einem einzigen Liner gemacht werden könnte:

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

und scheint der portabelste Weg zu sein und somit weniger wahrscheinlich, dass Sie Programme installieren.

Die folgenden sind weniger tragbar:

  • Klammer Erweiterung {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, denken Sie an GNU parallel:

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

Das führt Befehle parallel 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


4
2018-06-15 09:39





Eine Fischschalenimplementierung von @ eduardo-ivanecs run Funktion über

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

2
2018-06-20 18:44





Das wäre 'watch' - sollte Teil von fast jedem Unix-System sein, das procps verwendet

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

watch "df -hP | grep /tmp" 

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


0



Es gibt bereits eine Antwort mit Uhr ... siehe unten ... - mahatmanich