सभी चल रहे एक्स डिस्प्ले पर एक सूचना दिखाएं


16

कमांड लाइन का उपयोग करते हुए, मैं हर रनिंग एक्स डिस्प्ले पर एक सूचना दिखाना चाहता हूं। (और कंसोल चल रहा है)

कुछ इस तरह:

notify-send-all 'Warning' 'Nuclear launch in 5 minutes, please evacuate'

क्या कोई ऐसा कार्यक्रम है जो ऐसा करेगा? यदि नहीं, तो क्या इसे बैश के साथ लागू किया जा सकता है?


1
वर्षों बाद यहां आने वाले लोगों के लिए, इस उत्तर में एक सरल Inform_all फ़ंक्शन है जो Ubuntu 16.04 में काम करता है, और इसका उपयोग रूट द्वारा शुरू की गई स्क्रिप्ट में किया जा सकता है।
mivk

जवाबों:


16

आप कमांड वॉल के साथ सभी कंसोल को संदेश भेज सकते हैं।

एक्स के तहत सूचनाएं भेजने के लिए, सूचना-भेजें है जो वर्तमान प्रदर्शन पर वर्तमान उपयोगकर्ता को एक अधिसूचना भेजता है। (आपके प्रश्न से, मुझे लगता है कि आप पहले से ही इसे जानते हैं।) आप इस पर कुछ बैश स्क्रिप्टिंग के साथ निर्माण कर सकते हैं। मूल रूप से आपको यह पता लगाना होगा कि कौन से उपयोगकर्ता किस एक्स-डिस्प्ले पर हैं। एक बार जब आपको यह जानकारी मिल जाती है, तो आप इस तरह से सूचना भेज सकते हैं:

DISPLAY=:0 sudo -u fschmitt notify-send "Message"

जहाँ fschmitt प्रदर्शन 0 पर उपयोगकर्ता है। आप सभी उपयोगकर्ताओं और उनके प्रदर्शनों को खोजने के लिए "कौन" कमांड के आउटपुट को पार्स कर सकते हैं। आउटपुट इस तरह दिखता है

[edinburgh:~]$ who
markmerk3 tty7         2010-09-23 10:59 (:0)
markmerk3 pts/1        2010-09-30 13:30 (:0.0)
fschmitt pts/2        2010-10-08 11:44 (ip-77-25-137-234.web.vodafone.de)
markmerk3 pts/0        2010-09-29 18:51 (:0.0)
seamonkey pts/6        2010-09-27 15:50 (:1.0)
markmerk3 pts/5        2010-09-27 14:04 (:0.0)
seamonkey tty8         2010-09-27 15:49 (:1)
markmerk3 pts/13       2010-09-28 17:23 (:0.0)
markmerk3 pts/3        2010-10-05 10:40 (:0.0)

आप देखते हैं, दो उपयोगकर्ता हैं जो X सत्र चला रहे हैं, प्रदर्शन 0 पर markmerk3 और प्रदर्शन 1 पर सीमनीक। मुझे लगता है कि आपको tty के लिए grep करने की आवश्यकता है [0-9] * फिर आश्वासन दें कि पंक्ति के अंत में है: ([0] -9।] *) कंसोल लॉगइन से छुटकारा पाने के लिए और कोष्ठकों के बीच स्ट्रिंग से डिस्प्ले आईडी को निकालने के लिए।


2
कमांड whoआपको बताता है कि कौन लॉग इन है और किस एक्स पर वह लॉगिन प्रदर्शित है। आपको बस इसे कुछ हद तक फ़िल्टर करना पड़ सकता है।
टेंट

1
हालांकि यह शायद शेल स्क्रिप्ट में सिर्फ एक लूप का उपयोग करने के लिए बेहतर है आप हमेशा कुछ ऐसा कर सकते हैं who | awk '/\(:[0-9]+\)/ {gsub("[:|(|)]","");print "DISPLAY=:"$5 " sudo -u " $1 " notify-send \"Message\""}' | bash। इसके अलावा, आप unix.stackexchange.com/questions/1596/…
Steven D

8

यह धागा थोड़ा पुराना है, क्षमा करें, लेकिन मुझे उम्मीद है कि मैं अभी भी विषय के लिए कुछ उपयोगी जोड़ सकता हूं। (जोसेफ कुफनर ने भी एक अच्छी पटकथा लिखी, यह मेरे स्वाद के लिए थोड़ा लंबा था, और यह PHP का उपयोग करता है)

