给定XX的进程iD,我想要列出任何窗口ID,其中_NET_WM_PID = XX.如果可能的话,更好的是最老的仍然活跃的窗口ID.
我对linux很新,但我要做的是创建一个脚本,该脚本将采用命令行,并查看是否已经打开一个属于使用相同命令行调用的进程的窗口.如果是这样,只需将焦点设置到该窗口,否则执行命令行以获得新进程.我的目的是在我的ubuntu桌面中使用它,我将把这个脚本挂钩到我的easystroke鼠标手势命令中,这样,例如,每次我为gmail做手势我都没有得到一个全新的gmail会话,我只是被带到我现有的gmail chrome app窗口.也许有一个更简单的方法来解决所有这些问题,但我还没有找到方法.
在帮助下,我已经弄清楚如何使用pgrep找到命令行的PID以及如何使用wmctrl将焦点设置到窗口句柄,但我仍然坚持从PID到窗口ID.
Pat*_*ick 38
xwininfo和xprop允许检索你想要的东西,但它有点棘手.
xwininfo允许检索所有已知窗口,xprop查询X关于_NET_WM_PID参数的单个窗口ID.
到目前为止,一个hacky方法是:
#!/bin/sh
findpid=$1
known_windows=$(xwininfo -root -children|sed -e 's/^ *//'|grep -E "^0x"|awk '{ print $1 }')
for id in ${known_windows}
do
xp=$(xprop -id $id _NET_WM_PID)
if test $? -eq 0; then
pid=$(xprop -id $id _NET_WM_PID|cut -d'=' -f2|tr -d ' ')
if test "x${pid}" = x${findpid}
then
echo "Windows Id: $id"
fi
fi
done
Run Code Online (Sandbox Code Playgroud)
结果:
mycroft:~ $ ./find_windows.sh 1919
Windows Id: 0x1800748
Windows Id: 0x181b221
Windows Id: 0x1803ad5
Windows Id: 0x181f681
Windows Id: 0x181f658
Windows Id: 0x180006d
Windows Id: 0x1800003
Windows Id: 0x1800001
Windows Id: 0x180001e
Run Code Online (Sandbox Code Playgroud)
正如您将看到的,即使您只在屏幕上看到一个窗口,单个进程也可能具有一定数量的已知窗口.
也许你应该得到这些工具来源,以达到你想要的.
PSk*_*cik 27
你也可以用wmctrl查找PID ,事实上,我认为这是一个更好的方法.xwininfo将返回所有类似于 Windows的实体,但您不会在桌面上找到它们.
如果你做man wmctrl ,你会发现wmctrl -l列出了桌面上实际可见的所有窗口(最重要的是)它们的窗口ID和标题.-p添加PID,-x将添加窗口类.
正如手册所说(RTFM,对吗?:D),wmctrl也可以搜索其中一些并激活与搜索匹配的窗口.但是,我不知道是什么决定了所有可能的匹配中的哪一个将被返回.另一方面,您可以使用提供的列表函数编写一个包装器,它可以更好地进行搜索,并且可能基于一些其他属性(例如上次访问窗口的时间戳),您可以通过查询提供的获胜来获得例如,id到xprop.
下面的这些代码行返回最近的一个mate-terminal类窗口的实例:
XTIME="_NET_WM_USER_TIME" #a shorter name for xprop query that shoul return timestamps
export TMPDIR=/dev/shm #save tmp files to memory to make it faster
LST=`mktemp` #tmp file to store our listing
wmctrl -lx | awk -F' ' '{printf("%s\t%s \t",$1,$3); for(i=5;i<=NF;i++) printf("%s",$i); printf("\n") }' > $LST #pretty-print our listing of windows into the tmp file
#To each line of listing, prepend a timestamp acquired via an xprop call
#Use awk to find a line whose 3rd column (winclass) matches the window class "mate-terminal.Mate-terminal" and among those that do, find the one whose timestamp is the largest
while read LINE; do ID=`echo "$LINE"|cut -f 1`; TIME=`xprop -id $ID $XTIME`; TIME="${TIME/* = /}"; echo -e "$TIME\t$LINE" ; done <$LST ) | awk -v s="mate-terminal.Mate-terminal" '$3 == s {if($1>max){max=$1;line=$0};};END{print line}'
rm $LST #delete tmp file
Run Code Online (Sandbox Code Playgroud)
无论如何,对于你所描述的你正在构建的东西 - 如果我是你,我会找出你想要的命令产生什么类型的窗口,然后我的搜索基于它,而不是基于PID.或者,您可以假设命令CMD可能生成具有包含CMD的类名的窗口.
找到你的线后,你应该使用窗口ID
通过wmctrl激活窗口.
希望这可以帮助.
旁注:我发现xdotool也可以根据类名和窗口标题进行搜索,但速度非常慢.在我的计算机上,这个bash脚本(调用相当多的外部实用程序)的速度是xdotool:P的编译替代品的10倍.
您可以使用:
xdotool getwindowfocus getwindowname
Run Code Online (Sandbox Code Playgroud)
(按原样:您不需要用任何东西替换那些好听的名字。)
这里有多个很棒的 X11 窗口管理解决方案。
试试 wmctrl。这是一个脚本:
#!/usr/bin/env bash
#
# File:
# getwindidbypid
#
# Description:
# Get the ID of a window by PID (if the process has a window).
#
# Usage:
# getwindidbypid <PID>
#
while IFS= read line; do
if [[ "${line}" =~ (0x)([0-9a-z]+)([ ][- ][0-9]+[ ])([0-9]*) ]]; then
winId="${BASH_REMATCH[1]}${BASH_REMATCH[2]}"
pid="${BASH_REMATCH[4]}"
if [[ "${pid}" -eq "${1}" ]]; then
WIND_IDS+=("${winId}")
fi
fi
done < <(wmctrl -lp)
if [ "${#WIND_IDS[@]}" -gt 0 ]; then
echo "${WIND_IDS[@]}"
fi
Run Code Online (Sandbox Code Playgroud)
例子:
user ~ $ getwindidbypid 37248
0x05a00012
Run Code Online (Sandbox Code Playgroud)
$WINDOWID
功能在其他一些实现的xterm
环境下,您可以找到这个变量:
echo $WINDOWID
58720292
Run Code Online (Sandbox Code Playgroud)
因此对于任何其他pid:
很快通过使用sed
:
targetpid=12345
sed -zne 's/WINDOWID=//p' /proc/$targetpid/environ
Run Code Online (Sandbox Code Playgroud)
...
xdotool windowactivate $(sed -zne 's/WINDOWID=//p' /proc/$targetpid/environ)
Run Code Online (Sandbox Code Playgroud)
或者在纯 bash函数中:
xdotool windowactivate $(sed -zne 's/WINDOWID=//p' /proc/$targetpid/environ)
Run Code Online (Sandbox Code Playgroud)
然后
getWinFromPid () {
local pid=$1 array line
[ -z "$pid" ] || [ ! -d /proc/$pid ] && return -1
local -n result=${2:-winIDfromPid[$pid]}
mapfile -d $'\0' -t array </proc/$pid/environ
for line in "${array[@]}" ;do
[ -z "${line%WINDOWID=*}" ] &&
result=${line#*=} && return
done
}
Run Code Online (Sandbox Code Playgroud)
gnome-terminal
:这很强大,因为我们不需要terminal
进程的 pid,而是使用终端的 pid shell
。对于样品:
getWinFromPid 123456 myWinId
xdotool windowactivate $myWinId
Run Code Online (Sandbox Code Playgroud)
不要显示想要的 pid!
所以我们必须在流程的层次结构中导航
来自活动会话本人:
wmctrl -lp
Run Code Online (Sandbox Code Playgroud)
当您在任何活动终端控制台中键入此内容时,此操作就会起作用。
然后现在,与xdotool
:
SHWINID=$(xprop -root | sed -ne 's/^_NET_ACTIVE_WINDOW.*[)].*window id # //p')
Run Code Online (Sandbox Code Playgroud)
您现在可以切换到另一个窗口,将在 12 秒后返回。
我写了这个小函数:
sleep 12; xdotool windowactivate $SHWINID
Run Code Online (Sandbox Code Playgroud)
然后
getWinFromPid () {
local pid=$1 ttypid crtpid wid xprop ttycheck
[ -z "$pid" ] || [ ! -d /proc/$pid ] && return -1
local -n result=${2:-winIDfromPid[$pid]}
read ttycheck < <(ps ho tty $pid)
ttypid=$ttycheck
while [ "$ttypid" = "$ttycheck" ]; do
crtpid=$pid
read pid ttypid < <(ps ho ppid,tty $pid)
done
result=
while [ -z "$result" ] && read wid; do
xprop=$(xprop -id $wid)
[ "$xprop" ] && [ -z "${xprop//*_NET_WM_DESKTOP*}" ] &&
[ -z "${xprop//*_NET_WM_PID(CARDINAL) = $crtpid*}" ] && result=$wid
done < <(xwininfo -root -children -all |
sed -e '1,/children:$/d;s/^ *\(0x[0-9a-fA-F]\+\) .*/\1/p;d')
}
Run Code Online (Sandbox Code Playgroud)
如果没有提交变量名,这将$winIDfromPid
使用 pid id 作为索引号填充全局数组:
getWinFromPid <process id> [<variable name>]
Run Code Online (Sandbox Code Playgroud)
注意:这是用xterm
、mate-terminal
、konsole
和进行测试的gnome-terminal
。
Note2:如果你已经wmctrl
安装了,你可以替换最后两行函数:
getWinFromPid 1234 winId
echo $winId
0x0100012345
getWinFromPid 1234
echo ${winIDfromPid[1234]}
0x0100012345
declare -p winIDfromPid
declare -a winIDfromPid=([1234]="0x0100012345")
Run Code Online (Sandbox Code Playgroud)
经过:
done < <(xwininfo -root -children -all |
sed -e '1,/children:$/d;s/^ *\(0x[0-9a-fA-F]\+\) .*/\1/p;d')
Run Code Online (Sandbox Code Playgroud)
函数将变得大约快两倍。
done < <(wmctrl -l|sed -ne 's/^ *\(0x[0-9a-fA-F]\+\) .*/\1/p');}
Run Code Online (Sandbox Code Playgroud)
或者没有ID,您将必须用鼠标单击:
ps --ppid $(xprop _NET_WM_PID|sed s/.*=//) ho sid|xargs -I{} -n1 ps --sid {} fw
Run Code Online (Sandbox Code Playgroud)
进入一个函数
winID=0x123456
ps --ppid $(xprop -id $winID _NET_WM_PID|sed s/.*=//) ho sid |
xargs -I{} -n1 ps --sid {} fw
Run Code Online (Sandbox Code Playgroud)
然后:
ps --ppid $(xprop _NET_WM_PID|sed s/.*=//) ho sid|xargs -I{} -n1 ps --sid {} fw
Run Code Online (Sandbox Code Playgroud)
最后,有一个小功能用于显示带有进程的窗口列表。
psWin() {
ps --ppid $(xprop ${1+-id} $1 _NET_WM_PID|sed s/.*=//) ho sid |
xargs -I{} -n1 ps --sid {} fw
}
Run Code Online (Sandbox Code Playgroud)
然后
psWin $SHWINID
PID TTY STAT TIME COMMAND
30529 pts/2 Ss 0:00 bash
19979 pts/2 S+ 0:00 \_ bash
19982 pts/2 S+ 0:00 \_ xargs -I{} -n1 ps --sid {} fw
19986 pts/2 R+ 0:00 \_ ps --sid 30529 fw
Run Code Online (Sandbox Code Playgroud)
shWinList () {
local pids=() wids=() wtitl=() ttys=() pid ttypid wpid crtpid line title desk ttycheck
for pid in $(ps axho pid,tty| sed -ne 's/ pts.*//p') ;do # list pid / tty
wpid=$pid ttypid=
read ttycheck < <(ps ho tty $pid)
ttypid=$ttycheck
while [ "$ttypid" = "$ttycheck" ]; do
crtpid=$wpid
read wpid ttypid < <(ps ho ppid,tty $wpid)
done
[ -e /proc/$pid ] && pids[crtpid]+=$pid\ ttys[crtpid]=$ttycheck
done
while read wid; do title= pid= desk= # list wid / tty
while read line; do
[ "$line" ] && {
[ -z "${line%%_NET_WM_PID*}" ] && pid=${line##*= }
[ -z "${line%%WM_NAME*}" ] &&
title=${line#*\"} title=${title%\"*}
[ -z "${line%%_NET_WM_DESKTOP(*}" ] && desk=${line##*= } ;}
done < <(xprop -id $wid)
[ "${pids[pid]}" ] && [ "$title" ] && [ "$desk" ] &&
wtitl[16#${wid#0x}]=${title} wids[16#${wid#0x}]=${pids[pid]} \
ttys[16#${wid#0x}]=${ttys[pid]}
done < <(xwininfo -root -children -all |
sed -ne 's/^ *\(0x[0-9a-fA-F]\+\) .*/\1/p')
for xwin in ${!wids[@]} ;do out= # merge & print
printf " 0x%x %-9s %-40s " $xwin "${ttys[$xwin]}" "${wtitl[$xwin]}"
for pid in ${wids[$xwin]} ;do
mapfile -d '' cmdl < /proc/$pid/cmdline
echo -n " $pid[${cmdl[*]}]"
done ; echo
done
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
44054 次 |
最近记录: |