Le applicazioni basate sulla GUI eseguono comandi shell in background?


29

Sono migrato su Ubuntu 16.04 solo 2 giorni fa da Windows. Mi piace il modo in cui possiamo personalizzare Unity Desktop. Sto solo giocando con l'aspetto grafico dell'ambiente desktop. Proprio come in Windows, volevo che il launcher fosse nella parte inferiore dello schermo. Su Google, ho trovato un comando simile al seguente:

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

Inoltre, ci sono lo strumento unity-tweak-tool e l'editor dconf per portare a termine il lavoro. Ma questi sono gli approcci della GUI per fare le cose.

Le mie domande sono:

  • Queste applicazioni basate su GUI eseguono anche lo stesso comando in background?
  • Come dare un'occhiata al funzionamento interno di queste applicazioni? Voglio dire, c'è un modo per guardare effettivamente i comandi che vengono eseguiti ad ogni clic del pulsante?
  • Queste applicazioni aprono un terminale in background ed eseguono questi comandi?

La risposta qui spiega come ottenere il descrittore di file standard del processo. Ma non ho ricevuto nulla nell'output.

Inoltre, il strace -p pid -o output.txtcomando lancia una grande quantità di testo nel file.

Quindi, in breve, fare le cose usando le applicazioni della GUI equivale a fare cose dalla riga di comando?

Risposte:


35

Queste applicazioni basate su GUI eseguono anche lo stesso comando in background?

Sì e no. Scrivono nel dconfdatabase delle impostazioni, ma potrebbero utilizzare diversi modi per farlo. I programmi scritti in Python useranno probabilmente il gi.repository.Giomodulo (lo so perché lo uso molto) o possono invece usare gsettingscome comando esterno chiamando subprocess.Popen(['gsettings','org.some.schema','some-key','value'])e in pratica verrà eseguito come comando shell. Il programma AC userà qualcosa di simile, probabilmente una gio.hlibreria, o potrebbe persino usare la exec()famiglia di funzioni per fare lo stesso Popendi Python. Quindi, per rispondere alla domanda del titolo: "L'applicazione basata sulla GUI esegue i comandi della shell in background?" Possono, ma probabilmente non è necessario perché esiste una libreria per qualsiasi lingua in cui è scritta l'app, e probabilmente sarà un po 'più veloce usare una funzione di libreria, piuttosto che generare un nuovo processo.

Per darti un esempio di come è fatto con le librerie / i moduli, non esitare a dare un'occhiata al codice sorgente del mio indicatore dell'elenco di avvio. Lì ho scritto una funzione per creare un'istanza della Gio.Settingsclasse e quindi utilizzarla per modificare il programma di avvio di Unity a seconda del tipo di elenco che si desidera avere lì.

Come dare un'occhiata al funzionamento interno di queste applicazioni? Voglio dire, c'è un modo per guardare effettivamente i comandi che vengono eseguiti ad ogni clic del pulsante?

No. Se vuoi vedere quale comando viene emesso nel linguaggio di programmazione di quell'app quando premi un pulsante o fai clic sugli elementi della finestra, non è possibile. Leggi il codice sorgente dell'applicazione, se è possibile ottenerlo. Puoi usare dconf watch /per vedere quali impostazioni vengono modificate, ma non come è stato fatto.

Tecnicamente, se sai come gestire un debugger, leggere gli indirizzi di memoria e conoscere un po 'di linguaggio assembly, puoi sapere cosa fa un'app a livello di CPU e memoria. Questo è noto come reverse engineering del software ed è spesso utilizzato dai professionisti della sicurezza per analizzare software dannoso e rilevare vulnerabilità nel software legittimo.

Queste applicazioni aprono un terminale in background ed eseguono questi comandi?

No, non è collegato alcun terminale. Molti programmi sanno dove si trova il dconfdatabase per l'utente e scrivono lì. C'è anche un bus di comunicazione tra processi noto come dbus, in cui i programmi possono inviare segnali e un programma sarà come "Ehi, questo è un messaggio per me!"