मुझे मूल प्रश्न (सभी सक्रिय एक्स-उपयोगकर्ताओं को संदेश भेजने के लिए) के रूप में वर्णित टूल की भी आवश्यकता थी। और यहाँ जवाबों के आधार पर, मैंने इस छोटी सी बैश-केवल स्क्रिप्ट को लिखा, जो सक्रिय एक्स-उपयोगकर्ताओं ('कौन' का उपयोग करके) की खोज करता है, और फिर प्रत्येक सक्रिय उपयोगकर्ता के लिए सूचना-भेज रहा है।

और सबसे अच्छा: आप मेरी स्क्रिप्ट का उपयोग ठीक वैसे ही कर सकते हैं जैसे "सूचना-भेजें", इसके सभी मापदंडों के साथ! ;-)

सूचित-भेज-सब:

#!/bin/bash
PATH=/usr/bin:/bin

XUSERS=($(who|grep -E "\(:[0-9](\.[0-9])*\)"|awk '{print $1$5}'|sort -u))
for XUSER in $XUSERS; do
    NAME=(${XUSER/(/ })
    DISPLAY=${NAME[1]/)/}
    DBUS_ADDRESS=unix:path=/run/user/$(id -u ${NAME[0]})/bus
    sudo -u ${NAME[0]} DISPLAY=${DISPLAY} \
                       DBUS_SESSION_BUS_ADDRESS=${DBUS_ADDRESS} \
                       PATH=${PATH} \
                       notify-send "$@"
done

उपरोक्त कोड को "सूचित-भेजें-सभी" नामक फ़ाइल में कॉपी करें, इसे निष्पादन योग्य बनाएं और इसे / usr / स्थानीय / बिन या / usr / बिन (जैसा आप चाहें) पर कॉपी करें । फिर इसे इस तरह से चलाएँ जैसे कंसोल सत्र में रूट:

notify-send-all -t 10000 "Warning" "The hovercraft is full of eels!"

मैं कई महीनों से इसका इस्तेमाल कर रहा हूं, विभिन्न मशीनों पर, और अब तक कोई समस्या नहीं है, और मैंने इसे MATE और Cinnamon डेस्कटॉप के साथ परीक्षण किया है। साथ ही इसे क्रोन और एनाक्रोन के भीतर सफलतापूर्वक चलाना।

मैंने यह स्क्रिप्ट ArchLinux के तहत / के लिए लिखी है, इसलिए कृपया मुझे बताएं कि क्या आपको किसी अन्य लिनक्स वितरण या डेस्कटॉप पर समस्या हो रही है।


|egrep?? क्या egrep एक कमांड है?
स्वॉट

@ Sw0ut, egrep वास्तव में एक कमांड है। लेकिन grep (1) के मैन पेज में कहा गया है कि egrep, fgrep और rgrep को हटा दिया गया है, और उनके समकक्ष रूपों "grep -E", "grep -F" और "grep -r" का उपयोग करने की सिफारिश की गई है।
रसारेज़

इसके बजाय awk '{print $1$5}'इसका उपयोग करना बेहतर है awk '{print $1$NF}', ताकि यह उन कुछ स्थानों पर न टूटे, जहां तारीखों को रिक्त स्थान के साथ स्वरूपित किया गया है (उदाहरण Jun 3के लिए 2017-06-03)। : यहाँ भी सभी उपयोगकर्ताओं के बजाय विशिष्ट उपयोगकर्ता को सूचित करने के लिए एक संस्करण है gist.github.com/shvchk/ba2f0da49bf2f571d6bf606d96f289d7
Shevchuk

1
उबंटू पर पथ का उपयोग करने grep -Eऔर जोड़ने के बाद शानदार तरीके से काम करता है /bin(संपादित देखें)। वापस लौटने के लिए स्वतंत्र महसूस अगर आप आपत्ति
सर्व-इंक

3

मुझे कुछ सिस्टम-वाइड नोटिफिकेशन के लिए भी इसकी आवश्यकता थी। यहाँ मेरा समाधान है। यह सभी सत्रों को खोजने के लिए स्कैन / खरीद करता है और फिर यह प्रत्येक (एक बार प्रति बस) पर सूचना-भेजने को निष्पादित करता है। सभी तर्कों को वास्तविक सूचना-भेजने के लिए अपरिवर्तित किया जाता है।

#!/bin/bash

