Existe-t-il une commande linux pour déterminer les ID de fenêtre associés à un identifiant de processus donné?
avec un identifiant de processus de XX, j'aimerais avoir une liste de n'importe quel identifiant de fenêtre où _NET_WM_PID = XX. Encore mieux serait le plus ancien ID de fenêtre encore actif si possible.
je suis très nouveau sous linux, mais ce que j'essaie de faire c'est de créer un script qui prendrait une ligne de commande, et voir s'il y a déjà une fenêtre ouverte appartenant à un processus invoqué avec cette même ligne de commande. Si c'est le cas, il suffit de mettre l'accent sur cette fenêtre, sinon exécutez la ligne de commande pour lancer un nouveau processus. Mon l'intention est d'utiliser cela dans mon bureau ubuntu, où je vais accrocher ce script dans Mes commandes de geste de la souris easystroke, de sorte que, par exemple, chaque fois que je fais un geste pour gmail Je ne reçois pas une session gmail flambant neuve, je viens d'être amené à ma fenêtre existante gmail chrome app window. Peut-être qu'il y a une façon plus facile de faire tout ça, mais je n'ai pas encore trouvé mon chemin.
avec de l'aide, j'ai compris comment trouver un PID pour une ligne de commande avec pgrep et comment mettre le focus sur une poignée de fenêtre avec wmctrl, mais je suis coincé à passer de PID à window ID.
4 réponses
xwininfo et xprop permet de retrouver ce que vous voulez, mais c'est un peu délicat.
xwininfo permet de récupérer toutes les fenêtres connues, et xprop d'interroger X sur un identifiant de fenêtre unique pour votre paramètre _NET_WM_PID.
Jusqu'à présent, une façon hacky de le faire serait:
#!/bin/sh
findpid=
known_windows=$(xwininfo -root -children|sed -e 's/^ *//'|grep -E "^0x"|awk '{ print }')
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
Résultat:
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
peut-être vous devriez obtenir ces outils dans le but de faire ce que vous voulez.
vous pouvez aussi chercher les Pid wmctrl aussi, en fait, et je pense que c'est une meilleure façon de le faire. xwininfo va retourner toutes sortes d'entités qui semblent être des fenêtres, mais vous ne les trouverez pas vraiment sur votre bureau.
Si vous n' homme wmctrl vous verrez que wmctrl-l liste Toutes les fenêtres qui sont réellement visibles sur votre bureau avec (le plus important) leur ID des fenêtres et titres. -p ajoute pid et -x ajouter classes de fenêtres.
comme le manuel le dit (RTFM, Non? :D), wmctrl peut également rechercher à travers certains de ceux-ci et activer une fenêtre qui correspond à la recherche. Cependant, je n'ai aucune idée de ce qui détermine lequel de toutes les correspondances possibles seront retournés. D'un autre côté, vous pouvez utiliser la fonction de liste fournie pour écrire un wrapper qui fait la recherche mieux et peut-être basé sur d'autres propriétés (comme le timestamp du dernier accès à la fenêtre) que vous pouvez obtenir en questionnant le win id à xprop, par exemple.
ces lignes de code ci-dessous renvoient l'instance la plus récente d'une fenêtre de classe 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",,); 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" ' == s {if(>max){max=;line=};};END{print line}'
rm $LST #delete tmp file
quoi qu'il en soit, pour la chose que vous décrivez vous construisez-si j'étais vous, je trouverais quelle classe de fenêtres votre commande désirée génère et puis baser ma recherche sur cela, plutôt que sur les PIDs. Vous pouvez aussi supposer que la commande CMD générera peut-être windows avec un nom de classe qui inclut CMD.
après avoir trouvé votre ligne, vous devez utiliser le fenêtre id
pour activer la fenêtre via wmctrl.
Espérons que cette aide.
une note secondaire: j'ai trouvé que xdotool peut faire des recherches basées sur les noms de classe et les titres de fenêtre aussi, mais c'est très lent. Sur mon ordinateur, cette fête script (qui appelle pas mal d'Utilités externes) est 10 fois plus rapide que l'alternative compilée qui est xdotool :P.
Ici sont plusieurs solutions de gestion de fenêtres X11 (dont une pour ce problème).
Xwininfo et xprop sont de bons outils pour obtenir les ID de toutes les fenêtres mais pas les outils les plus faciles pour obtenir L'ID de la fenêtre principale associée à un PID (si cela est même possible avec eux). Pour obtenir l'ID de la fenêtre principale, utilisez wmctrl de la façon suivante:
#!/usr/bin/env bash
# getwindidbypid
#
# 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 "" ]]; then
WIND_IDS+=("${winId}")
fi
fi
done < <(wmctrl -lp)
if [ "${#WIND_IDS[@]}" -gt 0 ]; then
echo "${WIND_IDS[@]}"
fi
Exemple:
user ~ $ getwindidbypid 37248
0x05a00012
cette solution s'affichera ID de fenêtres multiples si plus d'une fenêtre principale est trouvée par wmctrl. Pour revenir seulement la première, il suffit de remplacer [@]
[0]
echo "${WIND_IDS[@]}"
.
Vous pouvez utiliser:
xdotool getwindowfocus getwindowname
(Comme: vous n'avez pas besoin de remplacer ceux de nice-noms à consonance avec quoi que ce soit.)