it-swarm.com.de

Befehle wie in einer Warteschlange ausführen

Ich muss eine Menge von verschiedenen Dateien in verschiedene Ordner kopieren. Ich kann alle meine Kopierbefehle zu einem Bash-Skript hinzufügen und das dann ausführen, aber dann muss ich warten, bis es beendet ist, wenn ich dieser "Kopierwarteschlange" weitere Befehle hinzufügen möchte.

Gibt es eine Möglichkeit, Befehle als Warteschlange auszuführen und dieser Warteschlange weitere Befehle hinzuzufügen, während die Dinge ausgeführt werden?

Anders erklärt, möchte ich eine lange laufende Aufgabe starten. Während das läuft, möchte ich ein anderes starten, das nicht wirklich startet, bis das erste fertig ist. Und dann fügen Sie eine weitere nach der letzten hinzu und so weiter. Ist das irgendwie möglich

41
Svish

Das Dienstprogramm at , das am besten dafür bekannt ist, Befehle zu einem bestimmten Zeitpunkt auszuführen, verfügt auch über eine Warteschlangenfunktion und kann aufgefordert werden, Befehle jetzt auszuführen. Es liest den Befehl, der von der Standardeingabe ausgeführt werden soll.

echo 'command1 --option arg1 arg2' | at -q myqueue now
echo 'command2 ...' | at -q myqueue now

Der Befehl batch entspricht at -q b -m now (-m bedeutet, dass die Befehlsausgabe, falls vorhanden, wie bei cron an Sie gesendet wird). Nicht alle Unix-Varianten unterstützen Warteschlangennamen (-q myqueue). Möglicherweise sind Sie auf eine einzelne Warteschlange namens b beschränkt. Die at von Linux ist auf Warteschlangennamen mit einem Buchstaben beschränkt.

24
Gilles

Fügen Sie & an das Ende Ihres Befehls an, um ihn an den Hintergrund zu senden, und wait, bevor Sie den nächsten Befehl ausführen. Zum Beispiel:

$ command1 &
$ wait; command2 &
$ wait; command3 &
$ ...
21
Vortico

Sowohl Brad als auch Mankoffs Lösungen sind gute Vorschläge. Eine andere, die einer Kombination aus beiden ähnelt, ist die Verwendung von GNU Screen , um Ihre Warteschlange zu implementieren. Dies hat den Vorteil, dass es im Hintergrund ausgeführt werden kann, dass Sie es jederzeit überprüfen können und beim Einreihen neuer Befehle diese einfach in den Puffer eingefügt werden, damit sie ausgeführt werden, nachdem die vorherigen Befehle beendet wurden.

Erster Lauf:

$ screen -d -m -S queue

(Übrigens, jetzt ist ein guter Zeitpunkt, um mit ein paar großartigen Dateien zu spielen. screenrc files )

Dadurch wird eine Hintergrundbildschirmsitzung für die von Ihnen angegebene Warteschlange erstellt.

Stellen Sie nun so viele Befehle in die Warteschlange, wie Sie möchten:

screen -S queue -X stuff "echo first; sleep 4; echo second^M"

Ich führe oben mehrere Befehle nur zum Testen aus. Ihr Anwendungsfall würde wahrscheinlich eher so aussehen:

screen -S queue -X stuff "echo first^M"
screen -S queue -X stuff "echo second^M"

Beachten Sie, dass das "^ M" in meiner Zeile oben eine Möglichkeit ist, eine eingebettete neue Zeile zu erhalten, die später interpretiert wird, nachdem der Bildschirm sie in Ihre vorhandene Bash-Shell eingefügt hat. Verwenden Sie "CTL-V", um diese Sequenz abzurufen.

Es wäre ziemlich einfach, einige einfache Shell-Skripte zu erstellen, um dies zu automatisieren und Befehle in die Warteschlange zu stellen. Wann immer Sie den Status Ihrer Hintergrundwarteschlange überprüfen möchten, können Sie eine erneute Verbindung herstellen über:

