crontabからNotify-Sendが機能しない


44

私が読んでいる漫画の新しい章があるときに私に通知するスクリプトを作成しました。これを行うには、コマンドnotify-sendを使用しました。このプログラムは、ターミナルで実行しようとすると機能します。通知が表示されています。ただし、これをcrontabに配置すると、通知が表示されません。ファイルを作成するために作成したので、プログラムが実行されていると確信しています。ファイルは作成されましたが、通知は表示されませんでした。

これが私のスクリプトです

#!/bin/bash   
#One Piece Manga reminder    
#I created a file named .newop that contains the latest chapter.    
let new=$(cat ~/.newop)    
wget --read-timeout=30 -t20 -O .opreminder.txt http://www.mangareader.net/103/one-piece.html

if (( $(cat .opreminder.txt | grep "One Piece $new" | wc -l) >=1 ))    
then    
    (( new+=1 ))    
    echo $new    
    echo $new > ~/.newop    
    notify-send "A new chapter of One Piece was released."    
else    
    notify-send "No new chapter for One Piece."    
    notify-send "The latest chapter is still $new."    
fi        
exit

そして、これが私がcrontabに書いたものです

0,15,30,45 12-23 * * 3   /home/jchester/bin/opreminder.sh

念のために、crontabのすべてのコマンドは、rootとして実行するときにパスを前に置く必要があります。crontabファイル内のスクリプトとラインがそうでなければ、私たちは自分の問題を推測されている役立つだろう取り付ける
ミーアボルグ

ええ、ごめんなさい。今やりました。
user158335

これは悪い考えです。通知は「GUI」であり、cronは「コンソール」です。lib-notifyがメッセージを表示する方法を見つけることができるというゴーレンティはありません。代わりに、データをstdoutに送信することを検討し、cronのメッセージングに情報の送信を任せる必要があります。通常、電子メールが送信されます。
coteyr

2
DISPLAY変数の設定も役立つ場合がありますexport DISPLAY=:0。例:
グルタニメート

1
のために16.04、これは私のために働いた */1 * * * * eval "export $(egrep -z DBUS_SESSION_BUS_ADDRESS /proc/$(pgrep -u $LOGNAME gnome-session)/environ)";/usr/bin/notify-send -i appointment -c "im" "Keep Working"
-KrIsHnA

回答:


18

コマンドはその場所を参照する必要があります。だからnotify-sendする必要があります/usr/bin/notify-send

すべてのコマンドには完全なパスが必要です。

whereis notify-sendコマンドを使用して、コマンドの「ライブ」の場所を確認します


2
cat、wget、if、let、grep、echoなどが含まれますか?
user158335

7
少なくとも私のシステムでnotify-sendPATH、cronジョブは偶数です。以下の私の答えをご覧ください。
krlmlr

2
Ubuntu 17.04のソリューションではありません。代わりにaskubuntu.com/a/472769/413683およびaskubuntu.com/a/834479/413683をご覧ください。
マテウスピオトロフスキ

2
これは問題ではありません。問題は、cronスクリプトがユーザーセッションで実行されず、ユーザーのログインセッションの環境の概念がないことです。notify-sendは通知を送信するためにdbusセッションバスに接続する必要があるため、正しいセッションバスに接続しない場合、バイナリがどのパスから呼び出されるかは関係ありません。
ドビー

2
これは答えではありません。確かに、実行可能ファイルが見つからない場合は実行されませんが、実行されます。実際には、not-sendにDBUS_SESSION_BUS_ADDRESSを設定する必要があるため、機能しません。そして、正しい答えはkmirからです。
クリスジェイス

31

少なくともGnome Shellでは、13.04では状況が異なっているようです。

まず、これはenvユーザーzzyxy(rootではない)のcronジョブから実行したときに出力されるものです。

HOME=/home/zzyxy
LOGNAME=zzyxy
PATH=/usr/bin:/bin
XDG_RUNTIME_DIR=/run/user/zzyxy
LANG=en_US.UTF-8
SHELL=/bin/sh
PWD=/home/zzyxy

動作するにnotify-sendは、ubuntuforums.orgに対するDahitiFのコメントDBUS_SESSION_BUS_ADDRESSに従って、環境変数を設定する必要があるようです。実際の仕事の説明に次を追加してください:

