web-dev-qa-db-fra.com

Est-ce qu'une application basée sur une interface graphique exécute des commandes Shell en arrière-plan?

J'ai migré vers Ubuntu 16.04 il y a à peine 2 jours à partir de Windows. J'aime la façon dont nous pouvons personnaliser Unity Desktop. Je ne fais que jouer avec l'apparence de l'environnement de bureau. Comme dans Windows, je voulais que le lanceur soit au bas de l'écran. Sur Google, j'ai trouvé une commande qui ressemble à ceci:

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

En outre, il existe les outils unity-Tweak-tool et dconf pour faire le travail. Mais c’est l’approche graphique pour faire avancer les choses.

Mes questions sont:

  • Ces applications basées sur une interface graphique exécutent-elles également la même commande en arrière-plan?
  • Comment avoir un aperçu du fonctionnement interne de ces applications? Je veux dire, y at-il un moyen de regarder réellement les commandes qui sont exécutées à chaque clic de bouton?
  • Ces applications ouvrent-elles un terminal en arrière-plan et exécutent-elles ces commandes?

La réponse ici indique comment obtenir le descripteur de fichier standard du processus. Mais, je n'ai rien eu dans la sortie.

De plus, la commande strace -p pid -o output.txt jette une énorme quantité de texte dans le fichier.

En bref, utiliser des applications à interface graphique revient-il à faire quelque chose à partir de la ligne de commande?

29
Logan

Ces applications basées sur une interface graphique exécutent-elles également la même commande en arrière-plan?

Oui et non. Ils écrivent dans la base de données de paramètres dconfname__, mais ils peuvent utiliser différentes méthodes pour le faire. Les programmes écrits en Python utiliseront probablement le module gi.repository.Gio (je le sais parce que je l’utilise beaucoup) ou ils peuvent utiliser plutôt gsettingsen tant que commande externe en appelant subprocess.Popen(['gsettings','org.some.schema','some-key','value']) et s’exécutera essentiellement en tant que commande Shell. Un programme C utilisera quelque chose de similaire, probablement une bibliothèque gio.h, ou pourrait même utiliser la famille de fonctions exec() pour faire la même chose que Popenfait en python. Donc, pour répondre à votre question de titre: "Est-ce que l'application basée sur l'interface graphique exécute des commandes Shell en arrière-plan?" Ils le peuvent, mais probablement pas nécessaire, car il existe une bibliothèque pour le langage dans lequel l'application est écrite, et il sera probablement un peu plus rapide d'utiliser une fonction de bibliothèque que de créer un nouveau processus.

Pour vous donner un exemple de la façon dont vous utilisez les bibliothèques/modules, n'hésitez pas à jeter un coup d'œil au code source de mon indicateur de liste de lanceurs. J'ai écrit une fonction pour créer une instance du Gio.Settings puis utilisez-le pour modifier le programme de lancement Unity en fonction du type de liste que vous souhaitez y avoir.

Comment avoir un aperçu du fonctionnement interne de ces applications? Je veux dire, y at-il un moyen de regarder réellement les commandes qui sont exécutées à chaque clic de bouton?

Non. Si vous voulez voir quelle commande est émise dans le langage de programmation de cette application lorsque vous appuyez sur un bouton ou cliquez sur des éléments de la fenêtre, ce n'est pas possible. Lisez le code source de l'application, s'il est possible de l'obtenir. Vous pouvez utiliser dconf watch / pour voir quels paramètres sont modifiés, mais pas comment procéder.

Techniquement, si vous savez utiliser un débogueur, lire des adresses de mémoire et connaître un langage d'assemblage, vous pouvez savoir ce qu'une application fait au niveau de la CPU et de la mémoire. C'est ce que l'on appelle l'ingénierie inverse des logiciels. Les professionnels de la sécurité l'utilisent fréquemment pour analyser les logiciels malveillants et découvrir les vulnérabilités des logiciels légitimes.

Ces applications ouvrent-elles un terminal en arrière-plan et exécutent-elles ces commandes?