appendice

  • Le applicazioni possono eseguire altre applicazioni? Sì, ciò avviene tramite chiamate standard fork()e di execve()sistema. L'essenza della creazione di processi su Linux e altri sistemi * nix si basa in gran parte su questi due. Il meccanismo di shell per l'esecuzione di comandi non integrati lo utilizza molto in particolare. Quando corri in modo interattivo

    $ ls 
    

    la shell creerà un nuovo processo tramite fork(), verrà eseguito quel processo execve() che inizierà ls. A causa di come sarà execve()quel nuovo processo biforcuto ls. La pipe()chiamata di sistema è ciò che aiuterà a rileggere l'output di ls. Consiglio vivamente di leggere la mia risposta su Qual è la differenza tra pipe e reindirizzamento per capire come funziona il meccanismo di pipe: non è solo un |operatore, ma in realtà un syscall.

  • Le applicazioni possono eseguire comandi shell? No. La sintassi della shell è compresa solo dalla shell stessa. Quello che puoi fare, tuttavia, è avviare una shell con un'opzione da riga di comando -ce fornire comandi appropriati. Questo è spesso usato per le scorciatoie personalizzate impostate in GNOME o altri ambienti desktop, poiché le scorciatoie personalizzate funzionano su eseguibili e non c'è shell per capire la sintassi. Quindi, ad esempio, dovresti eseguire bash -c 'xdotool key Ctrl+Alt+T'indirettamente il xdotoolcomando o bash -c 'cd $HOME/Desktop; touch New_File'creare un nuovo file sul desktop tramite il collegamento. Questo è un esempio particolarmente interessante in quanto puoi usare una variabile di shell, poiché stai usando esplicitamente una shell.


2
Grazie mille @Serg per la spiegazione dettagliata e per aver risposto a ciascuna domanda separatamente e sistematicamente!
ptmdevncoder

@Logan è un piacere, sempre felice di aiutarti :)
Sergiy Kolodyazhnyy

1
Fortunatamente, la fonte per gli strumenti citati è disponibile poiché sono FLOSS. Quindi direi che invertirli è un po 'eccessivo in questo caso. :)
Andrea Lazzarotto,

1
@AndreaLazzarotto Yep, Unity Tweak Tool e l'editor Dconf: quelli sono open source, quindi non c'è bisogno di decodificare quelli. Nella mia risposta ho mantenuto tutto molto generale e ho cercato di coprire non solo quegli strumenti, ma altre possibilità
Sergiy Kolodyazhnyy,

Più veloce è raramente il punto per le applicazioni GUI. L'escape o il marshalling dei valori da utilizzare con uno strumento shell è noioso, facile da sbagliare e inutile se si può semplicemente usare la libreria. Ri-debug: se l'applicazione è installata con simboli di debug e scritta in una lingua supportata da gdb (su debian, ad esempio installando un corrispondente pacchetto -dbg), non è necessario conoscere assembler: gdb mostrerà il codice sorgente usando informazioni di debug mentre si passa attraverso l'applicazione. Ciò che sarà più difficile è trovare un punto di ingresso adeguato da cui iniziare il debug, a causa della noiosa piastra della GUI.
Jonas Schäfer,

21

Spiare cosa succede

La maggior parte delle operazioni eseguite da questi editor delle impostazioni può essere eseguita eseguendo

dconf watch /

in un terminale.

gsettings

Inoltre, la maggior parte delle volte, per ottenere ciò che vedi accadere con il comando sopra, queste applicazioni dovranno modificare il dconfdatabase (più avanti). Questo può essere fatto direttamente , usando le opzioni cli di dconf (che non è preferito), o eseguendo i gsettingscomandi corrispondenti , come quello che menzioni.

Per eseguire questi comandi, non è necessaria alcuna finestra di terminale, come puoi vedere negli esempi.

Informazioni su, gsettings, dconf e il database dconf

gsettingsè il frontend di cli a dconf, che a sua volta modifica il dconfdatabase, dove sono memorizzate la maggior parte delle impostazioni, in formato binario. Vedi anche questa bella risposta .

Il dconfdatabase, a proposito, può anche essere modificato dalla GUI dconfdall'editor, che si trova nei repository:

inserisci qui la descrizione dell'immagine

Campioni di lavoro

un. In pitone

inserisci qui la descrizione dell'immagine

Per mostrarti cosa succede sotto il cofano, sotto un esempio funzionante per alternare la tua posizione di avvio dalla GUI in un unico pulsante (attiva / disattiva):

#!/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()
  • Incolla il codice in uno spazio vuoto file.py
  • eseguirlo dal comando:

    python3 /path/to/file.py
    

...e divertiti.

b. Icona di avvio

Anche un semplice lanciatore può fare il lavoro dalla GUI:

inserisci qui la descrizione dell'immagine

[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
  • Incolla il codice in un file vuoto, salvalo come setlauncher.desktop
  • Trascinalo sul lanciatore e fai clic con il tasto destro

Per uso permanente, conservarlo in ~/.local/share/applications(per uso locale) o ~/usr/share/applicationsper tutti gli utenti.


@Logan non menzionarlo :)
Jacob Vlijm
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.