当前位置: 首页>>技术教程>>正文


如何从命令行获取当前终端的名称?

问题描述

是否可以通过命令获取终端的类型?

如果我使用的是gnome-terminal,则输出应为gnome-terminal或类似的名称。获取终端的版本也很好。

更新资料

ps -aux | grep `ps -p $$ -o ppid=` 

将输出如下内容:

user     4239  0.0  0.7 292708 15744 pts/8    Sl   11:39   0:02 xfce4-terminal
user     4800  0.0  0.0   6176   820 pts/0    S+   12:23   0:00 grep --color=auto  4239

这也适用于xterm,但是如何仅获取名称(在这种情况下为xfce4-terminal)?

最佳办法

原始版本

一种方法是获取当前Shell会话的父进程,然后从那里获取终端名称。

  1. 获取当前shell进程的父级。 bash变量$$是当前shell的PID,因此我们可以将其作为对ps(-p $$)的查询,并要求它tp打印父进程的PID(-o ppid=,后跟的=以避免打印列标题):

    $ ps -p $$ -o ppid=
    544
    

    因此,我的 shell 程序父级的PID为544

  2. 获取与该PID关联的进程并打印其命令行

    $ ps -p 544 o args=
    /usr/bin/python /usr/bin/terminator
    

    以上输出将取决于您使用的终端仿真器,我正在使用terminator

  3. 将所有内容合并到一个命令中

    ps -p $(ps -p $$ -o ppid=) o args=
    
  4. 使用它来获取版本

    $(ps -p $(ps -p $$ -o ppid=) o args=) --version
    terminator 0.97
    
  5. ~/.bashrc中添加一个小函数,该函数将返回您正在使用的终端模拟器的名称和版本(这对于大多数常见的终端模拟器都适用):

    which_term(){
        term=$(ps -p $(ps -p $$ -o ppid=) -o args=);
        found=0;
        case $term in
            *gnome-terminal*)
                found=1
                echo "gnome-terminal " $(dpkg -l gnome-terminal | awk '/^ii/{print $3}')
                ;;
            *lxterminal*)
                found=1
                echo "lxterminal " $(dpkg -l lxterminal | awk '/^ii/{print $3}')
                ;;
            rxvt*)
                found=1
                echo "rxvt " $(dpkg -l rxvt | awk '/^ii/{print $3}')
                ;;
            ## Try and guess for any others
            *)
                for v in '-version' '--version' '-V' '-v'
                do
                    $term "$v" &>/dev/null && eval $term $v && found=1 && break
                done
                ;;
        esac
        ## If none of the version arguments worked, try and get the 
        ## package version
        [ $found -eq 0 ] && echo "$term " $(dpkg -l $term | awk '/^ii/{print $3}')    
    }
    

    现在,您可以获得终端的名称,还可以将任何您喜欢的选项传递给它(例如--version)。

使用不同终端的一些示例:

  1. xterm

    $ which_term
    XTerm(297)
    
  2. terminator

    $ which_term 
    terminator 0.97
    
  3. rxvt,这个没有-V-version--version标志,因此不会打印任何版本信息。

    $  which_term
    rxvt  1:2.7.10-5
    
  4. gnome-terminal

    $ which_term
    gnome-terminal  3.10.1-1
    
  5. konsole

    $ which_term
    Qt: 4.8.6
    KDE Development Platform: 4.11.3
    Konsole: 2.11.3
    
  6. lxterminal

    $ which_term
    lxterminal  0.1.11-4
    
  7. xfce4-terminal

    $ which_term
    xfce4-terminal 0.6.2 (Xfce 4.10)
    
    Copyright (c) 2003-2012
        The Xfce development team. All rights reserved.
    
    Written by Benedikt Meurer <benny@xfce.org>
    and Nick Schermer <nick@xfce.org>.
    
    Please report bugs to <http://bugzilla.xfce.org/>.
    

新的和改进的

上面的方法虽然不那么值得信赖。当su给另一个用户运行 shell 程序时,或者当您的终端被别名为其他情况时,它将阻塞。因为我们显然在这里使用X程序,所以更好的方法可能是使用xdotool(可通过sudo apt-get install xdotool安装)之类的信息来代替:

perl -lpe 's/\0/ /g' /proc/$(xdotool getwindowpid $(xdotool getactivewindow))/cmdline

上面将打印用于启动当前活动窗口的命令行。由于您的终端可能处于活动状态,因此它将显示该命令。这意味着对于大多数终端仿真器,您可以放心地假设返回的第一个字段是终端名称:

$ which_term 
lxterminal 

这意味着获得版本是微不足道的。例如

$ dpkg -l $(which_term) | awk '/^ii/{print $3}'
0.1.11-4

对于gnome-terminal并非如此:

$ which_term 
/usr/lib/gnome-terminal/gnome-terminal-server 

terminator

$ which_term
/usr/bin/python /usr/bin/terminator 

因此,我们可以使其更加复杂(这里有一些bashisms,这是不可移植的):

which_term(){
    term=$(perl -lpe 's/\0/ /g' \
           /proc/$(xdotool getwindowpid $(xdotool getactivewindow))/cmdline)

    ## Enable extended globbing patterns
    shopt -s extglob
    case $term in
        ## If this terminal is a python or perl program,
        ## then the emulator's name is likely the second 
        ## part of it
        */python*|*/perl*    )
         term=$(basename "$(readlink -f $(echo "$term" | cut -d ' ' -f 2))")
         version=$(dpkg -l "$term" | awk '/^ii/{print $3}')
         ;;
        ## The special case of gnome-terminal
        *gnome-terminal-server* )
          term="gnome-terminal"
        ;;
        ## For other cases, just take the 1st
        ## field of $term
        * )
          term=${term/% */}
        ;;
     esac
     version=$(dpkg -l "$term" | awk '/^ii/{print $3}')
     echo "$term  $version"
}

这适用于我测试过的所有情况。

次佳办法

尝试这个,

ps -aux | grep `ps -p $$ -o ppid=` | awk 'NR==1{print $11}'

要么

ps -aux | grep `ps -p $$ -o ppid=` | awk 'NR==1{print $NF}'

第三种办法

basename "$(cat "/proc/$PPID/comm")"

$PPID是 shell 程序父进程的PID。 comm表示命令。它可能不是完整路径,因此如果需要,我们使用basename剥离路径。

Caveats

这些可能也适用于至少其他一些答案。

  • 从技术上讲commargv[0],实际上可以是任意字符串。但总的来说,在这种情况下,您应该可以依靠它。

  • 如果您通过SSH连接或使用tmuxscreen或类似方法,则此操作将无法正常工作。

第四种办法

您可以尝试以下命令:

$ dpkg-query -W $COLORTERM
gnome-terminal  3.6.2-0ubuntu1

更新(由于OP和Avinash Raj):

$ dpkg-query -W $(ps -aux | grep "`ps -p $$ -o ppid=`" | awk 'NR==1{print $11}' | xargs basename)
rxvt    1:2.7.10-5

第五种办法

另一种(不完美的)可能性是:

xprop -id $WINDOWID WM_CLASS | cut -d" " -f3 | sed 's/^.\(.*\)..$/\1/'

但这不适用于lxterminal,因为环境变量$WINDOWID为空…

终结器显示名称”x-terminal-emulator”。

参考资料

本文由Ubuntu问答整理, 博文地址: https://ubuntuqa.com/article/11634.html,未经允许,请勿转载。