/bin/grep -sozZe '^DBUS_SESSION_BUS_ADDRESS=[a-zA-Z0-9:=,/-]*$' /proc/*/environ \
| /usr/bin/php -r '
        $busses = array();
        array_shift($argv);
        while($ln = fgets(STDIN)) {
                list($f, $env) = explode("\0", $ln, 2);
                if (file_exists($f)) {
                        $user = fileowner($f);
                        $busses[$user][trim($env)] = true;
                }
        }
        foreach ($busses as $user => $user_busses) {
                foreach ($user_busses as $env => $true) {
                        if (pcntl_fork()) {
                                posix_seteuid($user);
                                $env_array = array("DBUS_SESSION_BUS_ADDRESS" => preg_replace("/^DBUS_SESSION_BUS_ADDRESS=/", "", $env));
                                pcntl_exec("/usr/bin/notify-send", $argv, $env_array);
                        }
                }
        }
' -- "$@"

1

उबंटू 16.04 में, मुझे एक स्क्रिप्ट से रूट के रूप में चलने वाली सूचनाएँ चाहिए थीं। पर्यावरण चर सेट करने के बाद, sudo -u $userकिसी कारण के लिए काम नहीं किया, लेकिन sh -c "..." $userकाम करता है।

इसलिए मैं अब इस फ़ंक्शन का उपयोग करता हूं:

notify_all() {
    local title=$1
    local msg=$2

    who | awk '{print $1, $NF}' | tr -d "()" |
    while read u d; do
        id=$(id -u $u)
        . /run/user/$id/dbus-session
        export DBUS_SESSION_BUS_ADDRESS
        export DISPLAY=$d
        su $u -c "/usr/bin/notify-send '$title' '$msg'"
    done 
}

कैसे खोजने के लिए DBUS_SESSION_BUS_ADDRESS चर शायद आपके वितरण पर निर्भर करता है। उबंटू में 16.04, यह अंदर है /run/user/$UID/dbus-session, जिसे बस खट्टा किया जा सकता है। id -uउपर्युक्त फ़ंक्शन में उपयोग किया जाता है ताकि उपयोगकर्ता नाम से यूआईडी प्राप्त किया जा सके who


इसका इस्तेमाल कैसे करें? क्या आप मेरी मदद कर सकते हैं?
इलागोल्ड्रिनो

0

यहां एंडी की स्क्रिप्ट का अपडेट दिया गया है: जिस तरह से यह निर्धारित किया गया DBUS_SESSION_BUS_ADDRESSहै वह सेंटोस 7 पर काम नहीं करता है। इसके अलावा whoकमांड ने कुछ कारणों से कुछ सत्रों को सूचीबद्ध नहीं किया है, इसलिए मैं ps auxइसके बजाय आउटपुट को पार्स करता हूं । यह स्क्रिप्ट मानती है कि उपयोगकर्ता X2GO ( nxagent) का उपयोग कर लॉग इन हैं , लेकिन अन्य मामलों के लिए इसे समायोजित करना सरल होना चाहिए।

#!/bin/bash
PATH=/usr/bin:/bin
NOTIFY_ARGS='-u critical "Shutdown notice" "THE SYSTEM IS GOING DOWN TODAY AT 23:00.\nWe recommend you to save your work in time\!" -i /usr/share/icons/Adwaita/32x32/devices/computer.png -t 28800000'

function extract_displays {
    local processes=$1
    processes=$(printf '%s\n' "$processes" | grep -P "nxagent.+:\d+")
    ids=$(printf '%s\n' "$processes" | grep -oP "\W\K:(\d)+")
    echo $ids
}


function find_dbus_address {
    local name=$1
    PID=$(pgrep 'mate-session' -u $name)
    if [ -z "$PID" ]; then
        PID=$(pgrep 'gnome-session' -u $name)
    fi
    if [ -z "$PID" ]; then
        PID=$(pgrep 'xfce4-session' -u $name)
    fi

    exp=$(cat /proc/$PID/environ | grep -z "^DBUS_SESSION_BUS_ADDRESS=")
    echo $exp
}

PROCESSES=$(ps aux)
DISPLAY_IDS=$(extract_displays "$PROCESSES")
echo "Found the following DISPLAYS: $DISPLAY_IDS"
for DISPLAY in $DISPLAY_IDS; do
    NAME=$(printf '%s\n' "$PROCESSES" | grep -P "nxagent.+$DISPLAY" | cut -f1 -d ' ')
    DBUS_ADDRESS=$(find_dbus_address $NAME)
    echo "Sending message to NAME=$NAME DISPLAY=$DISPLAY DBUS_ADDRESS=$DBUS_ADDRESS"
    echo "NOTIFY_ARGS=$NOTIFY_ARGS"
    eval sudo -u ${NAME} DISPLAY=${DISPLAY} ${DBUS_ADDRESS} PATH=${PATH} notify-send $NOTIFY_ARGS
done

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.