Çalışan tüm X ekranlarda bir bildirim göster


16

Komut satırını kullanarak, çalışan her X ekranında bir bildirim göstermek istiyorum. (ve çalışan konsol)

Gibi bir şey:

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

Bunu yapacak bir program var mı? Değilse, bu bash ile uygulanabilir mi?


1
Yıllar sonra buraya gelen insanlar için , bu cevapta Ubuntu 16.04'te çalışan ve kök tarafından başlatılan komut dosyalarında kullanılabilen basit bir notify_all işlevi vardır .
mivk

Yanıtlar:


16

Komut duvarı ile tüm konsollara mesaj gönderebilirsiniz.

X altında bildirim göndermek için geçerli kullanıcıya geçerli ekranda bir bildirim gönderen bildir-gönder vardır. (Sorunuzdan, sanırım bunu zaten biliyorsunuz.) Biraz bash komut dosyasıyla bunu geliştirebilirsiniz. Temel olarak hangi kullanıcıların hangi X-Display'lerde olduğunu bulmanız gerekir. Bu bilgileri aldıktan sonra, notify-send komutunu aşağıdaki gibi kullanabilirsiniz:

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

Fschmitt 0 göstergesindeki kullanıcı olduğunda. Tüm kullanıcıları ve ekranlarını bulmak için "who" komutunun çıktısını ayrıştırabilirsiniz. Çıktı şöyle görünür

[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)

Gördüğünüz gibi, X oturumları çalıştıran iki kullanıcı var, ekran 0'da markmerk3 ve ekran 1'de seamonkey. Sanırım tty [0-9] * için grep yapmanız gerekiyor, ardından satırın sonunda (: [0 -9.] *) Konsol girişlerinden kurtulmak ve parantezler arasındaki dizeden display id değerini çıkarmak için.


2
Komut whosize kimin oturum açtığını ve hangi X'in oturum açtığını gösterir. Sadece biraz filtrelemeniz gerekebilir.
tante

1
Bir kabuk betiğinde bir döngü kullanmak muhtemelen daha iyi olsa da, her zaman böyle bir şey yapabilirsiniz who | awk '/\(:[0-9]+\)/ {gsub("[:|(|)]","");print "DISPLAY=:"$5 " sudo -u " $1 " notify-send \"Message\""}' | bash. Ayrıca, unix.stackexchange.com/questions/1596/…
Steven D

8

Bu konu biraz eski, üzgünüm, ama umarım yine de konuya faydalı bir şeyler ekleyebilirim. (ayrıca Josef Kufner güzel bir senaryo yazdı, benim zevkime göre biraz uzun ve PHP kullanıyor)

Ayrıca orijinal soruda açıklandığı gibi bir araca ihtiyacım vardı (tüm aktif X kullanıcılarına mesaj göndermek için). Ve buradaki cevaplara dayanarak, aktif X kullanıcılarını ('kim' kullanarak) arayan ve daha sonra her aktif kullanıcı için bildir-gönder çalıştıran bu küçük bash-script'i yazdım.

Ve en iyisi: betiğimi tüm parametreleriyle "notify-send" gibi kullanabilirsiniz! ;-)

bildirmek-send-hepsi:

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

Yukarıdaki kodu "notify-send-all" adlı bir dosyaya kopyalayın, çalıştırılabilir yapın ve / usr / local / bin veya / usr / bin (istediğiniz gibi) üzerine kopyalayın . Sonra, örneğin böyle bir konsol oturumunda root olarak çalıştırın:

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

Birkaç ay, farklı makinelerde kullanıyorum ve şimdiye kadar hiç problem yaşamadım ve MATE ve Cinnamon masaüstü bilgisayarlarıyla test ettim. Ayrıca başarıyla cron ve anacron içinde çalışıyor.

Bu komut dosyasını ArchLinux için / altında yazdım, bu yüzden lütfen başka bir Linux dağıtımında veya masaüstünde sorun yaşıyorsanız bana bildirin.


|egrep?? egrep bir komut mudur?
Sw0ut

@ Sw0ut, egrep gerçekten bir komut. Ancak grep'in (1) man sayfasında egrep, fgrep ve rgrep'in kullanımdan kaldırıldığını ve eşdeğer formlarının "grep -E", "grep -F" ve "grep -r" kullanılması önerildiğini söylüyor.
rsuarez

Bunun yerine awk '{print $1$5}'kullanılması daha iyidir awk '{print $1$NF}', böylece tarihin boşluklarla biçimlendirildiği (örneğin, Jun 3yerine 2017-06-03) bazı yerel ayarları kırmaz . Ayrıca, tüm kullanıcılar yerine belirli kullanıcıları bilgilendirmek için bir sürüm: gist.github.com/shvchk/ba2f0da49bf2f571d6bf606d96f289d7
Shevchuk

1
Kullandıktan sonra grep -Eve /binyola ekledikten sonra Ubuntu üzerinde harika çalışır (düzenlemeye bakın). İtiraz ederseniz geri dönmekten çekinmeyin
serv-inc

3

Bazı sistem bildirimleri için de buna ihtiyacım vardı. İşte benim çözümüm. Tüm oturum veri yollarını bulmak için tarar / proc ve daha sonra her biri (otobüs başına bir kez) bildir-gönder yürütür. Tüm argümanlar değişmeden gerçek bildir-gönder olarak iletilir.

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

Ubuntu 16.04'te crontab'dan root olarak çalışan bir betikten bildirimler istedim. Ortam değişkenlerini ayarladıktan sonra, sudo -u $userbir nedenden dolayı sh -c "..." $userçalışmadı , ama işe yarıyor.

Şimdi bu fonksiyonu kullanıyorum:

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 değişkeninin nasıl bulunacağı muhtemelen dağıtımınıza bağlıdır. Ubuntu 16.04'te, /run/user/$UID/dbus-sessionbasitçe tedarik edilebilir. id -u, yukarıdaki işlevde, döndürülen kullanıcı adından UID'yi almak için kullanılır who.


Bu nasıl kullanılır? Bana yardım eder misiniz?
elgolondrino

0

İşte Andy'nin script bir güncelleme var: yolu belirlenir DBUS_SESSION_BUS_ADDRESSAyrıca CentOS 7. iş değil whoben ayrıştırmak böylece komut, nedense bazı oturumları listelemedi ps auxyerine çıktı. Bu komut dosyası, kullanıcıların X2GO ( nxagent) kullanarak oturum açtığını varsayar , ancak diğer durumlar için ayar yapmanın basit olması gerekir.

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

-1
users=$(who | awk '{print $1}')

for user in $users<br>
do
        DISPLAY=:0 sudo -u $user notify-send "hello!!"
done
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.