我的电脑上有 Ubuntu,并且正在运行超棒的窗口管理器。如何检查我正在运行哪个终端?有命令吗?
答案1
总结
- 查找当前正在运行的 shell 使用
ls -l /proc/$$/exe
- 要查找当前正在运行的终端,请使用
xprop _NET_WM_PID WM_CLASS
。 稍后可以将 的值pid
传递给ps -p <pid> -o args
命令。 从技术上讲,对于终端仿真器,你甚至不需要命令,如评论:
您说的“哪个”是什么意思?单击“帮助 --> 关于”,是这个吗?–小丑
Shell 与终端
首先我们需要弄清楚的是到底在问什么——找出正在运行的 shell 或正在运行的终端。这两个术语通常可以互换使用,但它们完全是不同的东西。Shell 是命令行解释器,具体来说,交互式 shell 是提示符加上您输入命令的文本字段。Shell 也可以是非交互式的,例如,脚本启动非交互式 shell,或者bash -c 'echo hello world'
也启动非交互式 shell。
相比之下,终端是 shell 的接口(尽管它也可能是另一个应用程序)。最初,终端指的是实际的硬件,但现在它们大多是软件。当您按下Ctrl+ Alt+t或单击 GUI 中的终端图标时,您将看到启动终端仿真器,这是一个模拟硬件行为的窗口,您可以在该窗口中看到 shell 正在运行。Ctrl+ Alt+ F2(或 6 个功能键中的任何一个)将打开虚拟控制台,又名tty
。我建议阅读为什么虚拟终端是“虚拟的”,而“真实”终端是什么/为什么/在哪里?了解更多具体信息。
获取 shell 信息
每个用户都有一个为其用户名分配的默认 shell /etc/passwd
。假设您使用默认配置,并且没有明确地将另一个 shell 用作命令,则只需执行以下操作即可:
echo $SHELL
但这当然只表明默认值。假设我们执行以下操作:
user@ubuntu:~$ dash
$
我们原本在bash
,但开始了互动环节/bin/dash
,Ubuntu 的 POSIX 或系统 shell。变量$SHELL
不会改变,因为这不是它的用途 - 它显示的是默认值而不是当前值。我们需要从另一个角度来处理这个问题 - 进程的角度,这是我在“我使用的是 bash 还是 sh?”中介绍过的内容。
$ echo $$
4824
$ cat /proc/4824/comm
mksh
$ bash
xieerqi@eagle:~$ echo $$
6197
xieerqi@eagle:~$ cat /proc/6197/comm
bash
这里我们利用了/proc/
文件系统。进程的名称和命令行参数显示在 中/proc/<pid>/comm
。我们只需要提供 shell 的 PID,这就是它的作用$$
。在上面的例子中,我单独添加了它,但没有什么可以阻止我们这样做
cat /proc/$$/comm
主题的变化也可以是
ps -p $$ -o args
另一种方法是检查 where /proc/<pid>/exe
。此文件是指向可执行文件的符号链接。因此我们可以这样做
user@ubuntu:~$ ls -l /proc/$$/exe
lrwxrwxrwx 1 adminx adminx 0 Apr 4 18:20 /proc/1241/exe -> /bin/bash
user@ubuntu:~$ sh
$ ls -l /proc/$$/exe
lrwxrwxrwx 1 adminx adminx 0 Apr 4 18:20 /proc/1255/exe -> /bin/dash
这两种方法在 99% 的情况下都有效。当然,有些方法可以被破坏。例如,如果在 shell 启动后不久删除了可执行文件,则符号链接将不会指向任何地方(在这种情况下,您可能会遇到系统问题,因为不建议删除/bin/sh
、/bin/dash
甚至/bin/bash
- 毕竟很多脚本都依赖它们,尤其是系统级脚本)。shell 的命令名称通常设置为 syscall 中的第一个参数execve()
。这在bash 如何知道它是如何被调用的?,因此如果您有一个通过 启动 shell 的应用程序execve()
,则可以为其指定任何名称。但这些都是非标准和非典型的东西,为了一致性和安全性,应该避免。
获取终端信息
我们可以从环境变量开始。许多终端似乎将自己伪装成-compatible,这由或xterm
报告。但是环境变量并不是非常可靠的工具。它们可以设置和取消设置。我们可以再次对 PID 执行相同的操作,但这次我们将查看父 PID。您可能还记得,终端是 shell 的接口,通常会启动 shell 本身。因此,我们可以找出哪个进程是我们的 shell 的父进程:echo $TERM
echo $COLORTERM
$ ps -p $$ -o args,ppid
COMMAND PPID
bash 1234
$ ps -p 1234 -o args
COMMAND
/usr/lib/gnome-terminal/gnome-terminal-server
让我们尝试使用另一个终端应用程序sakura
:
$ ps -p $$ -o args,ppid
COMMAND PPID
/bin/bash 16950
$ ps -p 16950 -o args
COMMAND
sakura
从那里我们已经可以看到启动此 shell 的是gnome-terminal
。当然,如果您使用的是交互式 shell,此方法将有效。例如,如果我们试图找出 的父级bash -c '...'
或通过 启动的 shell ssh
,PID 很可能来自非终端应用程序,甚至可能根本不是 GUI。
因此,如果我们想专门处理 GUI 终端,我们可以做的是运行xprop
,单击所需的窗口,grep 其 pid,并找出与 pid 匹配的进程名称。或者换句话说:
$ ps aux | grep $(xprop | awk -F'=' '/PID/ {print $2}')
xieerqi 2124 0.6 1.7 208068 34604 ? Sl 18:47 1:49 gnome-terminal
此外,作为按规格,窗口管理器应该设置WM_CLASS
属性。因此,我们也可以从以下位置获取xprop
:
$ xprop WM_CLASS
WM_CLASS(STRING) = "sakura", "Sakura"
当然,这也有其 1% 的缺点:设置WM_CLASS
属性依赖于窗口管理器,并且 PID 不能保证窗口的准确性(请参阅什么过程创建了这个 X11 窗口?),这可能涉及复杂的调试。这些不是方法本身的缺点,而是 X11 服务器的缺点。但是,大多数稳定且知名的窗口管理器(如 openbox、Metacity、blackbox)和大多数应用程序都运行良好,因此我们不应该期望 Gnome Terminal 或 Terminator 之类的东西会出现问题。
但是当谈到 GUI 终端仿真器时,我们甚至不需要查找命令。我们可以直接使用About
窗口本身的对话框。但该规则的例外是xterm
。
答案2
如果你想知道你正在使用的终端程序,请使用以下命令:
ps -o 'cmd=' -p $(ps -o 'ppid=' -p $$)
打开终端(shell)后立即运行此命令无需分叉任何其他 shell 实例。
当你打开终端程序时,它基本上会生成一个子程序,即 shell。因此,生成的 shell 的父级是终端本身。换句话说,shell 的 PPID 是终端程序的 PID。
这里我们通过 找到 shell 的父进程 ID (PPID)(bash
)ps -o 'ppid=' -p $$
,它将是终端程序的进程 ID。
然后我们从 PID 中找到进程名称:
$ ps -o 'cmd=' -p $(ps -o 'ppid=' -p $$)
gnome-terminal
它基本上是一行代码:
$ ps -o 'ppid=' -p $$
2268
$ ps -o 'cmd=' -p 2268
gnome-terminal
答案3
简短版本(谢谢@Serg)
cat /etc/alternatives/x-terminal-emulator
长版本
sudo update-alternatives --config x-terminal-emulator
*
并在输出中查找
;)
示例输出
There are 7 alternatives which provide `x-terminal-emulator’.
选择方案 ———————————————– 1 /usr/bin/xterm 2 /usr/bin/uxterm 3 /usr/bin/koi8rxterm 4 /usr/bin/lxterm *+ 5 /usr/bin/gnome-terminal.wrapper 6 /usr/bin/konsole 7 /usr/bin/xfce4-terminal.wrapper
Press enter to keep the default[*], or type selection number:
或者,得益于@muru,下面是更详细的输出
$ update-alternatives --display x-terminal-emulator
x-terminal-emulator - auto mode
link currently points to /usr/bin/gnome-terminal.wrapper
/usr/bin/gnome-terminal.wrapper - priority 40
slave x-terminal-emulator.1.gz: /usr/share/man/man1/gnome-terminal.1.gz
/usr/bin/koi8rxterm - priority 20
slave x-terminal-emulator.1.gz: /usr/share/man/man1/koi8rxterm.1.gz
/usr/bin/lxterm - priority 30
slave x-terminal-emulator.1.gz: /usr/share/man/man1/lxterm.1.gz
/usr/bin/mate-terminal.wrapper - priority 30
slave x-terminal-emulator.1.gz: /usr/share/man/man1/mate-terminal.1.gz
/usr/bin/uxterm - priority 20
slave x-terminal-emulator.1.gz: /usr/share/man/man1/uxterm.1.gz
/usr/bin/xterm - priority 20
slave x-terminal-emulator.1.gz: /usr/share/man/man1/xterm.1.gz
Current 'best' version is '/usr/bin/gnome-terminal.wrapper'.
答案4
如果您只想要终端程序的名称,您很可能会在“帮助”>“关于”下找到它。