web-dev-qa-db-de.com

Start des Terminals blockieren

Wenn Sie diesen einfachen Testbefehl eingeben:

gnome-terminal -x bash -c "ls;sleep 3"

Sie werden feststellen, dass es sofort zurückkehrt (das neu erstellte Terminal verweilt natürlich drei Sekunden). Dies steht beispielsweise im Gegensatz zu rxvt (derselbe Befehl, aber mit e).

Wenn Sie einen Blockierungsstart wünschen, scheint der historische Konsens mit --disable-factory gewesen zu sein. Dies funktioniert leider nicht mehr (getestet 3.14.2).

Also, wie starte ich das Terminal nicht asynchron?

Bonus: konsole, lxterminal und xfce4-terminal Haben zumindest auch das gleiche Problem. Befehle für die?

5
imallett

Ich verwende eine Methode, die Ähnlichkeiten mit der Antwort von terdon aufweist (und mit seiner Hilfe erstellt wurde - Danke @ terdon dafür!), Aber einen etwas anderen Ansatz verfolgt:

Ich erstelle eine temporäre Datei, damit das untergeordnete Terminal mit dem übergeordneten Terminal kommunizieren und ihm die PID der entsprechenden Bash-Instanz mitteilen kann. Dann lasse ich das übergeordnete Terminal die temporäre Datei lesen und erinnere mich an die PID, lösche die Datei und fahre fort, indem ich alle 100 ms prüfe (Verzögerung kann geändert werden), ob die Bash-Instanz des untergeordneten Terminals noch ausgeführt wird. Wenn nicht, wurde das Terminal entweder manuell geschlossen oder der Befehl wurde beendet. Dann wird der Startbefehl beendet und das übergeordnete Terminal kann wieder verwendet werden.

Vorteil dieses Ansatzes:
Alle Befehle, die gestartet werden (ls; sleep 3 Oder ein Ersatz für diese), werden ausgeführt after der Befehl, der für die Erkennung des Schließens des Terminals verantwortlich ist. Wenn der innere Befehl hängt oder Sie das Terminal manuell schließen, bevor es endet, funktioniert der Mechanismus weiterhin und setzt die Ausführung des äußeren Skripts fort, anstatt in Endlosschleifen zu laufen.


Der Code als Einzeiler mit Debug-Ausgabe ("gestartet", nachdem das untergeordnete Terminalfenster geöffnet wurde, "beendet", nachdem es geschlossen wurde) und einer Genauigkeit von 0,1 Sekunden lautet:

pidfile=$(mktemp); gnome-terminal -x bash -c "echo \$$>$pidfile; ls; sleep 3"; until [ -s $pidfile ]; do sleep 0.1; done; terminalpid=$(cat "$pidfile"); rm $pidfile; echo "launched"; while ps -p $terminalpid > /dev/null 2>&1; do sleep 0.1; done; echo "terminated"

Oder ohne Debug-Ausgabe:

pidfile=$(mktemp); gnome-terminal -x bash -c "echo \$$>$pidfile; ls; sleep 3"; until [ -s $pidfile ]; do sleep 0.1; done; terminalpid=$(cat "$pidfile"); rm $pidfile; while ps -p $terminalpid > /dev/null 2>&1; do sleep 0.1; done

Fast derselbe Code, aber flexibler als Bash-Skript geschrieben:

#! /bin/bash

delay=0.1
pidfile=$(mktemp)

gnome-terminal -x bash -c "echo \$$>$pidfile; ls; sleep 3"

until [ -s $pidfile ] 
    do sleep $delay
done
terminalpid=$(cat "$pidfile")
rm $pidfile
echo "launched"
while ps -p $terminalpid > /dev/null 2>&1
    do sleep $delay
done
echo "terminated"

Natürlich können Sie die Zeilen echo "launched" Und echo "terminated" Weglassen und die Zeile delay=0.1 In eine andere Verzögerung zwischen zwei Überprüfungen des Terminalstatus (in Sekunden) ändern, wenn Sie brauchen es, um mehr oder weniger genau zu sein.

Ersetzen Sie die Zeile, um einen anderen benutzerdefinierten Befehl im untergeordneten Terminal auszuführen

gnome-terminal -x bash -c "echo \$$>$pidfile; ls; sleep 3"

mit dem Folgenden (fügen Sie Ihren Befehl anstelle des großgeschriebenen Platzhalters ein!)

gnome-terminal -x bash -c "echo \$$>$pidfile; INSERTYOURCOMMANDSHERE"
4
Byte Commander

