Linux / Bash, wie können Befehle in einer FIFO-Warteschlange geplant werden?

11399
Andrei

Ich möchte die Möglichkeit, Befehle in einer FIFO-Warteschlange auszuführen. Ich möchte NICHT, dass sie zu einem bestimmten Zeitpunkt in der Zukunft ausgeführt werden, wie dies bei dem Befehl "at" der Fall wäre. Ich möchte, dass sie jetzt anfangen zu laufen, aber nicht gleichzeitig. Der nächste geplante Befehl in der Warteschlange sollte erst ausgeführt werden, nachdem der erste Befehl ausgeführt wurde. Alternativ wäre es schön, wenn ich eine maximale Anzahl von Befehlen aus der Warteschlange angeben könnte, die gleichzeitig ausgeführt werden können. Wenn zum Beispiel die maximale Anzahl gleichzeitiger Befehle 2 ist, werden nur maximal 2 in der Warteschlange geplante Befehle aus der Warteschlange auf FIFO-Weise abgerufen, um ausgeführt zu werden Derzeit werden 2 laufende Befehle beendet.

Ich habe gehört, dass Task-Spooler so etwas tun könnte, aber dieses Paket scheint nicht gut unterstützt / getestet zu sein und ist nicht in den Ubuntu-Standard-Repositorys enthalten (Ubuntu ist das, was ich verwende). Wenn das die beste Alternative ist, lass es mich wissen und ich benutze den Task-Spooler, ansonsten bin ich daran interessiert herauszufinden, was der beste, einfachste, am meisten getestete, fehlerfreie, kanonische Weg ist, so etwas mit bash zu tun.

AKTUALISIEREN:

Einfache Lösungen wie; oder && von bash funktionieren nicht. Ich muss diese Befehle von einem externen Programm aus planen, wenn ein Ereignis auftritt. Ich möchte nur nicht, dass hunderte von Instanzen meines Befehls gleichzeitig ausgeführt werden. Daher ist eine Warteschlange erforderlich. Es gibt ein externes Programm, das Ereignisse auslöst, bei denen ich eigene Befehle ausführen kann. Ich möchte mit ALLEN ausgelösten Ereignissen umgehen, ich möchte kein Ereignis verpassen, aber ich möchte auch nicht, dass mein System abstürzt. Deshalb möchte ich, dass eine Warteschlange meine vom externen Programm ausgelösten Befehle verarbeitet.

7
Ich fand diesen Link, wo sie über gnu parallel zu Semaphor diskutieren und einige Kommentare zum Task-Spooler machen. Es könnte nützlich sein: http://unix.stackexchange.com/questions/168978/limit-maximum-number-of-concurrent-scp-prozesses-running-on-a-host vor 7 Jahren 0

6 Antworten auf die Frage

16
Andrei

Task Spooler:

http://vicerveza.homeunix.net/~viric/soft/ts/

https://launchpad.net/ubuntu/+source/task-spooler/0.7.3-1

Does the trick very well. Hopefully it will be included in Ubuntu's package repos.

Dies ist jetzt ab 15.10 in Ubuntus Paket-Repo. "apt-get install Task-Spooler" ovolve vor 8 Jahren 0
Beachten Sie, dass bei der Installation über Ubuntus Paket-Repo der Befehl von `ts` in` tsp` umbenannt wird. Mitja vor 6 Jahren 0
4
Hennes

Use ;

For example:
ls ; touch test ; ls

That will list the directory. Only after ls has run it will run touch test which will create a file named test. And only after that has finished it will run the next command. (In this case another ls which will show the old contents and the newly created file).

Similar commands are || and &&.

; will always run the next command.

&& will only run the next command it the first returned success.
Example: rm -rf *.mp3 && echo "Success! All MP3s deleted!"

|| will only run the next command if the first command returned a failure (non-zero) return value. Example: rm -rf *.mp3 || echo "Error! Some files could not be deleted! Check permissions!"

If you want to run a command in the background, append an ampersand (&).
Example:
make bzimage &
mp3blaster sound.mp3
make mytestsoftware ; ls ; firefox ; make clean

Will run two commands int he background (in this case a kernel build which will take some time and a program to play some music). And in the foregrounds it runs another compile job and, once that is finished ls, firefox and a make clean (all sequentially)

For more details, see man bash


[Edit after comment]