eval "export $(egrep -z DBUS_SESSION_BUS_ADDRESS /proc/$(pgrep -u $LOGNAME gnome-session)/environ)";

設定する必要はないようですDISPLAY


4
おかげで、これは最終的に私のために働いたものです。Xubuntuでは、に変更gnome-sessionする必要がありますxfce4-session
shrx

これは、受け入れられたものの明白なヒントとともに、14.04で機能する唯一の答えです。
-Wtower

1
ノーを持っていたgnome-sessionし、使用gnome-shellの代わりに(もありますように注意してくださいgnome-shell-calendar-serverので、pgrep2つのPIDを取得します)。またDISPLAY=:0、2つの物理画面を使用しており、定義されていなかったため、必要でした。ありがとう!
-soyuka

Openbox(CB ++など)を使用している場合は、openboxにスワップインしgnome-sessionます。
ACK_stoverflow

これは正しい答えであり、受け入れられた答えは正しくさえありません。それは必要とさえされていないDISPLAY変数について話し、実際に問題を解決します。
クリスジェイス

24

コマンドnotify-sendは、cronによって起動されたときに画面にメッセージを表示しませんでした。スクリプトの上部にターゲット表示を追加するだけです。例えば:

export DISPLAY=:0

これは、14.10でもやらなければならなかったことです。そうでなければ私は、このエラーになるだろうgdk_mir_display_open Failed to connect to Mir: Failed to connect to server socket: No such file or directory Option parsing failed: Cannot open display:
Joelmob

1
この。そしてecho $DISPLAY、端末で使用して、ディスプレイが実際にあることを確認します:0(通常はそうですが、常にそうではありません)。
マーク

これだけが私のために働いた、私はLinuxミントを使用しています
ハレンドラシン

5

少なくともUbuntu 14.04 の場合、上記のklrmrの応答は正しい答えです。DISPLAYを設定したり、notify-sendのフルパスを明示したり、通常は$ PATHで指定する必要はないようです。

以下は、ラップトップのバッテリー状態が低くなりすぎたときに仮想マシンをシャットダウンするために使用しているcronスクリプトです。上記のklrmrの応答でDBUS_SESSION_BUS_ADDRESSを設定する行は、最終的に警告が正しく機能するように修正したものです。

#!/bin/bash

# if virtual machine is running, monitor power consumption
if pgrep -x vmware-vmx; then
  bat_path="/sys/class/power_supply/BAT0/"
  if [ -e "$bat_path" ]; then
    bat_status=$(cat $bat_path/status)
    if [ "$bat_status" == "Discharging" ]; then
      bat_current=$(cat $bat_path/capacity)
      # halt vm if critical; notify if low
      if [ "$bat_current" -lt 10 ]; then
        /path/to/vm/shutdown/script
        echo "$( date +%Y.%m.%d_%T )" >> "/home/user/Desktop/VM Halt Low Battery"
        elif [ "$bat_current" -lt 15 ]; then
            eval "export $(egrep -z DBUS_SESSION_BUS_ADDRESS /proc/$(pgrep -u $LOGNAME gnome-session)/environ)";
            notify-send -i "/usr/share/icons/ubuntu-mono-light/status/24/battery-caution.svg"  "Virtual machine will halt when battery falls below 10% charge."
      fi
    fi
  fi
fi

exit 0

今では完璧に動作します-私はcrontabファイルから実行することをこれは、同様に私のために完璧に働いたソリューションは、私はちょうど私のスクリプトに「evalの...」の行を追加した
MTLのDev

2

私の場合、ubuntu 16.04では明示的なパスが必要でしたが、追加するだけで問題を解決します

DISPLAY =:0

notify-sendを呼び出す前に、crontabの最初の行で。


16.04で動作させるために必要なのはこれだけです。
ジョナサンランドラム

1

最初の原因はcrontabファイルです。また、スクリプトを実行する必要があるユーザー名を記載する必要があります。これは、rootとして保持する方が適切です。

0,15,30,45 12-23 * * 3 root   /home/jchester/bin/opreminder.sh