In ihrer unendlichen Weisheit beschlossen die GNOME-Entwickler, diese Option zu entfernen. Leider hat sich ihre Weisheit nicht darauf ausgeweitet, auch ihre man -Seite zu aktualisieren, auf der sie weiterhin aufgeführt ist. Es sieht also so aus, als würde gnome-terminal Immer im Hintergrund ausgeführt und die übergeordnete Shell-Sitzung wird sofort wiederhergestellt. Um dies zu umgehen, haben Sie einige Möglichkeiten:

  1. Verwenden Sie einfach ein anderes Terminal. Ich habe es mit xterm, rxvt und GNOME terminator versucht, die alle wie erwartet funktionierten.

  2. Verwenden Sie einige hässliche Hacks. gnome-terminal Startet beim ersten Start /usr/lib/gnome-terminal/gnome-terminal-server. Aus irgendeinem Grund bedeutet dies, dass der Prozess beendet ist, sobald Sie ihn gestartet haben. Um zu veranschaulichen:

    $ gnome-terminal  -x sh -c "ls;sleep 30" 
    [1] 5896
    $ jobs
    [1]+  Done                    gnome-terminal -x sh -c "ls;sleep 30"
    

    Wie Sie oben sehen können, wird der gestartete Job sofort beendet, nachdem er im Hintergrund gestartet wurde. Dies bedeutet, dass mein erster Gedanke, es im Hintergrund zu starten und dann mit $! Zu prüfen, ob es noch läuft, nicht funktioniert. Das bedeutet, dass Sie etwas weniger Elegantes tun müssen, wie eine Datei zu erstellen:

    tmpfile=$(mktemp); gnome-terminal  -x sh -c "ls;sleep 30; rm $tmpfile" 
    while [ -e $tmpfile ] ; do :; done
    

    Die obigen Befehle erstellen i) eine temporäre Datei (tmpfile=$(mktemp)); ii) starte gnome-terminal und fordere es auf, $tmpfile zu löschen, wenn es fertig ist und iii) tue nichts (:), solange die temporäre Datei existiert while [ -e $tmpfile ]. Dies führt dazu, dass ein Terminal wartet, bis der von gnome-terminal Ausgeführte Prozess beendet ist, bevor er fortgesetzt wird.

3
terdon

Die Ubuntu-Betreuer des gnome-terminal-Pakets bemerkten dieses Problem und erstellten ein Wrapper-Skript (im Ubuntu-Paket gnome-terminal-3.14.2-0ubuntu3), Um die Option --disable-factory Wieder zu aktivieren. Das Wrapper-Skript funktioniert jedoch nicht!

Aus dem Changelog http://changelogs.ubuntu.com/changelogs/pool/main/g/gnome-terminal/gnome-terminal_3.14.2-0ubuntu3/changelog :

gnome-terminal (3.14.2-0ubuntu3) lebhaft; Dringlichkeit = mittel

  • debian/gnome-terminal: Fügen Sie ein Wrapper-Skript hinzu, um gnome-terminal mit einer anderen App-ID zu starten, wenn ein Benutzer die jetzt ignorierte Option --disable-factory übergibt. Dadurch sollte die Kompatibilität mit alten Startprogrammen für Benutzer wiederhergestellt werden, die ein Upgrade durchführen. [...]

Ich kann nicht im Ubuntu "Launchpad" navigieren (so viel zu Open Source), aber das Wrapper-Skript befindet sich in https://launchpad.net/ubuntu/+archive/primary/+files/gnome-terminal_3) .14.2-0ubuntu3.debian.tar.xz (genannt gnome-terminal.wrap).

Der Fehler ist, dass das Skript gnome-terminal.wrap Auf den falschen untergeordneten Prozess wartet. Es sollte auf dem Terminalserver und nicht auf dem Terminalclient warten. Das Update besteht darin, die beiden Methoden server_appeared Und spawn_terminal_server Wie folgt zu ändern:

    def server_appeared(self, con, name, owner):
        # start gnome-terminal now
        gt = Gio.Subprocess.new(['/usr/bin/gnome-terminal.real',
                                 '--app-id', name] +
                                self.args,
                                Gio.SubprocessFlags.NONE)
        # removed a line here: gt.wait_async(...)

    def spawn_terminal_server(self, name):
        ts = Gio.Subprocess.new(['/usr/lib/gnome-terminal/gnome-terminal-server',
                                 '--app-id',
                                 name],
                                Gio.SubprocessFlags.NONE)
        ts.wait_async(None, self.exit_loop, ts)

Sie können die feste Datei von folgender Adresse herunterladen: https://Gist.github.com/ecatmur/00893506a23e828c6688 .

Ich habe den Paketbetreuer benachrichtigt und hoffe, dass es bald behoben sein wird.


Eine weitere interessante Tatsache: gnome-terminal kann mit einem alternativen Client namens gterminal erstellt werden, der eine --wait - Option hat, die genau das tut, was Sie wollen. Leider baut oder installiert Ubuntu es nicht in seinem Gnome-Terminal-Paket.

3
ecatmur

Für Personen im Februar 2017 <t <März 2018, die über Google auf diese Website gekommen sind, lautet die einfache Lösung:

gnome-terminal --disable-factory -e "cmd"

funktioniert und startet gnome-terminal erwartungsgemäß synchron/blockierend.

Getestet unter:

  • Ubuntu 16.04
  • gnome-terminal 3.18.3
0
Oscillon

Ich habe ein neueres Gnome-Terminal verwendet, und das Verhalten, das Sie für Gnome-Terminal beschrieben haben, scheint für konsole, lxterm und rxvt dasselbe zu sein (alle 3 ausprobiert). Da OP bisher keine Kommentare beantwortet hat, um zu verdeutlichen, was er oder sie möchte, gehe ich davon aus, dass OP das übergeordnete Terminal weiterhin verwenden möchte, ohne auf den Abschluss des untergeordneten Terminals zu warten.

Das kann erreicht werden mit gnome-terminal &. Wenn Sie verhindern möchten, dass das untergeordnete Terminal beim Beenden des übergeordneten Terminals geschlossen wird, verwenden Sie Nohup gnome-terminal &. Um zu vermeiden, dass die Fehlerausgabe im übergeordneten Terminal angezeigt wird, verwenden Sie gnome-terminal 2> /dev/null & oder Nohup gnome-terminal 2> /dev/null &.

0