如何检查当前正在使用哪个终端仿真器?


15

我安装了gnome-terminal和Guake。我想提供不同的启动消息,以在这些终端仿真器启动时显示。我应该在.bashrc中编写哪些代码才能实现?

Answers:


10

此功能应完成以下工作:

container() {
    pid=$$
    while true; do
        pid=$(ps -h -o ppid -p $pid 2>/dev/null)
        case $(ps -h -o comm -p $pid 2>/dev/null) in
        (gnome-terminal) echo "Running in gnome terminal";return;;
        (xterm) echo "Running in xterm";return;;
        (rxvt) echo "Running in rxvt";return;;
        (python) if [ ! -z "$(ps -h -o args -p $pid 2>/dev/null | grep guake)" ]; then echo "Running in Guake"; return; fi ;;
        esac
        [[ $(echo $pid) == 1 ]] && break
    done
}
container

好答案!别忘了container在定义之后实际调用该函数。
rosch 2012年

我希望这很明显,但是您是对的,答案也进行了相应更新。
jlliagre 2012年

@jlliagre我尝试了代码。它可以在gnome终端上正常运行,但是在Guake上存在问题。它没有任何输出。相反,它就像死锁一样冻结。我必须按Ctrl + C才能使用它。不太了解代码,所以不知道哪里出了问题。
VedVals

代码固定。我错过了guake由python运行的问题,并且遇到了一个阻止该函数退出的错误。感谢您的反馈。
jlliagre 2012年

抱歉,伙计,仍然无法正常工作。给出错误bash: [: too many arguments。有bash v4.2.24,python v2.7.3(如果有帮助)。
VedVals

10

尝试这个:

echo $TERM

这更具权威性,但可能会被您的程序弄乱。但是在我的机器上,它表示xterm,在ttys上表示linux,我认为它代表Linux Console。


2
$TERM是一个变量,它指的是所使用的终端仿真器自行报告的规范,而不是实际的仿真器本身。例如,在我的系统上,即使我实际上正在运行lxterminal ,也会echo $TERM返回xterm。正在发生的是lxterminal自报告xterm合规性。lxterminal实际上并不完全符合xterm,因此必须提防。规格文件通常位于中/usr/share/terminfo
stazher '16

7

您可以通过重复父进程的名称来获得终端仿真器的名称。因此,它适用于每个终端仿真器。

在bash,zsh等中:

basename "/"$(ps -f -p $(cat /proc/$(echo $$)/stat | cut -d \  -f 4) | tail -1 | sed 's/^.* //')

带鱼壳:

basename "/"(ps -f -p (cat /proc/(echo %self)/stat | cut -d \  -f 4) | tail -1 | sed 's/^.* //')

但是请注意,当终端仿真器与它们一起启动时,这将捕获程序参数。
Robobenklein

如果我使用SSH连接,是否可以正常工作?
user3731622 '18

@ user3731622不会!您必须从客户端转发它。
恩里科

2

在许多Linux系统echo $TERMxterm看stazher后上方。

要使用实际的终端,请执行以下操作:

1:关闭当前正在运行的每个终端实例。

2:使用常规方法打开新终端。

3:输入命令如下:

ps -o 'cmd=' -p $(ps -o 'ppid=' -p $$)

4:返回应该是这样的:

lxterminal --geometry=135x20

这是细分:

所以:ps是“过程状态”

ps选项-o是显示与指定的关键字的空格或逗号分隔列表关联的信息。听起来很复杂,但并非如此。(空格或逗号)分隔(关键字列表)指定。

因此,(关键字列表)'cmd='仅是列表中的一个关键字。因此,仅要求显示命令即可打开终端。

ps选项-p是“按进程ID”哇,这对于ps是非常好的选择。问题是,您必须将此进程ID传递给ps。那么,如何获取进程ID?我们解开表情 $(ps -o 'ppid=' -p $$)

在这里,我们必须开始更深入地思考。我希望我发明了这种bash一线纸,但我没有。我想我从https://wiki.archlinux.org/某个地方偷了它,我再也找不到了。那些家伙很棒,但是很多时候我不了解他们说要做什么,除非经过大量研究。我们能做的是现在就了解它,因为我会解释。

所以我们知道$bash中的扩展运算符。我喜欢“解开包装”。因此,$(foo -opt bar)将打开或扩展“ foo -opt bar”。但是在bash中,单个圆括号会(...)打开子外壳。

因此,$(foo -opt bar)将“ foo -opt bar”扩展为在子shell中运行。很奇怪,很难理解。

好的,现在我们再次运行几乎相同的命令,ps -o 'ppid=' -p $$但是这次ps(进程状态)向我们展示了他在子shell实例中可以看到的内容。

-o关键字列表,和以前一样只有一个关键字,但这ppid=直接要求父shell的进程ID 从WITHAU DAUGHTER SHELL!非常聪明,是吗?当我能理解这一点时,我感到非常兴奋!

-p同样,“按进程ID”和bash中的$$是进程ID。

如果您调用ps -o 'ppid=' -p $$,或任何其他$$直接从第一个shell 请求的命令,他可能会说pid = 1,或者是xWindow或您的桌面程序中的pid,或者您可能会得到shell的实际pid。如果您问了很多遍,您每次可能都会得到不同的答案!

但是,如果您召唤一个女儿并问她“谁是您的爸爸”,她会告诉您!非常聪明。我希望我能成为这样的天才发明这种方法。


好的,因此,AU将不允许在一个帖子中进行适当的细分。抱歉,不愿意与博客系统打架并发表多个帖子。也许你会明白。
stazher '16

您的另一个答案似乎是对该答案的复杂而翔实的评论,而不是对该问题的答案。如果您可以将两个答案合并为一个并删除其中一个,然后添加到其中,那将是很棒的选择完全回答问题。使用----在中间画一条线?也有一个按钮。
Zanna

我想我已经准确而详细地回答了OP问题。在我有机会了解Blog编辑系统并完成之前,您跳了我。付诸表决,我已经习惯了。
stazher

1
我不认为我对您感兴趣,我只是在做评论...感谢您使您的帖子更加完整
Zanna

谢谢您的答复。对不起,也许我跳上了你。我很抱歉
stazher

1

使用pstreeawk是最简单的方法:

pstree -sA $$ | awk -F "---" '{ print $2 }'

讲解

  1. 显示的过程与树pstree$$(在atual处理)。
  2. pstree参数:

    • -s:显示流程的父级
    • -A:以纯ASCII显示输出。
  3. awk工具扫描模式并使用-F参数来拆分进程。

  4. 最后'{ print $2 }'告诉awk仅输出第二匹配模式(在这种情况下,为终端仿真器名称)。

你确定$2吗?就我而言,awk实际上是systemd---lightdm---lightdm---upstart---gnome-terminal----bash---pstree...
Enrico Maria De Angelis

@EnricoMariaDeAngelis Ya。感谢您的观察。在我的情况下,终端仿真器直接在systemd服务中初始化。我再次检查代码并进行更正。
silvadev

当我使用键盘快捷键启动模拟器时,此方法不起作用。在XFCE上,我得到的xfsettingsd不是我使用的终端。
Michael Hoffmann '18

如果您从头开始,则效果会更好:pstree -sA $$ | head -n1 | awk -F "---" '{ print $(NF-1) }'
lleaff '18

0

您是正确的,我只回答标题问题,而不回答正文问题。所以,你和鲍勃的叔叔去了。

在上面显示的一个答案中,我不确定大小写切换的含义。不需要这种情况下的切换。我的〜/ .bashrc脚本实际上只是简单的一行,所有的echo命令只是为了好玩。如何解释...

启动时的任何术语都读取〜/ .bashrc,并执行他将在.bashrc中看到的任何命令。因此,无论调用哪个术语,他都将读取.bashrc并执行命令,因此.bashrc中唯一需要的结构将是修改或排除一个或另一个术语的行为。期望的行为是每个术语都执行相同的命令,因此不需要大小写切换。Terminal本人将告诉您他的名字,因此无需区分。

注意(1)我没有测试guake,但适用于jlliagre在第一个答案中提到的所有其他内容。

注意(2)由于Wiki的降价格式,因此无法如图所示进行剪切和粘贴。您必须删除每个反引号,包括删除下划线字符,并添加实际的反引号,在之前ps或之后没有空格-p $$)

