Führen GUI-basierte Anwendungen Shell-Befehle im Hintergrund aus?

29

Ich bin erst vor 2 Tagen von Windows auf Ubuntu 16.04 umgestiegen. Mir gefällt, wie wir den Unity Desktop anpassen können. Ich spiele nur mit dem Erscheinungsbild der Desktop-Umgebung. Genau wie in Windows wollte ich, dass der Launcher am unteren Bildschirmrand angezeigt wird. Beim Googeln habe ich einen Befehl gefunden, der wie folgt lautet:

gsettings set com.canonical.Unity.Launcher launcher-position Bottom

Es gibt auch das Unity-Tweak-Tool und den Dconf-Editor, um die Arbeit zu erledigen. Aber dies ist der GUI-Ansatz, um Dinge zu erledigen.

Meine Fragen sind:

  • Führen diese GUI-basierten Anwendungen denselben Befehl auch im Hintergrund aus?
  • Wie kann man einen Blick auf die interne Funktionsweise dieser Anwendungen werfen? Ich meine, gibt es eine Möglichkeit, die Befehle, die bei jedem Klick auf die Schaltfläche ausgeführt werden, tatsächlich anzuzeigen?
  • Öffnen diese Anwendungen ein Terminal im Hintergrund und führen diese Befehle aus?

In der Antwort hier erfahren Sie, wie Sie den Standard-Dateideskriptor des Prozesses erhalten. Aber ich habe nichts in der Ausgabe bekommen.

Darüber hinaus strace -p pid -o output.txtwirft der Befehl eine große Menge an Text in die Datei.

Kurz gesagt, funktioniert die Arbeit mit GUI-Anwendungen genauso wie die Arbeit über die Befehlszeile?

ptmdevncoder
quelle

Antworten:

35

Führen diese GUI-basierten Anwendungen denselben Befehl auch im Hintergrund aus?

Ja und nein. Sie schreiben in die dconfEinstellungsdatenbank, können jedoch unterschiedliche Methoden verwenden. In Python geschriebene Programme werden wahrscheinlich das gi.repository.GioModul verwenden (ich weiß, weil ich es oft benutze) oder sie können es stattdessen gsettingsdurch Aufrufen als externen Befehl verwenden subprocess.Popen(['gsettings','org.some.schema','some-key','value']), und es wird im Grunde genommen als Shell-Befehl ausgeführt. Ein AC-Programm wird etwas Ähnliches verwenden, wahrscheinlich eine gio.hBibliothek, oder es könnte sogar die exec()Funktionsfamilie verwenden, um dasselbe wie Popenin Python zu tun . Um also Ihre Titelfrage zu beantworten: "Führen GUI-basierte Anwendungen Shell-Befehle im Hintergrund aus?" Sie können es, aber wahrscheinlich ist es nicht notwendig, weil es eine Bibliothek für jede Sprache gibt, in der die App geschrieben ist, und wahrscheinlich wird es ein bisschen schneller sein, eine Bibliotheksfunktion zu verwenden, als einen neuen Prozess zu erzeugen.

Um Ihnen ein Beispiel zu geben, wie es mit Bibliotheken / Modulen gemacht wird, werfen Sie einen Blick auf den Quellcode meines Launcher-Listen-Indikators. Dort habe ich eine Funktion geschrieben, um eine Instanz der Gio.SettingsKlasse zu erstellen und sie dann zu verwenden, um den Unity-Launcher abhängig von der Art der Liste zu ändern, die Sie dort haben möchten.

Wie kann man einen Blick auf die interne Funktionsweise dieser Anwendungen werfen? Ich meine, gibt es eine Möglichkeit, die Befehle, die bei jedem Klick auf die Schaltfläche ausgeführt werden, tatsächlich anzuzeigen?

Nein. Wenn Sie sehen möchten, welcher Befehl in der Programmiersprache dieser App ausgegeben wird, indem Sie eine Taste drücken oder auf Fensterelemente klicken, ist dies nicht möglich. Lesen Sie den Quellcode der Anwendung, wenn Sie ihn erhalten können. Sie können dconf watch /damit sehen, welche Einstellungen geändert werden, aber nicht, wie dies durchgeführt wird.

