使用sed和pstree显示正在使用的终端类型

时间:2013-08-26 21:14:50

标签: linux bash shell sed

我一直在尝试显示仅用作名称的终端类型。例如,如果我使用konsole,它将显示konsole。到目前为止,我一直在使用这个命令。

pstree -A -s $$

输出这个。

systemd---konsole---bash---pstree

我有以下可以从该行提取konsole

pstree -A -s $$ | sed 's/systemd---//g;s/---.*//g' | head -1

并正确输出konsole。但有些人只从pstree命令输出,看起来像这样。

systemd---kdeinit4---terminator---bash---pstree

或者

systemd---kdeinit4---lxterminal---bash---pstree

然后当我添加sed命令时,它会提取kdeinit4而不是终结符。我可以想到几个场景来提取终端类型,但没有一个不包含条件语句来检查特定类型的终端。我遇到的问题是我无法准确预测终端名称或其后面会有多少非或非相关事物,也无法准确预测终端名称。有没有人对解决方案有任何想法?

4 个答案:

答案 0 :(得分:1)

您可以使用

ps -p "$PPID" -o comm=

或者

ps -p "$PPID" -o fname=

如果您的shell没有设置PPID变量,您可以使用

获取它
ps -p "$(ps -p "$$" -o ppid= | sed 's|\s\+||')" -o fname=

另一个理论是,当前shell的父进程与shell不属于同一个tty实际上可能是生成虚拟终端的那个进程,所以我们也可以这样找到它:

#!/bin/bash

shopt -s extglob

SHELLTTY=$(exec ps -p "$$" -o tty=)
P=$$

while read P < <(exec ps -p "$P" -o ppid=) && [[ $P == +([[:digit:]]) ]]; do
    if read T < <(exec ps -p "$P" -o tty=) && [[ $T != "$SHELLTTY" ]]; then
        ps -p "$P" -o comm=
        break
    fi
done

答案 1 :(得分:0)

curTerm=$(update-alternatives --query x-terminal-emulator | grep '^Best:')
curTerm=${curTerm##*/}

printf "%s\n" "$curTerm"

结果是

terminator

当然可能会有所不同 现在,您可以在sed命令中使用$curTerm变量。

但我不确定这是否适用于符号链接。

答案 2 :(得分:0)

我不知道如何隔离系统上的终端名称,但作为解析练习,并假设终端直接运行bash,您可以通过以下方式管道输出:

 awk -F"---bash---" ' NF == 2 { count = split( $1, arr, "---" ); print arr [count]; }'

这将找到“--- bash ---”之前的单词,在你的例子中是

konsole
terminator
lxterminal

如果您需要不同的shell类型,可以展开字段分隔符以包含它们:

awk -F"---(bash|csh)---" ' NF == 2 { count = split( $1, arr, "---" ); print arr[count]; }'

考虑如下的虚线:

systemd---imaginary---monkey---csh---pstree

awk会将“monkey”作为终端名称以及测试集中的任何内容。

答案 3 :(得分:0)

这里没有保证,但我认为这大部分时间都适用于linux:

ps -ocomm= $(lsof -tl /proc/$$/fd/0 | grep -Fxf <(lsof -t /dev/ptmx))

可能会有一些解释,但请参阅man psman lsof和(特别是)man pts以获取相关信息。

/dev/ptmx是一个伪tty主服务器(在现代Linux系统和其他一些unix(类似)系统上)。如果程序是终端模拟器,telnet / ssh守护程序或其他需要捕获终端的程序(例如screen),程序将打开其中一个程序。模拟器向pseudo-tty master写入它想要“键入”的内容,并从伪tty slave中读取结果。

/proc/$$/fd/0是进程$$的标准输入(即执行命令的shell)。如果stdin没有被重定向,那么这将是一些slave伪节的符号链接,/ dev / pts /#。这是/ dev / ptmx设备的另一面,因此上面列出的/dev/ptmx打开的所有程序也将打开一些/dev/pts/#从属设备。 (您可能认为可以使用/dev/stdin/dev/fd/0代替/proc/$$/fd/0,但这些将由lsof本身打开,因此将成为其标准输入;因为方式lsof已实现,但不起作用。)-l的{​​{1}}选项会使其遵循符号链接,这样会导致它显示具有相同pts打开的进程作为当前的shell。

lsof的{​​{1}}选项会导致它产生“简洁”输出,仅包含pids,每行一个。 -t的{​​{1}}选项使其匹配字符串,而不是正则表达式,并强制完整的行匹配; lsof选项使它接受来自-Fx的匹配字符串(在这种情况下是一个进程替换),每行一个。

最后,grep打印出对应于pid的“命令”(默认情况下,切碎为8个字符)。

简而言之,该命令找到一个终端仿真器列表和其他具有master伪tty的主类似程序,以及一个使用伪tty slave的进程列表;找到两者之间的交集,然后查找命令名称以获得任何结果。