そして、スクリプト内でGUIユーザーのuser_nameを使用し、「sudoまたはsu」でnotify-sendに追加して、GUIを所有するユーザーとしてコマンドを実行する必要があります。

例:

su gnome_user_name -c 'notify-send "summary" "body"'

または

sudo -u gnome_user_name notify-send "summary" "body"

どこgnome_user_nameでログインして、それはあなたですGUIセッションを開始したユーザのユーザ名であり、あなたはそれをダイナミックピックを作りたい場合は、あなたからそれを得ることができます

GNOME_USER=`ps -eo uname,cmd | grep gnome-session| head -1 | cut -d' ' -f1 `

例:

su $GNOME_USER -c 'notify-send "summary" "body"'

または

sudo -u $GNOME_USER notify-send "summary" "body"

1
私はあなたのユーザ名が長いXの文字を超えるとき、あなたのusernmaが切り捨てられていることを考える:たとえば、私のユーザー名はあるoniltonmacielが、$GNOME_USER表示されるでしょうonilton+(仕事をしません)
Oniltonマシエル

より良いコマンドで修正
S471

1

バイナリがdbusアドレスを取得する方法は最近変更されたようです。「notify-send 0.7.6」を使用するUbuntu 15.04(Vivid Vervet)では、次の2つの変数が必要です。

export HOME=/home/$notify_user
export DISPLAY=:0.0

'krlmlr'によるステートメントは正常に評価され、正しいアドレスを設定しますが、ダイアログはcronジョブからポップアップしません。


0

crontab内のスクリプトがrootとして実行されている場合、上記の回答はおそらく機能しません。この機能を試してください。これは16.04でうまく機能します。

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 
}