Non, il n'y a pas de terminal attaché. De nombreux programmes savent où se trouve la base de données dconfde l'utilisateur et y écrivent. Il existe également un bus de communication interprocessus appelé dbusname__, où les programmes peuvent envoyer des signaux, et un programme sera du type "Hé, c'est un message pour moi!"

Addenda

  • Les applications peuvent-elles exécuter d'autres applications? Oui, cela s'effectue via les appels système fork() et execve() standard. L’essence même de la création de processus sur Linux et d’autres systèmes * nix repose en grande partie sur ces deux éléments. Le mécanisme de shell pour exécuter des commandes non intégrées utilise cela en particulier. Quand vous courez de manière interactive

    $ ls 
    

    le shell créera un nouveau processus via fork(), ce processus exécutera execve() qui démarrera lsname__. En raison de la façon dont execve() ce nouveau processus créé sera lsname__. L’appel système pipe() permet de relire la sortie de lsname__. Je suggère fortement de lire ma réponse pour Quelle est la différence entre le canal et la redirection pour comprendre le fonctionnement du mécanisme de canal - ce n'est pas seulement l'opérateur |, mais en fait un appel système.

  • Les applications peuvent-elles exécuter des commandes Shell? Non. La syntaxe de Shell n'est comprise que par Shell lui-même. Ce que vous pouvez faire, cependant, est de démarrer un shell avec un commutateur -c en ligne de commande et de fournir les commandes appropriées. Ceci est souvent utilisé pour les raccourcis personnalisés définis dans GNOME ou d'autres environnements de bureau, car les raccourcis personnalisés fonctionnent sur les exécutables et qu'il n'y a pas de shell pour comprendre la syntaxe. Ainsi, à titre d'exemple, vous feriez bash -c 'xdotool key Ctrl+Alt+T' pour exécuter indirectement la commande xdotoolou bash -c 'cd $HOME/Desktop; touch New_File' pour créer un nouveau fichier sur le bureau via un raccourci. Ceci est un exemple particulièrement intéressant car vous pouvez utiliser une variable Shell, puisque vous utilisez explicitement un Shell.

35

Espionner ce qui se passe

La plupart des fonctions de ces éditeurs de paramètres peuvent être visionnées en exécutant

dconf watch /

dans un terminal.

gsettings

De plus, la plupart du temps, pour obtenir ce que vous voyez avec la commande ci-dessus, ces applications devront éditer la base de données dconf (plus loin ci-dessous). Cela peut être fait soit directement , en utilisant les options cli de dconf (ce qui n'est pas recommandé), ou en exécutant la commande les commandes gsettings correspondantes, comme celle que vous avez mentionnée.

Pour exécuter ces commandes, aucune fenêtre de terminal n'est nécessaire, comme vous pouvez le voir dans les exemples.

About, gsettings, dconf et la base de données dconf

gsettings est l'interface CLI de dconf, qui à son tour édite la base de données dconf, où la plupart des paramètres sont stockés, au format binaire. Voir aussi cette belle réponse .

La base de données dconf, à propos, peut également être modifiée à partir de l'interface graphique à l'aide de l'éditeur dconf, qui se trouve dans les référentiels:

enter image description here

Échantillons de travail

une. En python

enter image description here

Pour vous montrer ce qui se passe sous le capot, sous un échantillon de travail, basculez votre position de lanceur depuis l'interface graphique en un seul bouton (bascule):

#!/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()
  • Collez le code dans un file.py vide
  • lancez le par la commande:

    python3 /path/to/file.py
    

...et amusez-vous.

b. Icône lanceur

Même un simple lanceur peut faire le travail à partir de l'interface graphique:

enter image description here

[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
  • Collez le code dans un fichier vide, enregistrez-le sous setlauncher.desktop
  • Faites-le glisser sur le lanceur et faites un clic droit

Pour une utilisation permanente, stockez-le dans ~/.local/share/applications (pour une utilisation locale) ou ~/usr/share/applications pour tous les utilisateurs.

21
Jacob Vlijm