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.

31
demandé sur amphetamachine 2010-02-12 12:28:10

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.

33
répondu Patrick 2010-02-12 09:50:35

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.

21
répondu PSkocik 2012-09-18 05:01:04

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[@]}".

2
répondu Adrian Bartyczak 2018-01-24 04:19:44

Vous pouvez utiliser:

xdotool getwindowfocus getwindowname

(Comme: vous n'avez pas besoin de remplacer ceux de nice-noms à consonance avec quoi que ce soit.)

1
répondu Richard 2017-04-11 05:32:08