¿La aplicación basada en GUI ejecuta comandos de shell en segundo plano?

29

He migrado a Ubuntu 16.04 hace solo 2 días desde Windows. Me gusta la forma en que podemos personalizar el escritorio de Unity. Solo estoy jugando con la apariencia del entorno de escritorio. Al igual que en Windows, quería que el iniciador estuviera en la parte inferior de la pantalla. En Google, encontré un comando que dice así:

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

Además, existe la herramienta de ajuste de la unidad y el editor dconf para hacer el trabajo. Pero este es el enfoque GUI de hacer las cosas.

Mis preguntas son:

  • ¿Estas aplicaciones basadas en GUI también ejecutan el mismo comando en segundo plano?
  • ¿Cómo echar un vistazo al funcionamiento interno de estas aplicaciones? Quiero decir, ¿hay alguna forma de ver realmente los comandos que se ejecutan con cada clic del botón?
  • ¿Estas aplicaciones abren una terminal en segundo plano y ejecutan estos comandos?

La respuesta aquí dice cómo obtener el descriptor de archivo estándar del proceso. Pero no obtuve nada en la salida.

Además, el strace -p pid -o output.txtcomando arroja una gran cantidad de texto en el archivo.

Entonces, en resumen, ¿hacer cosas usando aplicaciones GUI es lo mismo que hacer cosas desde la línea de comandos?

ptmdevncoder
fuente

Respuestas:

35

¿Estas aplicaciones basadas en GUI también ejecutan el mismo comando en segundo plano?

Si y no. Escriben en la dconfbase de datos de configuraciones, pero podrían estar usando diferentes formas de hacerlo. Los programas escritos en Python probablemente usarán el gi.repository.Giomódulo (lo sé porque lo uso mucho) o en su lugar pueden usarlo gsettingscomo un comando externo llamando subprocess.Popen(['gsettings','org.some.schema','some-key','value']), y básicamente se ejecutará como un comando de shell. El programa de AC usará algo similar, probablemente una gio.hbiblioteca, o incluso podría usar la exec()familia de funciones para hacer lo mismo Popenque en Python. Entonces, para responder a la pregunta del título: "¿La aplicación basada en GUI ejecuta comandos de shell en segundo plano?" Pueden, pero es probable que no sea necesario porque hay una biblioteca para cualquier idioma en el que esté escrita la aplicación, y es probable que sea un poco más rápido usar una función de biblioteca que generar un nuevo proceso.

Para darle una muestra de cómo se hace con las bibliotecas / módulos, no dude en consultar el código fuente de mi indicador de lista de iniciadores. Allí he escrito una función para crear una instancia de la Gio.Settingsclase y luego usarla para modificar el iniciador de Unity dependiendo del tipo de lista que desee tener allí.

¿Cómo echar un vistazo al funcionamiento interno de estas aplicaciones? Quiero decir, ¿hay alguna forma de ver realmente los comandos que se ejecutan con cada clic del botón?

No. Si desea ver qué comando se emite en el lenguaje de programación de esa aplicación cuando presiona un botón o hace clic en los elementos de la ventana, entonces no es posible. Lea el código fuente de la aplicación, si es posible obtenerlo. Puede usar dconf watch /para ver qué configuraciones se están cambiando, pero no cómo se hace.

Técnicamente, si sabe cómo operar un depurador, leer direcciones de memoria y sabe algo de lenguaje ensamblador, entonces puede saber qué hace una aplicación a nivel de CPU y memoria. Esto se conoce como ingeniería inversa de software y es utilizado frecuentemente por profesionales de seguridad para analizar software malicioso y descubrir vulnerabilidades en software legítimo.

¿Estas aplicaciones abren una terminal en segundo plano y ejecutan estos comandos?

No, no hay terminal conectada. Muchos programas saben dónde se encuentra la dconfbase de datos para el usuario y escriben allí. También hay un bus de comunicación entre procesos conocido como dbus, donde los programas pueden enviar señales, y un programa será como "¡Hola, ese es un mensaje para mí!"