screen -S queue -r

Technisch gesehen müssen Sie Ihre Bildschirmsitzung nicht einmal benennen, und es funktioniert einwandfrei, aber sobald Sie sich darauf einlassen, möchten Sie sowieso immer eine laufen lassen. ;-)

Wenn Sie dies tun, ist es natürlich auch sinnvoll, eine der aktuellen Windows-Warteschlangen zu benennen und Folgendes zu verwenden:

screen -S queue -p queue -X stuff "command"
11
Jordan

Es gibt ein Dienstprogramm, das ich mit großem Erfolg für genau den Anwendungsfall verwendet habe, den Sie beschreiben. Kürzlich habe ich meinen primären Laptop auf neue Hardware umgestellt, wobei einige Dateien auf einen NAS und der Rest auf den neuen Computer verschoben wurden.

So habe ich es gemacht.

  1. Richten Sie alle an einer Netzwerkverbindung beteiligten Computer so ein, dass sie sich gegenseitig erreichen können.

  2. Installieren Sie auf dem Computer, von dem Sie Dateien verschieben (im Folgenden als Quellcomputer bezeichnet), rsync mit apt-get install rsync und der geheimen Sauce Task Spooler (Website http: // vicerveza.homeunix.net/~viric/soft/ts/ ). Wenn Sie unter Debian arbeiten, lautet der Paketname für tstask-spooler und die ausführbare Datei wird in tsp umbenannt, um Namenskonflikte mit der ausführbaren Datei ts aus dem Paket moreutils zu vermeiden. Das von der Website verlinkte Debian-Paket ist perfekt auf Ubuntu mit dpkg -i task-spooler_0.7.3-1_AMD64.deb oder ähnlichem installierbar.

  3. Stellen Sie außerdem sicher, dass auf allen Computern SSH mit apt-get install openssh-server installiert ist. Auf dem Quellcomputer müssen Sie SSH einrichten, um eine kennwortlose Anmeldung auf den Zielcomputern zu ermöglichen. Die am häufigsten verwendete Methode ist die Authentifizierung mit öffentlichem Schlüssel mit ssh-agent (Beispiele hierfür finden Sie unter https://www.google.se/search?q=ssh+public+key+authentication ). , aber ich benutze manchmal eine einfachere Methode, die genauso gut mit der Passwortauthentifizierung funktioniert. Fügen Sie Ihrer SSH-Client-Konfiguration Folgendes hinzu (entweder ~/.ssh/config oder /etc/ssh/ssh_config):

    Host *
         ControlMaster auto
         ControlPath ~/.ssh/master-%[email protected]%h:%p
    

    Öffnen Sie dann ein Terminal auf dem Quellcomputer, melden Sie sich mit ssh target1 an, authentifizieren Sie sich wie gewohnt und lassen Sie dieses Terminal geöffnet. Beachten Sie, dass es eine Socket-Datei mit dem Namen ~/.ssh/[email protected]:22 gibt. Dies ist die Datei, die eine authentifizierte Mastersitzung geöffnet hält und nachfolgende kennwortlose Verbindungen für user zulässt (solange die Verbindung denselben Ziel-Hostnamen und -Port verwendet).

    Zu diesem Zeitpunkt müssen Sie sicherstellen, dass Sie sich anmelden können, ohne zur Authentifizierung bei den Zielcomputern aufgefordert zu werden.

  4. Führen Sie nun ts rsync -ave ssh bigfile [email protected]: für eine einzelne Datei oder ts rsync -ave ssh bigdir [email protected]: für ein Verzeichnis aus. Bei rsync ist es wichtig, keinen abschließenden Schrägstrich in das Verzeichnis einzufügen (bigdir im Vergleich zu bigdir/). Andernfalls geht rsync davon aus, dass Sie in den meisten anderen Tools das Äquivalent von bigdir/* gemeint haben.

    Der Task-Spooler gibt die Eingabeaufforderung zurück und lässt Sie viele dieser Befehle nacheinander in die Warteschlange stellen. Untersuchen Sie die Ausführungswarteschlange mit ts ohne Argumente.

Der Task-Spooler verfügt über zahlreiche Funktionen, wie z. B. das Neuanordnen der Ausführungswarteschlange, das Ausführen eines bestimmten Jobs nur, wenn ein anderer Job erfolgreich ausgeführt wurde usw. Zeigen Sie die Hilfe zu ts -h an. Manchmal überprüfe ich die Befehlsausgabe, während sie mit ts -c ausgeführt wird.

Es gibt andere Methoden, um dies zu tun, aber für Ihren Anwendungsfall enthalten sie alle Task-Spooler. Ich habe mich für die Verwendung von rsync over SSH entschieden, um die Datei-Zeitstempel beizubehalten, die beim Kopieren über SMB nicht möglich wären.

8
holmb

Ich brauche solche Sachen auch ziemlich oft. Ich habe ein kleines Hilfsprogramm namens after geschrieben, das einen Befehl ausführt, wenn ein anderer Prozess beendet ist. Es sieht aus wie das:

#!/usr/bin/Perl

my $pid = shift;
die "Usage: $0 <pid> <command...>" unless $pid =~ /^\d+$/ && @ARGV;

print STDERR "Queueing process $$ after process $pid\n";
sleep 1 while -e "/proc/$pid";
exec @ARGV;

Sie führen es dann so aus:

% command1 arg1 arg2 ...  # creates pid=2853
% after 2853 command2 arg1 arg2 ... # creates pid=9564
% after 9564 command3 arg1 arg2 ...

Dies hat gegenüber einigen anderen Ansätzen den großen Vorteil, dass der erste Job nicht auf besondere Weise ausgeführt werden muss. Sie können jeden Prozess mit Ihrem neuen Job verfolgen.

4
Ken Williams

Befehl1 && Befehl2

  • das "&&" bedeutet, dass Befehl2 erst ausgeführt wird, nachdem Befehl1 mit dem Rückkehrcode 0 beendet wurde
  • Hinweis: Ein || bedeutet, dass Befehl2 erst ausgeführt wird, nachdem Befehl1 mit einem anderen Rückkehrcode als 0 beendet wurde
2
naftuli

Sie können der Befehlszeile von Shell, die bereits einen Befehl ausführt, einfach Befehle hinzufügen.

Entweder sorgfältig tippen oder anderswo tippen, überprüfen und ausschneiden und einfügen. Selbst wenn der aktuelle Befehl Ausgabezeilen spuckt, können Sie immer noch etwas Neues eingeben, die Eingabetaste drücken und es wird ausgeführt, wenn alle Befehle ausgeführt oder eingegeben wurden, bevor es abgeschlossen ist.

Beispiel folgt. Sie können das Ganze ausschneiden und einfügen oder die nachfolgenden Befehle eingeben, während der erste ausgeführt wird (wenn Sie wirklich sehr schnell tippen), oder wahrscheinlicher, während der zweite ausgeführt wird:

echo "foo"
sleep 10; echo "bar"
sleep 3
echo "baz"
1
user31752

der hackigste Weg, den ich mir vorstellen kann, ist es, den Warteschlangenzustand mit einfachen Sperrdateien in/tmp beizubehalten. Wenn file1.sh seine cp-Befehle ausführt, behält es eine Sperrdatei (oder einen Hardlink) in/tmp bei. Wenn es fertig ist, löschen Sie die Datei. Jedes andere Skript muss in/tmp nach Sperrdateien mit dem von Ihnen gewählten Benennungsschema suchen. Natürlich ist dies mit allen Arten von Fehlern behaftet, aber es ist trivial einzurichten und kann vollständig innerhalb von Bash durchgeführt werden.

0
Brad Clawsie