Technisch gesehen können Sie, wenn Sie wissen, wie man einen Debugger bedient, Speicheradressen liest und eine Assemblersprache beherrscht, wissen, was eine App auf CPU- und Speicherebene tut. Dies wird als Software-Reverse-Engineering bezeichnet und wird häufig von Sicherheitsexperten verwendet, um schädliche Software zu analysieren und Schwachstellen in legitimer Software zu erkennen.

Öffnen diese Anwendungen ein Terminal im Hintergrund und führen diese Befehle aus?

Nein, es ist kein Terminal angeschlossen. Viele Programme wissen, wo sich die dconfDatenbank für den Benutzer befindet und schreiben dort. Es gibt auch einen Interprozess-Kommunikationsbus dbus, in dem Programme Signale senden können, und ein Programm wird lauten: "Hey, das ist eine Nachricht für mich!"

Nachtrag

  • Können Anwendungen andere Anwendungen ausführen? Ja, das geschieht über Standard- fork()und execve()Systemaufrufe. Das Wesentliche beim Erstellen von Prozessen unter Linux und anderen * nix-Systemen basiert weitgehend auf diesen beiden. Der Shell-Mechanismus zum Ausführen von nicht eingebauten Befehlen nutzt dies besonders häufig. Wenn Sie interaktiv laufen

    $ ls 
    

    Die Shell erstellt über einen neuen Prozess fork(), execve() der ausgeführt wird und gestartet wird ls. Aufgrund dessen, wie execve()dieser neue gegabelte Prozess sein wird ls. Der pipe()Systemaufruf hilft beim Zurücklesen der Ausgabe von ls. Ich empfehle dringend, meine Antwort für Was ist der Unterschied zwischen Pipe und Umleitung , um zu verstehen, wie der Pipe-Mechanismus funktioniert - es ist nicht nur ein |Operator, sondern tatsächlich ein Systemaufruf.

  • Können Anwendungen Shell-Befehle ausführen? Nein. Die Shell-Syntax wird nur von der Shell selbst verstanden. Sie können jedoch eine Shell mit einer Befehlszeilenoption starten -cund entsprechende Befehle bereitstellen. Dies wird häufig für benutzerdefinierte Verknüpfungen verwendet, die in GNOME oder anderen Desktop-Umgebungen festgelegt wurden, da benutzerdefinierte Verknüpfungen auf ausführbaren Dateien ausgeführt werden und es keine Shell gibt, die die Syntax versteht. So würden Sie beispielsweise den Befehl bash -c 'xdotool key Ctrl+Alt+T'indirekt ausführen xdotooloder bash -c 'cd $HOME/Desktop; touch New_File'eine neue Datei auf dem Desktop über eine Verknüpfung erstellen. Dies ist ein besonders interessantes Beispiel, da Sie eine Shell-Variable verwenden können, da Sie eine Shell explizit verwenden.

Sergiy Kolodyazhnyy
quelle
2
Vielen Dank @Serg für die ausführliche Erklärung und die getrennte und systematische Beantwortung jeder Frage!
ptmdevncoder
@ Logan mein Vergnügen, immer froh zu helfen :)
Sergiy Kolodyazhnyy
1
Zum Glück ist die Quelle für die genannten Tools verfügbar, da es sich um FLOSS handelt. Daher würde ich sagen, dass es in diesem Fall ein bisschen übertrieben ist, sie umzukehren. :)
Andrea Lazzarotto
1
@AndreaLazzarotto Yep, Unity Tweak Tool und Dconf Editor - das sind Open Source, daher müssen diese nicht rückentwickelt werden. In meiner Antwort habe ich alles sehr allgemein gehalten und versucht, nicht nur diese Tools, sondern auch andere Möglichkeiten zu behandeln
Sergiy Kolodyazhnyy
Schneller ist selten der Punkt für GUI-Anwendungen. Es ist mühsam, die Werte für die Verwendung mit einem Shell-Tool zu maskieren oder zu marshallen. Es ist leicht, Fehler zu machen und es ist sinnlos, wenn Sie einfach die Bibliothek verwenden können. Erneutes Debuggen: Wenn die Anwendung mit Debug-Symbolen installiert und in einer von gdb unterstützten Sprache geschrieben ist (unter debian z. B. durch Installation eines entsprechenden -dbg-Pakets), müssen Sie Assembler nicht kennen: gdb zeigt Ihnen den Quellcode mit dem Debug-Informationen, während Sie durch die Anwendung gehen. Was schwieriger sein wird, ist, einen richtigen Einstiegspunkt zu finden, von dem aus das Debuggen beginnen kann, da die GUI-Boilerplate langweilig ist.
Jonas Schäfer
21

