it-swarm-ko.tech

실행중인 모든 X 디스플레이에 알림 표시

명령 줄을 사용하여 실행중인 모든 X 디스플레이에 알림을 표시하고 싶습니다. (및 실행중인 콘솔)

다음과 같은 것 :

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

이를 수행하는 프로그램이 있습니까? 그렇지 않은 경우 bash로 구현할 수 있습니까?

16
Stefan

커맨드 월을 사용하여 모든 콘솔에 메시지를 보낼 수 있습니다.

X에서 알림을 보내기 위해 현재 디스플레이의 현재 사용자에게 알림을 보내는 알림 보내기가 있습니다. (귀하의 질문에 따르면 이미 이것을 알고 있다고 생각합니다.) 일부 bash 스크립팅을 사용하여이를 기반으로 구축 할 수 있습니다. 기본적으로 어떤 사용자가 어떤 X- 디스플레이에 있는지 알아 내야합니다. 이 정보를 받으면 다음과 같이 알림 보내기를 사용할 수 있습니다.

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

여기서 fschmitt는 디스플레이 0의 사용자입니다. "who"명령의 출력을 구문 분석하여 모든 사용자와 해당 디스플레이를 찾을 수 있습니다. 출력은 다음과 같습니다.

[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에는 seamonkey가 있습니다. tty [0-9] *에 대해 grep해야한다고 생각합니다. 그런 다음 줄 끝에 (: [0 -9.] *) 콘솔 로그인을 제거하고 괄호 사이의 문자열에서 디스플레이 ID를 추출합니다.

16
fschmitt

이 스레드는 약간 오래되었습니다. 죄송하지만 여전히 주제에 유용한 내용을 추가 할 수 있기를 바랍니다. (또한 Josef Kufner가 Nice 스크립트를 작성했는데 내 취향에 비해 너무 길었고 PHP를 사용했습니다)

또한 원래 질문에서 설명한 도구가 필요했습니다 (모든 활성 X 사용자에게 메시지를 보내기 위해). 그리고 여기의 답변을 바탕으로 활성 X- 사용자 ( 'who'사용)를 검색 한 다음 모든 활성 사용자에 대해 notify-send를 실행하는이 작은 bash 전용 스크립트를 작성했습니다.

그리고 가장 좋은 점은 모든 매개 변수와 함께 "notify-send"와 똑같이 내 스크립트를 사용할 수 있다는 것입니다! ;-)

알림-모두 보내기 :

#!/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 "[email protected]"
done

위의 코드를 "notify-send-all"이라는 파일에 복사하고 실행 가능하게 만든 다음 / usr/local/bin 또는 / usr/bin (as 너는 좋아한다). 그런 다음 예를 들어 실행하십시오. 다음과 같이 콘솔 세션에서 루트로 :

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

저는 지금까지 몇 달 동안 다른 컴퓨터에서 사용하고 있으며 지금까지 아무런 문제가 없었으며 MATE 및 Cinnamon 데스크톱에서 테스트했습니다. 또한 cron 내에서 성공적으로 실행했습니다. 및 아나 크론.

이 스크립트는 ArchLinux 용/아래에서 작성 했으므로 다른 Linux 배포판이나 데스크톱에서 문제가 발생하면 알려주세요.

10
Andy

Ubuntu 16.04에서는 crontab에서 루트로 실행되는 스크립트의 알림을 원했습니다. 환경 변수 설정 후 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 변수를 찾는 방법은 아마도 배포판에 따라 다릅니다. Ubuntu 16.04에서는 /run/user/$UID/dbus-session, 간단히 소싱 할 수 있습니다. id -u는 위의 함수에서 who에 의해 반환 된 사용자 이름에서 UID를 가져 오는 데 사용됩니다.

3
mivk

시스템 전체 알림에도이 정보가 필요했습니다. 여기 내 해결책이 있습니다./proc을 스캔하여 모든 세션 버스를 찾은 다음 각 버스에 대해 notify-send를 실행합니다 (버스 당 한 번). 모든 인수는 변경되지 않은 상태로 실제 통지 전송에 전달됩니다.

#!/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);
                        }
                }
        }
' -- "[email protected]"
3
Josef Kufner

다음은 Andy의 스크립트 업데이트입니다. DBUS_SESSION_BUS_ADDRESS는 Centos 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
0
jpf