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

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

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

如果我使用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在这种情况下)?

答案1

原始版本

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

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

     $ ps -p $$ -o ppid=
     544
    

因此,我的 shell 的父级 PID 是544

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

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

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

  1. 用一个命令组合所有内容

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

     $(ps -p $(ps -p $$ -o ppid=) o args=) --version
     terminator 0.97
    
  3. 添加一个小函数,~/.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 <[email protected]>
     and Nick Schermer <[email protected]>.
    
     Please report bugs to <http://bugzilla.xfce.org/>.
    

全新和改进

但是上述方法并不那么可靠。当您在su切换到另一个用户后运行 shell 时,或者当您的终端被别名为某个东西时,以及各种其他情况时,它都会阻塞。由于我们在这里显然是在使用 X 程序,因此更好的方法可能是使用类似xdotool(installable with 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 

因此,我们可以使它稍微复杂一些(这里有一些批判性思维,这个是不可移植的):

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"
}

这对我测试过的所有情况都有效。

答案2

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

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

注意事项

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

  • comm从技术上讲是argv[0],实际上可以是任意字符串。但一般来说,对于这种特殊情况,您应该能够依赖它。

  • tmux如果您通过 SSH 连接或者使用或screen类似的东西,这将无法按预期工作。

答案3

尝试这个,

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

或者

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

答案4

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

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

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

Terminator 显示名称“x-terminal-emulator”。

相关内容