Приложение на основе графического интерфейса выполняет команды оболочки в фоновом режиме?

29

Я перешел на Ubuntu 16.04 всего 2 дня назад из Windows. Мне нравится, как мы можем настроить Unity Desktop. Я просто играю с внешним видом рабочего стола. Как и в Windows, я хотел, чтобы панель запуска находилась внизу экрана. На Google, я нашел команду, которая выглядит так:

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

Кроме того, для выполнения этой задачи есть инструмент unity-tweak-tool и редактор dconf. Но это подход GUI для достижения цели.

Мои вопросы:

  • Эти приложения на основе графического интерфейса также выполняют ту же команду в фоновом режиме?
  • Как заглянуть во внутреннюю работу этих приложений? Я имею в виду, есть ли способ на самом деле смотреть на команды, которые выполняются при каждом нажатии кнопки?
  • Эти приложения открывают терминал в фоновом режиме и выполняют эти команды?

Ответ здесь говорит о том, как получить стандартный дескриптор файла процесса. Но я ничего не получил в выводе.

Более того, strace -p pid -o output.txtкоманда выбрасывает в файл огромное количество текста.

Итак, короче говоря, делать вещи с использованием приложений с графическим интерфейсом так же, как делать вещи из командной строки?

ptmdevncoder
источник

Ответы:

35

Эти приложения на основе графического интерфейса также выполняют ту же команду в фоновом режиме?

Да и нет. Они пишут в dconfбазу данных настроек, но могут использовать разные способы для этого. Программы, написанные на Python, вероятно, будут использовать gi.repository.Gioмодуль (я знаю, потому что я часто его использую), или вместо этого они могут использовать его gsettingsкак внешнюю команду, вызывая ее subprocess.Popen(['gsettings','org.some.schema','some-key','value']), и он будет в основном работать как команда оболочки. Программа AC будет использовать нечто подобное, скорее всего, gio.hбиблиотеку, или она может даже использовать exec()семейство функций для того же, что Popenи в python. Итак, чтобы ответить на ваш заглавный вопрос: "Приложение на основе графического интерфейса выполняет команды оболочки в фоновом режиме?" Они могут, но, вероятно, в этом нет необходимости, потому что есть библиотека для любого языка, на котором написано приложение, и, вероятно, будет немного быстрее использовать библиотечную функцию, чем порождать новый процесс.

Чтобы дать вам пример того, как это делается с библиотеками / модулями, не стесняйтесь взглянуть на исходный код индикатора моего списка запуска. Там я написал функцию для создания экземпляра Gio.Settingsкласса, а затем использую его для изменения модуля запуска Unity в зависимости от типа списка, который вы хотите иметь там.

Как заглянуть во внутреннюю работу этих приложений? Я имею в виду, есть ли способ на самом деле смотреть на команды, которые выполняются при каждом нажатии кнопки?

Нет. Если вы хотите увидеть, какая команда выполняется на языке программирования этого приложения, когда вы нажимаете кнопку или нажимаете на элементы окна, это невозможно. Прочитайте исходный код приложения, если есть возможность его получить. Вы можете использовать, dconf watch /чтобы увидеть, какие настройки меняются, а не как это делается.

Технически, если вы знаете, как работать с отладчиком, читать адреса памяти и знать некоторый язык ассемблера, то вы можете знать, что приложение делает на уровне процессора и памяти. Это называется реверс-инжинирингом программного обеспечения и часто используется специалистами по безопасности для анализа вредоносного программного обеспечения и обнаружения уязвимостей в легальном программном обеспечении.

Эти приложения открывают терминал в фоновом режиме и выполняют эти команды?

Нет, нет подключенного терминала. Многие программы знают, где находится dconfбаза данных для пользователя и пишут туда. Существует также межпроцессная коммуникационная шина, известная как dbus, где программы могут отправлять сигналы, и программа будет выглядеть как «Эй, это сообщение для меня!»

