我曾经pstree
使用类似以下内容来查找运行 shell 脚本的父模拟器的名称:
pstree -s $PPID | awk -F '---' '{print $6}'
这适用于我当前的系统。我测试过mate-terminal
,xterm
但不确定这是否适用于其他 Linux 系统/平台和其他终端。有没有更好/更整洁(更便携的方式)的方法来实现这一目标?
答案1
ps -o comm= -p "$(($(ps -o ppid= -p "$(($(ps -o sid= -p "$$")))")))"
可能会给你带来好的结果。它给出了会话领导者的父进程的名称。对于在终端仿真器中启动的进程,通常是运行该终端仿真器的进程(除非使用诸如screen
、expect
、 ... 之类的东西(但请注意,tmux
screen
tmux
是setsid
终端模拟器),或者使用, start-stop-daemon
...)显式启动新会话
或者使用变量将其分解为单独的步骤(这也可以帮助使脚本更加不言自明):
sid=$(ps -o sid= -p "$$")
sid_as_integer=$((sid)) # strips blanks if any
session_leader_parent=$(ps -o ppid= -p "$sid_as_integer")
session_leader_parent_as_integer=$((session_leader_parent))
emulator=$(ps -o comm= -p "$session_leader_parent_as_integer")
这里数字周围的空白的剥离是使用$((...))
算术扩展完成的。您还可以使用 split+glob 运算符(假设未修改$IFS
)或按照 @ack 在注释中的建议使用xargs
:
ps -o sid= -p "$$" |
xargs ps -o ppid= -p |
xargs ps -o comm= -p
您还可以尝试解析wtmp
终端仿真器通常记录的条目及其与伪终端设备关联的 pid。如果不涉及expect/screen/tmux...,这在 Debian 系统上适用于我:
ps -o comm= -p "$(
dump-utmp -r /var/log/wtmp |
awk -v tty="$(ps -o tty= -p "$$")" -F ' *\\| *' '
$2 == tty {print $5;exit}')"
(来自dump-utmp
GNU acct
)。
答案2
要查找当前 shell 使用的终端仿真器的名称,您可以要求 X 窗口系统提供当前 shell 可见的窗口的名称:
$ xwininfo -id $WINDOWID | awk '/^xwin/ { print $NF }'
当我在 Rxvt-unicode 中运行时,这会"xterm"
在 XTerm 中返回字符串。"urxvt"
如果您有更改窗口标题的习惯,结果可能会有所不同,因为我认为这就是这里返回给您的内容。
答案3
建立在斯蒂芬·查泽拉斯使其在 tmux 下工作的解决方案(即返回 tmux 客户端用于显示的终端模拟器),这似乎对我有用:
TERMINAL_EMULATOR="$(ps --pid $(ps --pid $$ -o ppid=) -o comm=)"
if [[ "${TERMINAL_EMULATOR}" =~ tmux ]]; then
export TERMINAL_EMULATOR=$(ps --pid "$(($(ps --pid $(ps --pid $(tmux display-message -p "#{client_pid}") -o sid=) -o ppid=)))" -o comm=)
else
export TERMINAL_EMULATOR
fi