Как я могу получить PID экземпляра терминала GNOME, который я использую, из скрипта Bash?
Я могу запустить 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
, так что опять есть препятствие.
В приведенном ниже коде используется qdbus
и интерфейс dbus аятаны, чтобы вывести список всех окон терминала gnome и определить, сосредоточены ли они в данный момент или нет. Позже это может быть проанализировано или отредактировано для вывода только 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
Бывают случаи, когда работает более одного экземпляра - когда у меня открыт терминал в гостевой сессии, например
blockquote>Переменная
$PPID
даст вам родителя процесс для текущей оболочки Bash, которая частоgnome-terminal
.Чтобы быть в безопасности, следующие найдут родительский гном-терминальный процесс, даже если вложены несколько оболочек:
pstree -p -s $PPID | grep -Po 'gnome-terminal\(\K.*?(?=\))'
Следующая универсальная версия будет работать для любой оболочки, даже если запущены другие экземпляры 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
Это решение чувствует самое устойчивое мне. Это рекурсивно ищет родительский PID до нахождения того, которое принадлежит Терминалу GNOME.
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