如何以编程方式获取活动GNOME终端实例的PID?
如何在Bash脚本中获取我正在使用的GNOME Terminal实例的PID?
我可以运行xprop _NET_WM_PID
,然后手动单击终端窗口,但我想完全自动执行此操作。
我写了两个递归函数来跟踪进程的父进程
get_parent() { ps --no-headers -p $1 -o ppid,cmd } process_list() { if [ "$1" -ne "1" ]; then PARENT="$(get_parent $1 )" printf "%s\n" "$PARENT" process_list $( printf "%s" "$PARENT" | awk '{print $1}' ) fi } print_header() { printf "PPID\tPROCESS\n" for i in $(seq 1 20 ) do printf "-" done printf "\n" } print_header process_list $$
我在这个过程中发现的是:
$ bash get_process_list PPID PROCESS -------------------- 31264 bash get_process_list 31251 mksh 16696 gnome-terminal 15565 /bin/mksh 2164 x-terminal-emulator 1677 init --user 1342 lightdm --session-child 12 19 1 lightdm
所以我们可以使用这两个函数并grep
gnome-terminal
,假设这是用户想要的。 如果用户想要任何终端仿真器,那可能会有问题,因为除了检查lsof
是否打开pts设备之外,没有办法判断该进程是否是终端仿真器。
除此之外,还有一些非常有趣的事情:
$ bash get_process_list PPID PROCESS -------------------- 32360 bash get_process_list 23728 -mksh 2164 tmux 1677 init --user 1342 lightdm --session-child 12 19 1 lightdm
tmux
显然是自己分叉,并且进程被 init
,所以再次出现了障碍。
使用Unity的Ayatana
下面的代码使用qdbus
和Ayatana的dbus接口来列出所有gnome-terminal窗口,以及它们是否现在都是焦点。 这可以在以后解析或编辑,以仅输出活动/聚焦窗口PID
样品运行:
$ bash get_gt_pd.sh XID:33554486 PID:20163 ACTIVE:true XID:33554444 PID:20163 ACTIVE:false
而代码本身
get_gt_xid() { # Prints XID of each gnome-terminal window qdbus --literal org.ayatana.bamf \ /org/ayatana/bamf/matcher \ org.ayatana.bamf.matcher.XidsForApplication \ /usr/share/applications/gnome-terminal.desktop } for window in $(get_gt_xid | awk -F'{' '{ gsub(/\,|}|]/," ");print $2 }' ) do PID=$(qdbus org.ayatana.bamf /org/ayatana/bamf/window/"$window"\ org.ayatana.bamf.window.GetPid) ACTIVE=$( qdbus org.ayatana.bamf /org/ayatana/bamf/window/"$window"\ org.ayatana.bamf.view.IsActive ) printf "XID:%s\tPID:%s\tACTIVE:%s\n" "$window" "$PID" "$ACTIVE" done
有时会运行多个实例 – 例如,当我在访客会话中打开终端时
变量$PPID
将为您提供当前bash shell的父进程,该进程通常是gnome-terminal
。
但是为了安全起见,即使嵌套了多个bash shell,以下内容也会找到父 gnome-terminal进程:
pstree -p -s $PPID | grep -Po 'gnome-terminal\(\K.*?(?=\))'
以下通用版本适用于任何shell,即使其他grep实例正在运行。 解读它是留给读者的练习;)
pstree -p -a -s \ $(pstree -p -a | grep -B3 $ RANDOM $ RANDOM \ | grep -m1`echo $ SHELL | cut -d / -f3` | 切-d,-f2) | grep gnome-terminal | cut -d,-f2
这个解决方案对我来说是最强大的。 它递归地查找父PID,直到找到属于GNOME终端的PID。
find-parent() { i=($(ps -o pid= -o ppid= -o cmd= -p $1)) ((i[0] == 1)) && return 1 if [[ ${i[2]} =~ (^|/)gnome-terminal$ ]]; then echo ${i[0]}; else find-parent ${i[1]}; fi }; find-parent $PPID