两天前,我从 Windows 迁移到了 Ubuntu 16.04。我喜欢我们可以自定义 Unity 桌面的方式。我只是在尝试桌面环境的外观和感觉。就像在 Windows 中一样,我希望启动器位于屏幕底部。在谷歌上,我找到了一个命令,如下所示:
gsettings set com.canonical.Unity.Launcher launcher-position Bottom
另外,还有 unity-tweak-tool 和 dconf 编辑器来完成这项工作。但这些都是通过 GUI 来完成任务的方法。
我的问题是:
- 这些基于 GUI 的应用程序是否也在后台执行相同的命令?
- 如何窥视这些应用程序的内部工作?我的意思是,有没有办法真正查看每次单击按钮时正在执行的命令?
- 这些应用程序是否在后台打开终端并执行这些命令?
答案这里告诉如何获取进程的标准文件描述符。但是,我在输出中没有得到任何东西。
此外,该strace -p pid -o output.txt
命令会将大量文本放入文件中。
那么,简而言之,使用 GUI 应用程序执行的操作是否与从命令行执行的操作相同?
答案1
这些基于 GUI 的应用程序是否也在后台执行相同的命令?
是也不是。它们写入dconf
设置数据库,但它们可能使用不同的方式。用 Python 编写的程序可能会使用模块gi.repository.Gio
(我知道是因为我经常使用它),或者它们可以通过gsettings
调用来用作外部命令subprocess.Popen(['gsettings','org.some.schema','some-key','value'])
,它基本上会作为 shell 命令运行。C 程序将使用类似的东西,可能是gio.h
库,或者它甚至可以使用exec()
函数系列来执行Popen
与 Python 中相同的操作。因此,回答您的标题问题:“基于 GUI 的应用程序是否在后台执行 shell 命令?” 可以,但可能没有必要,因为无论应用程序是用什么语言编写的,都有一个库,并且使用库函数可能比生成新进程要快一些。
为了给你一个如何使用库/模块的示例,请随意查看我的源代码启动器列表指示器。我在那里编写了一个函数来创建该类的一个实例Gio.Settings
,然后根据您想要的列表类型使用它来修改 Unity 启动器。
如何窥视这些应用程序的内部工作?我的意思是,有没有办法真正查看每次单击按钮时正在执行的命令?
不可以。如果您想查看按下按钮或单击窗口元素时该应用程序的编程语言发出了哪个命令,那么这是不可能的。如果可以获取,请阅读应用程序的源代码。您可以使用它dconf watch /
来查看正在更改哪些设置,但无法查看更改方式。
从技术上讲,如果您知道如何操作调试器、读取内存地址并了解一些汇编语言,那么您就可以知道应用程序在 CPU 和内存级别上的作用。这被称为软件逆向工程,安全专业人员经常使用它来分析恶意软件并发现合法软件中的漏洞。
这些应用程序是否在后台打开终端并执行这些命令?
不,没有连接终端。许多程序知道dconf
用户的数据库位于何处并在那里写入。还有一个称为的进程间通信总线dbus
,程序可以发送信号,程序会说“嘿,这是给我的消息!”
附录
应用程序可以运行其他应用程序吗?可以,这是通过标准调用
fork()
和execve()
系统调用完成的。在 Linux 和其他 *nix 系统上创建进程的本质主要基于这两个。用于运行非内置命令的 Shell 机制特别大量地使用了它。当您以交互方式运行时$ ls
shell 将通过创建一个新进程
fork()
,该进程将运行execve()
并启动ls
。由于execve()
新分叉的进程将如何ls
。pipe()
系统调用将有助于读回的输出ls
。我强烈建议阅读我的答案管道和重定向有什么区别了解管道机制如何工作 - 它不仅仅是|
操作符,而且实际上是一个系统调用。应用程序可以运行 shell 命令吗?不能。只有 shell 本身才能理解 shell 语法。但是,你可以使用命令行开关启动 shell
-c
并提供适当的命令。这通常用于在 GNOME 或其他桌面环境中设置的自定义快捷方式,因为自定义快捷方式对可执行文件进行操作,并且没有 shell 可以理解语法。因此,作为示例,你可以bash -c 'xdotool key Ctrl+Alt+T'
间接运行xdotool
命令或bash -c 'cd $HOME/Desktop; touch New_File'
通过快捷方式在桌面上创建新文件。这是一个特别有趣的例子,因为你可以使用 shell 变量,因为你正在明确使用 shell。
答案2
监视发生的事情
这些设置编辑器的大部分操作可以通过运行来观察
dconf watch /
在终端中。
设定
此外,大多数情况下,要实现上述命令所发生的情况,这些应用程序需要编辑数据库dconf
(见下文)。这可以通过以下方式完成直接地通过使用dconf(这不是首选),或者通过运行相应的gsettings
命令,就像您提到的那样。
要运行这些命令,不需要终端窗口,正如您在示例中看到的。
关于、gsettings、dconf 和 dconf 数据库
gsettings
是 的 cli 前端dconf
,它反过来编辑dconf
数据库,其中存储了大多数二进制格式的设置。另请参阅这个很好的答案。
dconf
顺便说一下,也可以通过编辑器从 GUI 编辑数据库,编辑dconf
器位于存储库中:
工作样本
a. 在 Python 中
为了向您展示内部发生的情况,下面是一个工作示例,通过单个(切换)按钮从 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
...玩得开心。
b. 启动器图标
即使是简单的启动器也可以通过 GUI 完成这项工作:
[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
供所有用户使用。