(ソース:https : //unix.stackexchange.com/a/344377/7286


0

dbus-sessionプロセスに依存する方が適切でDBUS_SESSION_BUS_ADDRESSあり、存在するすべてのシステムで実行する必要があります。

スクリプトを作成します。

#!/bin/bash
# notify.sh

environs=`pidof dbus-daemon | tr ' ' '\n' | awk '{printf "/proc/%s/environ ", $1}'`
export DBUS_SESSION_BUS_ADDRESS=`cat $environs 2>/dev/null | tr '\0' '\n' | grep DBUS_SESSION_BUS_ADDRESS | cut -d '=' -f2-`
export DISPLAY=:0

notify-send "It works!"

実行可能にする:

$ chmod +x ~/notify.sh

crontabに追加します。

* * * * * $HOME/notify.sh

0

これは、ubuntu 15.10で動作するために永遠にかかりました。ユーザーに通常のenv変数を取得するためのソースを追加する必要がありました。私のディスプレイも何らかの理由で:1でした。gnome-sessionを使用すると、DBUS_SESSION_BUS_ADDRESSルックアップの最初のpidが得られます。

# Crontab is
* 21 * * * /bin/sh /home/tristik/cron.sh
#!/bin/sh 
# cron.sh
# Notifies the user of date and time
source /home/tristik/.bashrc
pid=$(pgrep -u tristik gnome-session | head -n 1)
dbus=$(grep -z DBUS_SESSION_BUS_ADDRESS /proc/$pid/environ | sed 's/DBUS_SESSION_BUS_ADDRESS=//' )
export DBUS_SESSION_BUS_ADDRESS=$dbus
export HOME=/home/tristik
export DISPLAY=:1
/usr/bin/notify-send 'title' "$(/bin/date)"

0

次のレシピを使用して、Ubuntu 15.10のcinnamonデスクトップで動作するようになりました。

if [ ! -v DBUS_SESSION_BUS_ADDRESS ]; then
  pid=$(pgrep -u $LOGNAME cinnamon-sessio)
  eval "export $(\grep -z DBUS_SESSION_BUS_ADDRESS /proc/$pid/environ)"
fi
notify-send "$RESUME" "$INFO"

トリックは、「シナモンセッション」がpgrepが見つけるには長すぎることを認識することでした。

$ pgrep -u $LOGNAME cinnamon-session
$ pgrep -u $LOGNAME cinnamon
30789
30917
30965
30981
31039
31335
$ ps -a | \grep cinnamon
30789 tty2     00:00:00 cinnamon-sessio
30917 tty2     00:00:02 cinnamon-settin
30965 tty2     00:00:00 cinnamon-launch
30981 tty2     00:04:15 cinnamon
31039 tty2     00:00:00 cinnamon-killer
31335 tty2     00:00:00 cinnamon-screen
$ ps a | \grep cinnamon
 4263 pts/1    S+     0:00 grep cinnamon
30779 tty2     Ssl+   0:00 /usr/lib/gdm/gdm-x-session --run-script cinnamon-session-cinnamon
30789 tty2     Sl+    0:00 cinnamon-session --session cinnamon
30917 tty2     Sl+    0:02 /usr/lib/x86_64-linux-gnu/cinnamon-settings-daemon/cinnamon-settings-daemon
30965 tty2     Sl+    0:00 /usr/bin/python2 /usr/bin/cinnamon-launcher
30970 tty2     Sl+    0:00 /usr/lib/x86_64-linux-gnu/cinnamon-settings-daemon/csd-printer
30981 tty2     Sl+    4:16 cinnamon --replace
31039 tty2     Sl+    0:00 /usr/bin/python2 /usr/bin/cinnamon-killer-daemon
31335 tty2     Sl+    0:00 cinnamon-screensaver
$ pgrep -u $LOGNAME cinnamon-sessio
30789

私のgrepのエイリアスは\ grepでもあるため、

$ alias grep
alias grep='grep -n --color=always'

0

Ubuntu 18.04でi3を使用しています。これを解決する私の方法は次のとおりです。

* * * * * XDG_RUNTIME_DIR=/run/user/$(id -u) notify-send Hey "this is dog!"


0

ロケールを使用python3してcrontabを呼び出すと発生する問題UTF-8

TL; DR: crontab w / localeのプレフィックス呼び出し:

*/5 * * * * LC_ALL=en_US.utf-8 LANG=en_US.utf-8 ~/.local/bin/watson-notify

clickおよびpython3も参照してください:

Traceback (most recent call last):
  File "/usr/lib/python3.6/runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "/usr/lib/python3.6/runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "/usr/lib/python3/dist-packages/watson/__main__.py", line 6, in <module>
    cli.cli()
  File "/usr/lib/python3/dist-packages/click/core.py", line 759, in __call__
    return self.main(*args, **kwargs)
  File "/usr/lib/python3/dist-packages/click/core.py", line 693, in main
    _verify_python3_env()
  File "/usr/lib/python3/dist-packages/click/_unicodefun.py", line 123, in _verify_python3_env
    'for mitigation steps.' + extra)
RuntimeError: Click will abort further execution because Python 3 was configured to use ASCII as encoding for the environment.  Consult http://click.pocoo.org/python3/ for mitigation steps.

This system supports the C.UTF-8 locale which is recommended.
You might be able to resolve your issue by exporting the
following environment variables:

    export LC_ALL=C.UTF-8
    export LANG=C.UTF-8

0

libnotifyを使用するすべてのcrontabスクリプトについて、これを使用します。

notify_user() {
    local user=$(whoami)
    notify-send -u normal -t 4000 "System Backup" "Starting backup"
}

notify_user # and do other stuff

ルートモードでcronを使用しても動作します。


0

必要なのはX_userとX_useridだけです。以下のコマンドで両方を置き換えます。

systemdによるソリューション

/etc/systemd/system/opreminder.service#サービスファイル

[Unit]
Descrption=some service to run

[Service]
User=[X_user]
ExecStart=/home/jchester/bin/opreminder.sh


/etc/systemd/system/opreminder.timer #timerファイル

[Unit]
Description=Some desc


[Timer]
OnCalendar=0,15,30,45 12-23 * * 3 

[Install]
WantedBy=list.timer.target

/home/jchester/bin/opreminder.sh#スクリプト

#!/usr/bin/env bash

sudo -u [X_user] DISPLAY=:0 DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/[X_userid]/bus notify-send 'Hello world!' 'This is an example notification.'

サービスファイルが目的のユーザーで既に設定されている場合、sudo -uを使用する必要はありません。

ソース:https : //wiki.archlinux.org/index.php/Desktop_notifications#Usage_in_programming

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.