Apéndice

  • ¿Pueden las aplicaciones ejecutar otras aplicaciones? Sí, eso se hace a través de llamadas estándar fork()y del execve()sistema. La esencia de crear procesos en Linux y otros sistemas * nix se basa en gran medida en estos dos. El mecanismo de shell para ejecutar comandos no incorporados lo utiliza mucho en particular. Cuando corres interactivamente

    $ ls 
    

    el shell creará un nuevo proceso a través de fork(), ese proceso se ejecutará execve() y comenzará ls. Por cómo execve()será ese nuevo proceso bifurcado ls. La pipe()llamada al sistema es lo que ayudará a leer la salida de ls. Sugiero leer mi respuesta para Cuál es la diferencia entre tubería y redirección para comprender cómo funciona el mecanismo de tubería: no es solo un |operador, sino una llamada al sistema.

  • ¿Pueden las aplicaciones ejecutar comandos de shell? No. La sintaxis de Shell solo se entiende por la propia shell. Sin embargo, lo que puede hacer es iniciar un shell con un -cinterruptor de línea de comandos y proporcionar los comandos adecuados. Esto se usa a menudo para accesos directos personalizados establecidos en GNOME u otros entornos de escritorio, ya que los accesos directos personalizados operan en ejecutables y no hay un shell para comprender la sintaxis. Por lo tanto, como ejemplo, haría bash -c 'xdotool key Ctrl+Alt+T'ejecutar indirectamente el xdotoolcomando o bash -c 'cd $HOME/Desktop; touch New_File'crear un nuevo archivo en el escritorio a través de un acceso directo. Este es un ejemplo particularmente interesante ya que puede usar una variable de shell, ya que está utilizando un shell explícitamente.

Sergiy Kolodyazhnyy
fuente
2
¡Muchas gracias @Serg por la explicación detallada y por responder cada pregunta por separado y sistemáticamente!
ptmdevncoder
@Logan, es un placer, siempre me alegra ayudar :)
Sergiy Kolodyazhnyy
1
Afortunadamente, la fuente de las herramientas mencionadas está disponible ya que son FLOSS. Por lo tanto, diría que invertirlos es un poco exagerado en este caso. :)
Andrea Lazzarotto
1
@AndreaLazzarotto Yep, Unity Tweak Tool y Dconf editor: son de código abierto, por lo que no es necesario realizar ingeniería inversa. En mi respuesta, mantuve todo muy general e intenté cubrir no solo esas herramientas, sino otras posibilidades
Sergiy Kolodyazhnyy
Más rápido rara vez es el punto para aplicaciones GUI. Escapar o ordenar los valores para usar con una herramienta de shell es tedioso, fácil de equivocarse y no tiene sentido si simplemente puede usar la biblioteca. Nueva depuración: si la aplicación se instala con símbolos de depuración y está escrita en un idioma compatible con gdb (en debian, por ejemplo, instalando el paquete -dbg correspondiente), no necesita conocer el ensamblador: gdb le mostrará el código fuente utilizando depure la información mientras recorre la aplicación. Lo que será más difícil es encontrar un punto de entrada adecuado para comenzar a depurar, debido a la aburrida interfaz gráfica de usuario GUI.
Jonas Schäfer
21

Espiando lo que pasa

La mayor parte de lo que hacen estos editores de configuración se puede ver ejecutando

dconf watch /

en una terminal

gsettings

Además, la mayoría de las veces, para lograr lo que ve que sucede con el comando anterior, estas aplicaciones deberán editar la dconfbase de datos (más adelante). Esto se puede hacer directamente , usando las opciones cli de dconf (que no se prefiere), o ejecutando los gsettingscomandos correspondientes , como el que usted menciona.

Para ejecutar estos comandos, no se necesita una ventana de terminal, como puede ver en los ejemplos.

Acerca de, gsettings, dconf y la base de datos dconf

gsettingses la interfaz de usuario de cli dconf, que a su vez edita la dconfbase de datos, donde se almacena la mayoría de las configuraciones, en formato binario. Vea también esta buena respuesta .

La dconfbase de datos, por cierto, también se puede editar desde la GUI por dconfeditor, que está en los repositorios:

ingrese la descripción de la imagen aquí

Muestras de trabajo

a. En pitón

ingrese la descripción de la imagen aquí

Para mostrarle lo que sucede debajo del capó, debajo de una muestra de trabajo para alternar su posición de iniciador desde la GUI en un solo botón (alternar):

#!/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()
  • Pega el código en un espacio vacío file.py
  • ejecútelo con el comando:

    python3 /path/to/file.py
    

...y divertirse.

si. Icono de lanzador

Incluso un simple iniciador puede hacer el trabajo desde la GUI:

ingrese la descripción de la imagen aquí

[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
  • Pegue el código en un archivo vacío, guárdelo como setlauncher.desktop
  • Arrástrelo al iniciador y haga clic derecho

Para uso permanente, almacénelo en ~/.local/share/applications(para uso local) o ~/usr/share/applicationspara todos los usuarios.

Jacob Vlijm
fuente
@Logan no lo menciones :)
Jacob Vlijm