O aplicativo baseado em GUI executa comandos do shell em segundo plano?

29

Eu migrei para o Ubuntu 16.04 há apenas 2 dias do Windows. Gosto da maneira como podemos personalizar o Unity Desktop. Estou apenas brincando com a aparência do ambiente de área de trabalho. Assim como no Windows, eu queria que o lançador estivesse na parte inferior da tela. No Google, encontrei um comando que se parece com:

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

Além disso, existem o unity-tweak-tool e o editor dconf para fazer o trabalho. Mas essa é a abordagem da GUI para fazer as coisas.

Minhas perguntas são:

  • Esses aplicativos baseados em GUI também executam o mesmo comando em segundo plano?
  • Como dar uma espiada no trabalho interno desses aplicativos? Quero dizer, existe alguma maneira de realmente olhar para os comandos que estão sendo executados a cada clique do botão?
  • Esses aplicativos abrem um terminal em segundo plano e executam esses comandos?

A resposta aqui mostra como obter o descritor de arquivo padrão do processo. Mas, não recebi nada na saída.

Além disso, o strace -p pid -o output.txtcomando lança uma enorme quantidade de texto no arquivo.

Então, em resumo, fazer as coisas usando aplicativos GUI é o mesmo que fazer coisas na linha de comando?

ptmdevncoder
fonte

Respostas:

35

Esses aplicativos baseados em GUI também executam o mesmo comando em segundo plano?

Sim e não. Eles escrevem no dconfbanco de dados de configurações, mas podem estar usando maneiras diferentes de fazer isso. Os programas escritos em Python provavelmente usarão o gi.repository.Giomódulo (eu sei porque o uso muito) ou podem usar gsettingscomo um comando externo chamando subprocess.Popen(['gsettings','org.some.schema','some-key','value']), e basicamente serão executados como um comando shell. O programa AC usará algo semelhante, provavelmente uma gio.hbiblioteca, ou pode até usar a exec()família de funções para fazer o mesmo Popenque em python. Então, para responder à sua pergunta do título: "O aplicativo baseado em GUI executa comandos do shell em segundo plano?" Eles podem, mas provavelmente não é necessário porque existe uma biblioteca para qualquer idioma em que o aplicativo esteja escrito e provavelmente será um pouco mais rápido usar uma função de biblioteca do que gerar um novo processo.

Para dar uma amostra de como isso é feito com bibliotecas / módulos, fique à vontade para dar uma olhada no código-fonte do meu indicador da lista de iniciantes. Lá, escrevi uma função para criar uma instância da Gio.Settingsclasse e depois usá-la para modificar o iniciador do Unity, dependendo do tipo de lista que você deseja ter lá.

Como dar uma espiada no trabalho interno desses aplicativos? Quero dizer, existe alguma maneira de realmente olhar para os comandos que estão sendo executados a cada clique do botão?

Não. Se você deseja ver qual comando é emitido na linguagem de programação desse aplicativo, ao pressionar um botão ou clicar nos elementos da janela, isso não é possível. Leia o código fonte do aplicativo, se for possível obtê-lo. Você pode usar dconf watch /para ver quais configurações estão sendo alteradas, mas não como são feitas.

Tecnicamente, se você souber operar um depurador, ler endereços de memória e conhecer alguma linguagem assembly, poderá saber o que um aplicativo faz no nível da CPU e da memória. Isso é conhecido como engenharia reversa de software e é frequentemente usado por profissionais de segurança para analisar software malicioso e descobrir vulnerabilidades em software legítimo.

Esses aplicativos abrem um terminal em segundo plano e executam esses comandos?

Não, não há terminal conectado. Muitos programas sabem onde o dconfbanco de dados do usuário está localizado e gravam nele. Há também um barramento de comunicação entre processos conhecido como dbus, onde os programas podem enviar sinais, e um programa será como "Ei, isso é uma mensagem para mim!"

