2010-02-12 9 views
29

Với quy trình iD là XX, tôi muốn có danh sách bất kỳ id cửa sổ nào có _NET_WM_PID = XX. Thậm chí tốt hơn sẽ là id cửa sổ vẫn còn hoạt động lâu đời nhất nếu có thể.Có lệnh linux nào để xác định ID cửa sổ được liên kết với ID tiến trình nhất định không?

Tôi rất mới với Linux, nhưng những gì tôi đang cố gắng là tạo một tập lệnh có dòng lệnh và xem liệu có một cửa sổ đã mở thuộc quá trình được gọi với cùng dòng lệnh đó hay không. Nếu vậy, chỉ cần tập trung vào cửa sổ đó, nếu không thì thực hiện dòng lệnh để có được một tiến trình mới. Ý định của tôi là sử dụng điều này trong máy tính để bàn ubuntu của tôi, nơi tôi sẽ móc kịch bản này vào các lệnh cử chỉ chuột easystroke của tôi, ví dụ, mỗi lần tôi cử chỉ cho gmail tôi không có phiên gmail mới, tôi chỉ được đưa đến cửa sổ ứng dụng Chrome gmail hiện có của tôi. Có lẽ có một cách dễ dàng hơn để đi về tất cả điều này, nhưng tôi đã không tìm thấy con đường của tôi để nó được nêu ra. Với sự giúp đỡ, tôi đã tìm ra cách tìm một PID cho một dòng lệnh với pgrep và làm thế nào để tập trung vào một cửa sổ xử lý với wmctrl, nhưng tôi bị mắc kẹt khi nhận được từ PID đến ID cửa sổ.

Trả lời

30

xwininfo và xprop cho phép truy xuất những gì bạn muốn, nhưng hơi phức tạp một chút.

xwininfo cho phép truy xuất tất cả các cửa sổ đã biết và xprop để truy vấn X về một ID cửa sổ duy nhất cho thông số _NET_WM_PID của bạn.

Cho đến nay, một cách hacky để làm điều đó sẽ là:

#!/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 

Kết quả:

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 

Như bạn sẽ thấy, một quá trình duy nhất có thể có một số lượng nhất định các cửa sổ được biết đến, thậm chí nếu bạn chỉ thấy một trên màn hình của mình.

Có thể bạn sẽ nhận được các nguồn công cụ này để thực hiện những gì bạn muốn.

+0

Cảm ơn. Tôi bắt đầu hacking xung quanh với mã này khi bạn ban đầu đăng nó, nhưng tôi đã boggled và sau đó sidetracked (do đó chấp nhận hối tiếc đáng tiếc) ... vẫn, điều này dường như được cho tôi chỉ muốn tôi muốn. –

+1

Một lớp lót sẽ làm điều đó (ăn cắp từ Patrick) khi bạn có thể dễ dàng chọn cửa sổ bạn quan tâm là 'xwininfo | sed -e 's/^ * //' | grep -E "Id cửa sổ" | awk '{print $ 4}' '. Chạy xwininfo không có đối số hoặc chuyển mạch cho phép bạn chọn bằng chuột của bạn cửa sổ bạn muốn biết. LƯU Ý: Tôi đã phải thay đổi lệnh grep một chút cho RHEL6. – MrMas

20

bạn cũng có thể tra cứu PID với wmctrl, và thực tế là tôi nghĩ đó là cách tốt hơn để thực hiện. xwininfo sẽ trả về tất cả các loại thực thể xuất hiện dưới dạng cửa sổ, nhưng bạn sẽ không thực sự tìm thấy chúng trên màn hình của mình.

Nếu bạn làm người wmctrl , bạn sẽ thấy rằng wmctrl -l liệt kê tất cả cửa sổ đang thực sự có thể nhìn thấy trên màn hình desktop của bạn với (quan trọng nhất) cửa sổ id của họtiêu đề. -p thêm PIDs-x sẽ thêm lớp cửa sổ.

Khi hướng dẫn sử dụng cho biết (RTFM, phải?: D), wmctrl cũng có thể tìm kiếm thông qua một số trong số này và kích hoạt cửa sổ khớp với tìm kiếm. Tuy nhiên, tôi không có ý tưởng gì xác định mà một trong tất cả các trận đấu có thể sẽ được trả lại. Mặt khác, bạn có thể sử dụng hàm liệt kê được cung cấp để viết một trình bao tìm kiếm tốt hơn và có thể dựa trên một số thuộc tính khác (chẳng hạn như dấu thời gian của lần truy cập cuối cùng vào cửa sổ) mà bạn có thể nhận được bằng cách truy vấn được cung cấp Ví dụ: hãy giành mã số id thành xprop.

Những dòng mã dưới đây trả lại ví dụ gần đây nhất một cửa sổ lớp người bạn đời-thiết bị đầu cuối:

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 

Nhưng dù sao, đối với điều mà bạn mô tả bạn đang xây dựng-nếu tôi là bạn, tôi sẽ tìm hiểu những gì lớp của cửa sổ lệnh mong muốn của bạn tạo ra và sau đó căn cứ tìm kiếm của tôi trên đó, chứ không phải trên PID. Ngoài ra, bạn có thể đoán rằng lệnh CMD có thể sẽ tạo ra các cửa sổ với một tên lớp bao gồm CMD.

Sau khi bạn đã tìm thấy đường của mình, bạn nên sử dụng mã cửa sổ
để kích hoạt cửa sổ qua wmctrl.

Hy vọng điều này sẽ hữu ích.

Một lưu ý phụ: Tôi thấy rằng xdotool có thể thực hiện tìm kiếm dựa trên tên lớp và tiêu đề cửa sổ, nhưng nó là cực kỳ chậm. Trên máy tính của tôi, tập lệnh bash này (gọi là khá nhiều tiện ích bên ngoài) nhanh gấp 10 lần so với phương pháp được biên dịch là xdotool: P.

+1

Nhưng lợi ích của xdotool là nó không cần một trình quản lý cửa sổ 'tiên tiến', vì vậy nó chắc chắn đáng nói đến. –

+0

'TIME =" $ {TIME/* = /} "' làm gì? –

+0

@JanusTroelsen: Thay thế mẫu Bash, xem http://www.tldp.org/LDP/abs/html/parameter-substitution.html#EXPREPL1 –

1

Bạn có thể sử dụng:

xdotool getwindowfocus getwindowname 

(Như là:. Bạn không cần phải thay thế những cái tên đẹp-sounding với bất cứ điều gì)

2

Here một số giải pháp quản lý cửa sổ X11 (trong đó có một cho vấn đề này).

Xwininfo và xprop là công cụ tốt để nhận ID của tất cả các cửa sổ nhưng không phải là công cụ đơn giản nhất để nhận ID của cửa sổ chính được liên kết với PID (nếu có thể với chúng). Để có được ID của cửa sổ chính, sử dụng wmctrl theo cách sau:

#!/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 "${1}" ]]; then 
     WIND_IDS+=("${winId}") 
    fi 
    fi 
done < <(wmctrl -lp) 

if [ "${#WIND_IDS[@]}" -gt 0 ]; then 
    echo "${WIND_IDS[@]}" 
fi 

Ví dụ:

user ~ $ getwindidbypid 37248 
0x05a00012 

Giải pháp này sẽ in nhiều ID Window nếu có nhiều hơn một cửa sổ chính được tìm thấy bằng cách wmctrl. Để chỉ trả lại giá trị đầu tiên, chỉ cần thay đổi [@] thành [0] trong echo "${WIND_IDS[@]}".