in pseudo code, something like this?

 Program run_queue: While(true) { Wait_for_a_signal(); While( queue not empty ) { run next command from the queue. remove this command from the queue. // If commands where added to the queue during execution then // the queue is not empty, keep processing them all. } // Queue is now empty, returning to wait_for_a_signal } 
// // Wait forever on commands and add them to a queue // Signal run_quueu when something gets added. // program add_to_queue() { While(true) { Wait_for_event(); Append command to queue signal run_queue } } 
Wie in meiner Frage aktualisiert: Einfache Lösungen wie; oder && von bash funktionieren nicht. Ich muss diese Befehle von einem externen Programm aus planen, wenn ein Ereignis auftritt. Ich möchte nur nicht, dass hunderte von Instanzen meines Befehls gleichzeitig ausgeführt werden. Daher ist eine Warteschlange erforderlich. Andrei vor 11 Jahren 0
Ah. Ja, das ändert sich ein bisschen. :-) Wie erkennen Sie das Ereignis? Jemand, der auf eine Schaltfläche klickt (real von webbasiert)? Ist ein Wrapper-Skript eine Option? (if (button_pressed &&! script_running) run_my_script. script: Legt fest, dass das Flag-Skript ausgeführt wird, den Befehl ausführen und das Flag löschen. Hennes vor 11 Jahren 0
Das Programm ist extern und löst ein Ereignis aus, bei dem ich meinen eigenen Befehl hinzufügen kann. Im Grunde möchte ich ALLE ausgelösten Ereignisse behandeln. Ich möchte kein Ereignis verpassen, nur dass ich nicht möchte, dass mein System abstürzt. Aus diesem Grund möchte ich, dass eine Warteschlange für meine vom externen Programm ausgelösten Befehle verwendet wird. Andrei vor 11 Jahren 0
Pseudo-Code hinzugefügt. add_to_queue () kann für mehrere Queus geändert werden. Aber ... Wenn Sie sich so viel Mühe geben, könnte etwas Pre-Build besser sein. Hennes vor 11 Jahren 0
Ich bin selbst Programmierer, damit ich meine eigene Lösung schreiben kann. Vielleicht war meine Frage irreführend. Da ich dies auf einem Pogoplug ausführen möchte, hatte ich gehofft, es gäbe etwas Ähnliches wie den "at" -Befehl, der getan hätte, was ich wollte. Der einzige "bash" -Teil der Frage bezog sich auf meine Hoffnung, dass eine solche Lösung so nahe wie möglich an der Shell gefunden werden könnte (um ressourcenschonend, zuverlässig / getestet und auf fast allem Linux verfügbar zu sein). Andrei vor 11 Jahren 0
2
terdon

The easiest way would be to simply run the commands sequentially:

cmd1; cmd2; cmd3; cmdN 

If you want the next command to run only if the previous command exited successfully, use &&:

cmd1 && cmd2 && cmd3 && cmdN 

That is the only bash native way I know of doing what you want. If you need job control (setting a number of parallel jobs etc), you could try installing a queue manager such as TORQUE but that seems like overkill if all you want to do is launch jobs sequentially.

Meine Frage wurde aktualisiert: Einfache Lösungen wie; oder && von bash funktionieren nicht. Ich muss diese Befehle von einem externen Programm aus planen, wenn ein Ereignis auftritt. Ich möchte nur nicht, dass hunderte von Instanzen meines Befehls gleichzeitig ausgeführt werden. Daher ist eine Warteschlange erforderlich. Andrei vor 11 Jahren 0
Schauen Sie sich TORQUE an, vielleicht können Sie auch etwas schreiben. Vielleicht eine Kombination von `pgrep foo | wc`, um laufende Prozesse zu zählen und entsprechend zu handeln. terdon vor 11 Jahren 0
1
psusi

Sie suchen at‚s Zwillingsbruder: batch. Er verwendet denselben Dämon, aber anstatt eine bestimmte Zeit einzuplanen, werden die Jobs in die Warteschlange gestellt und ausgeführt, wenn der durchschnittliche Systemlastdurchschnitt niedrig ist.

Aber ich möchte eine genaue Kontrolle darüber haben, ich möchte nicht, dass sich der Stapel für mich entscheidet. Der Task-Spooler scheint den Job zu erledigen, aber es ist ein Programm, das etwas unklar ist. Andrei vor 11 Jahren 0
0
mpy

Neben dedizierten Warteschlangensystemen (wie der Sun Grid Engine ), die Sie auch lokal auf einer Maschine verwenden können und die Dutzende von Möglichkeiten bieten, können Sie so etwas wie verwenden

 command1 && command2 && command3 

Das ist das andere Extrem - ein sehr einfacher Ansatz. Letzteres sieht weder mehrere gleichzeitige Prozesse vor, noch füllt die "Warteschlange" allmählich.

Meine Frage wurde aktualisiert: Einfache Lösungen wie; oder && von bash funktionieren nicht. Ich muss diese Befehle von einem externen Programm aus planen, wenn ein Ereignis auftritt. Ich möchte nur nicht, dass hunderte von Instanzen meines Befehls gleichzeitig ausgeführt werden. Daher ist eine Warteschlange erforderlich. Andrei vor 11 Jahren 0
0
Bogdan Dumitru

Ich ging die gleiche Route, suchte Task-Spooler und so weiter. Das Beste vom Besten ist folgendes:

GNU Parallel --semaphore --fg Es hat auch -j für parallele Jobs.

Diese Antwort ist sinnvoller, wenn Sie die Funktionsweise dieses Befehls und den Grund für die Verwendung dieser Optionen / Flags erläutern. Anthony Geoghegan vor 8 Jahren 0