Ausspionieren, was passiert

Die meisten Funktionen dieser Einstellungseditoren können durch Ausführen von überwacht werden

dconf watch /

in einem Terminal.

gEinstellungen

In den meisten Fällen müssen diese Anwendungen die dconfDatenbank (weiter unten) bearbeiten, um das zu erreichen, was Sie mit dem obigen Befehl sehen . Dies kann entweder direkt erfolgen , indem Sie die cli-Optionen von dconf verwenden (was nicht bevorzugt wird), oder indem Sie die entsprechenden gsettingsBefehle wie den von Ihnen erwähnten ausführen.

Zum Ausführen dieser Befehle wird kein Terminalfenster benötigt, wie Sie in den Beispielen sehen können.

About, gsettings, dconf und die Datenbank dconf

gsettingsist das Cli-Frontend für dconf, das seinerseits die dconfDatenbank, in der die meisten Einstellungen gespeichert sind, im Binärformat bearbeitet . Siehe auch diese nette Antwort .

Die dconfDatenbank kann übrigens auch über die GUI mit dem dconfEditor bearbeitet werden , der sich in den Repositorys befindet:

Bildbeschreibung hier eingeben

Arbeitsproben

ein. In Python

Bildbeschreibung hier eingeben

Um Ihnen zu zeigen, was unter der Haube passiert, klicken Sie unterhalb eines Arbeitsbeispiels auf eine einzelne Schaltfläche, um Ihre Startposition über die grafische Benutzeroberfläche umzuschalten:

#!/usr/bin/env python3
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
import subprocess

key = ["com.canonical.Unity.Launcher", "launcher-position"]

class ToggleWin(Gtk.Window):

    def __init__(self):
        Gtk.Window.__init__(self, title="Toggle")
        button = Gtk.Button("Toggle launcherposition")
        button.connect("clicked", self.toggle)
        self.add(button)

    def toggle(self, *args):
        # read the current setting on launcher position
        current = subprocess.check_output([
            "gsettings", "get", key[0], key[1]
            ]).decode("utf-8").strip()
        # toggle to the other option
        new = "'Left'" if current == "'Bottom'" else "'Bottom'"
        subprocess.Popen([
            "gsettings", "set", key[0], key[1], new
            ])

def delete_actions(*args):
    Gtk.main_quit()

def miniwindow():
    window = ToggleWin()
    window.connect("destroy", delete_actions)
    window.show_all()
    Gtk.main()

miniwindow()
  • Fügen Sie den Code in ein leeres ein file.py
  • starte es mit dem Befehl:

    python3 /path/to/file.py
    

...und Spaß haben.

b. Startsymbol

Selbst ein einfacher Launcher kann die Aufgabe über die GUI erledigen:

Bildbeschreibung hier eingeben

[Desktop Entry]
Name=Set launcherposition
Exec=zenity --info --text="Right- click to set launcher position"
Type=Application
StartupNotify=False
Icon=preferences-system

Actions=Launcher to bottom;Launcher on the left;

[Desktop Action Launcher to bottom]
Name=Launcher to bottom
# right click option to set launcher to bottom
Exec=gsettings set com.canonical.Unity.Launcher launcher-position Bottom

[Desktop Action Launcher on the left]
Name=Launcher on the left
# right click option to set launcher to left
Exec=gsettings set com.canonical.Unity.Launcher launcher-position Left
  • Fügen Sie den Code in eine leere Datei ein und speichern Sie ihn unter setlauncher.desktop
  • Ziehen Sie es auf den Launcher und klicken Sie mit der rechten Maustaste

Zum dauerhaften Gebrauch in ~/.local/share/applications(für den lokalen Gebrauch) oder ~/usr/share/applicationsfür alle Benutzer aufbewahren.

Jacob Vlijm
quelle
@Logan erwähne es nicht :)
Jacob Vlijm