如何从 Bash 脚本中获取我正在使用的 GNOME 终端实例的 PID?
我可以运行xprop _NET_WM_PID
然后手动单击终端窗口,但我想完全自动化这一过程。
答案1
我编写了两个递归函数来跟踪进程的父进程
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
答案2
有时会运行多个实例 - 例如,当我在来宾会话中打开一个终端时
该变量$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` | cut -d, -f2)\ | grep gnome-terminal | cut -d,-f2
答案3
我觉得这个解决方案最可靠。它递归查找父 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