〜/ .bashrc的脚本

# show welcome message for actual terminal in use
echo "Welcome.  You are attempting to use"
echo ""
echo _backtick_ps -o 'cmd=' -p $(ps -o 'ppid=' -p $$)_backtick_
echo ""
echo "Good Luck and God Speed."

这很有趣。我已将此添加到我自己的〜/ .bashrc中。


根据Note(1)的要求,已经在Tilda上进行了测试,效果很好。Guake与Tilda类似,但是用python编写,因此仍然不了解Guake。
stazher

0

如果您使用的是bash,我想这个命令将为您提供帮助:

which $(ps -o 'cmd=' -p $(ps -o 'ppid=' -p $$))


0

如果您使用的是ZSH,则有更好的(更快)解决方案,该解决方案仅使用ZSH内置函数并/proc/$pid/{stat,cmdline}直接进行操作。

get-terminal-emulator() {
    if [[ $TTY = "/dev/tty"* ]]; then
        echo "linux-console"
        return
    fi
    local pid=$$ name=''
    while true; do
        proc_stat=(${(@f)$(</proc/${pid}/stat)})
        name=${proc_stat[2]//[()]/}
        case "${name}" in
            gnome-terminal|konsole|rxvt|xterm)
                echo "${name}"; return ;;
            python*)
                local cmdline=(${(@f)$(</proc/${pid}/cmdline)})
                if [[ "$cmdline" =~ "\\bguake.main\\b" ]]; then
                    echo "guake"; return
                fi
                ;;
        esac
        if test "$pid" = "1" -o "$pid" = ""; then
            echo "unknown"
            return
        fi
        pid=${proc_stat[4]}       
    done
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.