Termo aditivo

  • Os aplicativos podem executar outros aplicativos? Sim, isso é feito por meio de chamadas padrão fork()e do execve()sistema. A essência da criação de processos no Linux e em outros sistemas * nix é amplamente baseada nesses dois. O mecanismo do shell para executar comandos não integrados usa muito isso em particular. Quando você executa interativamente

    $ ls 
    

    o shell criará um novo processo via fork(), esse processo será executado execve() e será iniciado ls. Por causa de como será execve()esse novo processo bifurcado ls. A pipe()chamada do sistema é o que ajudará a ler a saída de ls. Eu sugiro fortemente que leia minha resposta para Qual é a diferença entre canal e redirecionamento para entender como o mecanismo de canal funciona - não é apenas |operador, mas na verdade um syscall.

  • Os aplicativos podem executar comandos do shell? Não. A sintaxe do shell é entendida apenas pelo próprio shell. O que você pode fazer, no entanto, é iniciar um shell com uma -copção de linha de comando e fornecer os comandos apropriados. Isso geralmente é usado para atalhos personalizados definidos no GNOME ou em outros ambientes da área de trabalho, já que atalhos personalizados operam em executáveis ​​e não há shell para entender a sintaxe. Assim, como exemplo, você faria bash -c 'xdotool key Ctrl+Alt+T'para executar indiretamente o xdotoolcomando ou bash -c 'cd $HOME/Desktop; touch New_File'criar um novo arquivo na área de trabalho via atalho. Este é um exemplo particularmente interessante, pois você pode usar uma variável de shell, pois está usando um shell explicitamente.

Sergiy Kolodyazhnyy
fonte
2
Muito obrigado à @Serg pela explicação detalhada e por responder a cada pergunta separadamente e sistematicamente!
ptmdevncoder
@Logan meu prazer, sempre feliz em ajudar :) #
Sergiy Kolodyazhnyy
1
Felizmente, a fonte das ferramentas mencionadas está disponível, pois são FLOSS. Portanto, eu diria que revertê-los é um pouco exagerado neste caso. :)
Andrea Lazzarotto
1
@AndreaLazzarotto Sim, Unity Tweak Tool e editor Dconf - eles são de código aberto, então não há necessidade de fazer engenharia reversa. Na minha resposta, mantive tudo muito geral e tentei cobrir não apenas essas ferramentas, mas outras possibilidades #
Sergiy Kolodyazhnyy 15/11
Mais rápido raramente é o ponto para aplicativos de GUI. Escapar ou organizar os valores para uso com uma ferramenta shell é entediante, fácil de errar e sem sentido se você puder simplesmente usar a biblioteca. Re depuração: se o aplicativo estiver instalado com símbolos de depuração e escrito em um idioma suportado pelo gdb (no debian, por exemplo, instalando um pacote -dbg correspondente), você não precisará conhecer o assembler: o gdb mostrará o código-fonte usando o informações de depuração enquanto você percorre o aplicativo. O que será mais difícil é encontrar um ponto de entrada adequado para iniciar a depuração, por causa do clichê chato da GUI.
Jonas Schäfer
21

Espionando o que acontece

A maior parte do que esses editores de configurações fazem pode ser assistida executando

dconf watch /

em um terminal.

gsettings

Também na maioria das vezes, para alcançar o que você vê acontecendo com o comando acima, esses aplicativos precisarão editar o dconfbanco de dados (mais abaixo). Isso pode ser feito diretamente , usando as opções cli do dconf (o que não é preferido) ou executando os gsettingscomandos correspondentes , como o que você mencionou.

Para executar esses comandos, nenhuma janela de terminal é necessária, como você pode ver nos exemplos.

Sobre, gsettings, dconf e o banco de dados dconf

gsettingsé o front end do cli que dconf, por sua vez, edita o dconfbanco de dados, onde a maioria das configurações está armazenada, em formato binário. Veja também esta boa resposta .

O dconfbanco de dados, a propósito, também pode ser editado a partir da GUI pelo dconfeditor, que está nos repositórios:

insira a descrição da imagem aqui

Amostras de trabalho

uma. Em python

insira a descrição da imagem aqui

Para mostrar o que acontece sob o capô, abaixo de uma amostra de trabalho para alternar a posição do iniciador da GUI em um único botão (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()
  • Cole o código em um vazio file.py
  • execute-o pelo comando:

    python3 /path/to/file.py
    

...e divirta-se.

b. Ícone do iniciador

Mesmo um iniciador simples pode fazer o trabalho na GUI:

insira a descrição da imagem aqui

[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
  • Cole o código em um arquivo vazio, salve-o como setlauncher.desktop
  • Arraste-o para o iniciador e clique com o botão direito do mouse

Para uso permanente, armazene-o ~/.local/share/applications(para uso local) ou ~/usr/share/applicationspara todos os usuários.

Jacob Vlijm
fonte
@Logan não mencioná-lo :)
Jacob Vlijm