29 votes

Est-ce que les applications basées sur une interface graphique exécutent des commandes shell en arrière-plan?

J'ai migré vers Ubuntu 16.04 il y a seulement 2 jours à partir de Windows. J'aime la façon dont nous pouvons personnaliser le bureau Unity. Je m'amuse juste avec l'apparence et l'ambiance de l'environnement de bureau. Tout comme dans Windows, je voulais que le lanceur soit en bas de l'écran. En cherchant sur Google, j'ai trouvé une commande qui ressemble à :

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

Il y a aussi l'outil unity-tweak-tool et l'éditeur Dconf pour accomplir la tâche. Mais ce sont des approches graphiques pour faire les choses.

Mes questions sont :

  • Ces applications basées sur GUI exécutent-elles également la même commande en arrière-plan ?
  • Comment jeter un coup d'œil sur le fonctionnement interne de ces applications ? Est-ce qu'il y a un moyen de regarder réellement les commandes qui sont exécutées à chaque clic sur un bouton ?
  • Ces applications ouvrent-elles un terminal en arrière-plan et exécutent-elles ces commandes ?

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

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

En résumé, est-ce que faire les choses à l'aide des applications GUI est la même chose que de faire des choses à partir de la ligne de commande ?

35voto

Sergiy Kolodyazhnyy Points 97292

Est-ce que ces applications basées sur une interface graphique exécutent également la même commande en arrière-plan ?

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

Pour vous donner un exemple de comment cela se fait avec des bibliothèques/modules, n'hésitez pas à jeter un œil au code source de mon indicateur de liste de lanceur. Là, j'ai écrit une fonction pour créer une instance de la classe Gio.Settings et ensuite l'utiliser pour modifier le lanceur Unity en fonction du type de liste que vous souhaitez avoir.

Comment jeter un coup d'œil au fonctionnement interne de ces applications ? Je veux dire, y a-t-il un moyen de voir les commandes qui sont exécutées à chaque clic sur un bouton ?

Non. Si vous voulez voir quelle commande est émise dans le langage de programmation de l'application lorsque vous appuyez sur un bouton ou cliquez sur des éléments de fenêtre, alors c'est impossible. Lisez le code source de l'application, si vous pouvez l'obtenir. Vous pouvez utiliser dconf watch / pour voir quels paramètres sont modifiés, mais pas comment cela se fait.

Techniquement, si vous savez comment utiliser un débogueur, lire des adresses mémoire et connaissez un peu le langage d'assemblage, alors vous pouvez savoir ce qu'une application fait au niveau du CPU et de la mémoire. C'est ce qu'on appelle l'ingénierie inverse logicielle et est souvent utilisé par les professionnels de la sécurité pour analyser les logiciels malveillants et découvrir des vulnérabilités dans les logiciels légitimes.

Est-ce que ces applications ouvrent un terminal en arrière-plan et exécutent ces commandes ?

Non, il n'y a pas de terminal attaché. Beaucoup de programmes savent où se trouve la base de données dconf de l'utilisateur et écrivent dedans. Il y a aussi un bus de communication inter-processus appelé dbus, où les programmes peuvent envoyer des signaux, et un programme dira "Hé, c'est un message pour moi !"

Additif

  • Les applications peuvent-elles exécuter d'autres applications ? Oui, c'est fait via les appels système standard fork() et execve(). L'essence de la création de processus sur Linux et d'autres systèmes *nix est largement basée sur ces deux-là. Le mécanisme de shell pour exécuter des commandes non intégrées utilise cela en particulier. Lorsque vous exécutez de manière interactive

    $ ls 

    le shell créera un nouveau processus via fork(), ce processus exécutera execve() qui démarrera ls. En raison de la manière dont execve() fonctionne, le nouveau processus forké sera ls. L'appel système pipe() aidera à lire la sortie de ls. Je vous recommande vivement de lire ma réponse pour Quelle est la différence entre le pipe et la redirection pour comprendre comment fonctionne le mécanisme de pipe - 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 du shell est uniquement comprise par le shell lui-même. Ce que vous pouvez faire, cependant, est de démarrer un shell avec l'option de ligne de commande -c et fournir les commandes appropriées. Cela est souvent utilisé pour les raccourcis personnalisés définis dans GNOME ou d'autres environnements de bureau, puisque les raccourcis personnalisés utilisent des exécutables et il n'y a pas de shell pour comprendre la syntaxe. Ainsi, par exemple, vous feriez bash -c 'xdotool key Ctrl+Alt+T' pour exécuter indirectement la commande xdotool ou bash -c 'cd $HOME/Desktop; touch New_File' pour créer un nouveau fichier sur le bureau via un raccourci. C'est un exemple particulièrement intéressant car vous pouvez utiliser une variable de shell, puisque vous utilisez un shell explicitement.

21voto

Jacob Vlijm Points 78990

Observation de ce qui se passe

La plupart de ce que font ces éditeurs de paramètres peut être observé en exécutant

dconf watch /

dans un terminal.

gsettings

La plupart du temps, pour réaliser ce que vous voyez se passer avec la commande ci-dessus, ces applications devront éditer la base de données dconf (plus bas). Cela peut être fait soit directement, en utilisant les options en ligne de commande de dconf (ce qui n'est pas préféré), ou en exécutant les commandes gsettings correspondantes, comme celle que vous mentionnez.

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

À propos de, gsettings, dconf et la base de données dconf

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

La base de données dconf, au passage, peut également être éditée depuis l'interface graphique par l'éditeur dconf, qui se trouve dans les dépôts :

enter image description here

Exemples de travail

a. En python

enter image description here

Pour vous montrer ce qui se passe en coulisses, voici un exemple de travail pour basculer la position de votre 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="Basculer")
        button = Gtk.Button("Basculez la position du lanceur")
        button.connect("clicked", self.toggle)
        self.add(button)

    def toggle(self, *args):
        # lire le paramètre actuel de la position du lanceur
        current = subprocess.check_output([
            "gsettings", "get", key[0], key[1]
            ]).decode("utf-8").strip()
        # basculer vers l'autre option
        new = "'Gauche'" if current == "'Bas'" else "'Bas'"
        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 fichier vide fichier.py

  • exécutez-le par la commande :

      python3 /chemin/vers/fichier.py

...et amusez-vous.

b. Icône du lanceur

Même un simple lanceur peut faire le travail depuis l'interface graphique :

enter image description here

[Desktop Entry]
Name=Définir la position du lanceur
Exec=zenity --info --text="Clic droit pour définir la position du lanceur"
Type=Application
StartupNotify=False
Icon=preferences-system

Actions=Lanceur en bas;Lanceur sur la gauche;

[Desktop Action Lanceur en bas]
Name=Lanceur en bas
# Option clic droit pour définir le lanceur en bas
Exec=gsettings set com.canonical.Unity.Launcher launcher-position Bas

[Desktop Action Lanceur sur la gauche]
Name=Lanceur sur la gauche
# Option clic droit pour définir le lanceur sur la gauche
Exec=gsettings set com.canonical.Unity.Launcher launcher-position Gauche
  • Collez le code dans un fichier vide, enregistrez-le sous setlauncher.desktop
  • Faites glisser l'icône sur le lanceur et cliquez dessus avec le bouton droit

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

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X