當前位置: 首頁>>技術教程>>正文


基於GUI的應用程序在後台執行shell命令嗎?

, , , , ,

問題描述

我在2天前從Windows遷移到Ubuntu 16.04。我喜歡我們自定義Unity桌麵的方式。我正在玩桌麵環境的外觀和感覺。就像在Windows中一樣,我希望啟動器位於屏幕的底部。在穀歌搜索,我發現了一個命令,如:

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

此外,還有unity-tweak-tool和dconf編輯器來完成工作。但這些是完成工作的GUI方法。

我的問題是:

  • 這些GUI-based應用程序是否也在後台執行相同的命令?

  • 如何窺探這些應用程序的內部工作?我的意思是,有沒有辦法真正查看每次點擊按鈕時執行的命令?

  • 這些應用程序是否在後台打開終端並執行這些命令?

答案here告訴如何獲取進程的標準文件描述符。但是,我在輸出中沒有得到任何東西。

此外,strace -p pid -o output.txt命令會向文件中輸入大量文本。

那麽,簡而言之,使用GUI應用程序做的事情與從命令行做事情一樣嗎?

最佳解決思路

Do these GUI-based applications also execute the same command in the background?

是的,不是。他們寫入dconf設置數據庫,但他們可能會使用不同的方法來執行此操作。用Python編寫的程序可能會使用gi.repository.Gio模塊(我知道因為我經常使用它),或者他們可以通過調用subprocess.Popen(['gsettings','org.some.schema','some-key','value'])來使用gsettings作為外部命令,它基本上將作為shell命令運行。 C程序將使用類似的東西,可能是gio.h庫,或者它甚至可以使用exec()係列函數來執行與Popen在python中相同的功能。所以回答你的標題問題:“基於GUI的應用程序在後台執行shell命令嗎?”它們可以,但可能沒有必要,因為有一個庫可以用於編寫app的任何語言,並且使用庫函數可能會比生成一個新進程快一些。

為了給你一個如何使用庫/模塊的示例,請隨時查看我的launcher list indicator.的源代碼。我已經編寫了一個函數來創建Gio.Settings類的實例,然後用它來修改Unity啟動器取決於您希望在那裏的列表類型。

How to have a peep at the internal working of these applications? I mean, is there any way of actually looking at the commands that are being executed at every click of button?

不可以。如果您想在按下按鈕或單擊窗口元素時查看該應用程序編程語言中發出的命令,則無法進行。如果可以獲得它,請閱讀應用程序的源代碼。您可以使用dconf watch /查看正在更改的設置,但不知道它是如何完成的。

從技術上講,如果您知道如何操作調試器,讀取內存地址,並了解一些匯編語言,那麽您就可以知道應用程序在CPU和內存級別上的作用。這稱為軟件逆向工程,安全專業人員經常使用它來分析惡意軟件並發現合法軟件中的漏洞。

Do these applications open up a terminal in the background and execute these commands?

不,沒有附加終端。許多程序知道用戶的dconf數據庫所在的位置並在那裏寫入。還有一個名為dbus的inter-process通信總線,程序可以發送信號,程序就像“嘿,這對我來說是個消息!”

Addendum

  • 應用可以運行其他應用嗎?是的,這是通過標準fork()execve()係統調用完成的。在Linux和其他* nix係統上創建進程的本質主要基於這兩個。用於運行non-builtin命令的Shell機製特別使用了很多。當您以交互方式運行時

    $ ls 
    

    shell將通過fork()創建一個新進程,該進程將運行execve(),它將啟動ls。因為execve()如何新的分叉過程將是lspipe()係統調用有助於回讀ls的輸出。我強烈建議閱讀我對What is the difference between pipe and redirection的回答,以了解管道機製的工作原理 – 它不僅僅是|運算符,而且實際上是一個係統調用。

  • 應用程序可以運行shell命令嗎沒有.Shell語法隻能由shell本身理解。但是,您可以使用命令行 -c開關啟動一個shell並提供適當的命令。這通常用於在GNOME或其他桌麵環境中設置的自定義快捷方式,因為自定義快捷方式對可執行文件進行操作,並且沒有shell來理解語法。因此,作為示例,您可以使用bash -c 'xdotool key Ctrl+Alt+T'間接運行xdotool命令或bash -c 'cd $HOME/Desktop; touch New_File'以通過快捷方式在桌麵上創建新文件。這是一個特別有趣的示例,因為您可以使用shell變量,因為您明確使用了shell。

次佳解決思路

間諜發生的事情

這些設置編輯器的大部分內容都可以通過運行來觀察

dconf watch /

在一個終端。

gsettings

大多數情況下,為了實現您在上麵的命令中看到的情況,這些應用程序將需要編輯dconf數據庫(下麵進一步說明)。這可以通過使用dconf(不是首選)的cli選項直接完成,也可以通過運行相應的gsettings命令(如您提到的那樣)來完成。

要運行這些命令,不需要終端窗口,如示例中所示。

關於,gsettings,dconf和dconf數據庫

gsettingsdconf的cli前端,後者編輯dconf數據庫,其中大多數設置以二進製格式存儲。另請參見this nice answer

順便說一句,dconf數據庫也可以通過dconf編輯器從GUI編輯,該編輯器位於存儲庫中:

command-line,unity,launcher,dconf,gsettings,ubuntu

工作樣本

一個。在python中

command-line,unity,launcher,dconf,gsettings,ubuntu

為了向您展示在引擎蓋下發生的事情,在工作樣本下方,在單個(切換)按鈕中切換GUI中的啟動器位置:

#!/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
    

…玩得開心。

灣啟動器圖標

即使是一個簡單的啟動器也可以從GUI完成這項任務:

command-line,unity,launcher,dconf,gsettings,ubuntu

[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

  • 將其拖到啟動器和right-click上

如需永久使用,請將其存儲在~/.local/share/applications(供本地使用)或~/usr/share/applications中供所有用戶使用。

參考資料

本文由Ubuntu問答整理, 博文地址: https://ubuntuqa.com/zh-tw/article/3092.html,未經允許,請勿轉載。