добавление

  • Могут ли приложения запускать другие приложения? Да, это делается с помощью стандартных fork()и execve()системных вызовов. Суть создания процессов в Linux и других * nix системах в значительной степени основана на этих двух. Механизм оболочки для запуска не встроенных команд использует это особенно. Когда вы работаете в интерактивном режиме

    $ ls 
    

    оболочка создаст новый процесс через fork(), этот процесс будет запущен, execve() который запустится ls. Из-за того execve(), каким будет этот новый раздвоенный процесс ls. pipe()Системный вызов , что поможет считан выходу ls. Я настоятельно рекомендую прочитать мой ответ «В чем разница между конвейером и перенаправлением, чтобы понять, как работает конвейерный механизм - это не просто |оператор, а фактически системный вызов».

  • Могут ли приложения запускать команды оболочки? Нет. Синтаксис оболочки понимается только самой оболочкой. Однако вы можете запустить оболочку с параметром командной строки -cи предоставить соответствующие команды. Это часто используется для пользовательских ярлыков, установленных в GNOME или других средах рабочего стола, поскольку настраиваемые ярлыки работают на исполняемых файлах, и нет оболочки для понимания синтаксиса. Таким образом, в качестве примера, вы могли бы сделать bash -c 'xdotool key Ctrl+Alt+T'косвенный запуск xdotoolкоманды или bash -c 'cd $HOME/Desktop; touch New_File'создать новый файл на рабочем столе с помощью ярлыка. Это особенно интересный пример, поскольку вы можете использовать переменную оболочки, поскольку вы используете оболочку явно.

Сергей Колодяжный
источник
2
Большое спасибо @Serg за подробное объяснение и ответы на каждый вопрос отдельно и систематически!
ptmdevncoder
@Logan с удовольствием, всегда рад помочь :)
Сергей Колодяжный
1
К счастью, источник упомянутых инструментов доступен, так как они FLOSS. Поэтому я бы сказал, что их изменение в этом случае немного излишне. :)
Андреа Лаззаротто
1
@AndreaLazzarotto Да, Unity Tweak Tool и редактор Dconf - это программы с открытым исходным кодом, поэтому нет необходимости их перепроектировать. В своем ответе я держал все в общих чертах и ​​старался охватить не только эти инструменты, но и другие возможности
Сергей Колодяжный
Быстрее редко дело в приложениях с графическим интерфейсом. Экранирование или маршалинг значений для использования с инструментом оболочки утомителен, легко ошибиться и бессмысленно, если вы можете просто использовать библиотеку. Повторная отладка: если приложение установлено с символами отладки и написано на языке, поддерживаемом gdb (например, в debian путем установки соответствующего пакета -dbg), вам не нужно знать ассемблер: gdb покажет вам исходный код, используя Отладочная информация при выполнении приложения. Что будет сложнее, так это найти подходящую точку входа для начала отладки из-за скучного шаблона графического интерфейса пользователя.
Йонас Шефер
21

Следите за происходящим

Большинство из этих редакторов настроек можно посмотреть, запустив

dconf watch /

в терминале.

gsettings

Кроме того, в большинстве случаев для достижения того, что вы видите с помощью приведенной выше команды, эти приложения должны будут редактировать dconfбазу данных (подробнее ниже). Это можно сделать либо напрямую , используя параметры cli dconf (что не является предпочтительным), либо запустив соответствующие gsettingsкоманды, такие как упомянутая вами.

Для запуска этих команд окно терминала не требуется, как вы можете видеть в примерах.

О, gsettings, dconf и база данных dconf

gsettingsэто клиентский интерфейс dconf, который в свою очередь редактирует dconfбазу данных, в которой хранится большинство настроек, в двоичном формате. Смотрите также этот хороший ответ .

dconfБазы данных, кстати, также могут быть изменены с помощью графического интерфейса с помощью dconfредактора, который находится в хранилищах:

введите описание изображения здесь

Рабочие образцы

а. В питоне

введите описание изображения здесь

Чтобы показать вам, что происходит под капотом, под рабочим образцом для переключения позиции запуска из графического интерфейса пользователя с помощью одной (кнопки) переключения:

#!/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()
  • Вставьте код в пустой file.py
  • запустите его командой:

    python3 /path/to/file.py
    

...и получать удовольствие.

б. Значок запуска

Даже простой лаунчер может сделать работу из графического интерфейса:

введите описание изображения здесь

[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
  • Вставьте код в пустой файл, сохраните его как setlauncher.desktop
  • Перетащите его на панель запуска и щелкните правой кнопкой мыши

Для постоянного использования сохраните его ~/.local/share/applications(для локального использования) или ~/usr/share/applicationsдля всех пользователей.

Якоб Влейм
источник
@Logan не упоминай об этом :)
Джейкоб Влейм