16

I keep getting very strange notifications which go away before I can read them, they are long, and appear at random times, the most recently one came up was during a kernel upgrade, it had a strange icon, and was long, but I didn't manage to read it because it was on the screen so briefly.

So I am wondering if there is any log which logs all calls to notify-send which logs the program calling it, and all the parameters given? Or if I can set up such a log to find out what these notifications are about? I am running Ubuntu GNOME 15.10 with GNOME 3.18.

Jacob Vlijm
  • 85,475

2 Answers2

16

Even didn't need a full script...
...but put it in the form of a script:

#!/bin/bash

file=$1

dbus-monitor "interface='org.freedesktop.Notifications'" |\
 grep --line-buffered "string" |\
 grep --line-buffered -e method -e ":" -e '""' -e urgency -e notify -v |\
 grep --line-buffered '.*(?=string)|(?<=string).*' -oPi |\
 grep --line-buffered -v '^\s*$' |\
 xargs -I '{}' echo {} >> $file

To run it

  • Copy the "script" into an empty file, save it as keep_log.sh
  • Run it with the logfile as argument with the command

    /bin/bash /path/to/keep_log.sh /path/to/log.txt
    

The answer was retrieved from an earlier answer (not a dupe), in which this application of the method was mentioned as an example.

The answer I gave there, on its own turn, was based on this very nice answer, in which is explained that the method uses dbus-monitor to intercept the contents of notify-send. By editing the example there, we can make it write notify-send messages to a (log-) file.

Or, more elegant

...would be to add the date to the logfile, producing a logfile like:

---di 10 mei 2016 17:37:20 CEST---
SOme kind of a message!
---di 10 mei 2016 17:37:20 CEST---
The last message was misspelled so here i9s another one

In that case, the script would be:

#!/bin/bash

logfile=$1

dbus-monitor "interface='org.freedesktop.Notifications'" |\
grep --line-buffered "string" |\
grep --line-buffered -e method -e ":" -e '""' -e urgency -e notify -v |\
grep --line-buffered '.*(?=string)|(?<=string).*' -oPi |\
grep --line-buffered -v '^\s*$' |\
xargs -I '{}' \
printf "---$( date )---\n"{}"\n" >> $logfile
Jacob Vlijm
  • 85,475
2

I've always wanted this myself, and tried the suggestions here to no great avail, the output of the dbus-monitor being too complex for such simple handling. So I whipped up a small solution I'm using now, having finally bitten the bullet. It's just an extension of the existing solution but implements far more rigorous processing and add some ease of use tools.

https://github.com/bernd-wechner/Linux-Tools/tree/master/nlog

The script for the record right now is:

#!/bin/bash

Output function to handle printing to either stdout or a file

output() { if [ -n "$logfile" ]; then echo -e "$1" >> "$logfile" else echo -e "$1" fi }

Check if a filename argument is provided

logfile="" if [ -n "$1" ]; then logfile="$1" # Create the directory if it doesn't exist logdir=$(dirname "$logfile") mkdir -p "$logdir" touch $logfile fi

Monitor DBus for notification events

dbus-monitor "interface='org.freedesktop.Notifications'" | while read -r line; do # Check for the start of a "Notify" method call if [[ "$line" == "member=Notify" ]]; then app_name="" icon="" title="" body="" hints="" capturing_body=false

    # Read subsequent lines for details
    while read -r line; do
        # Capture app name, icon, title, or start capturing body
        if [[ &quot;$line&quot; == *&quot;string \&quot;&quot;* ]]; then
            value=$(echo &quot;$line&quot; | sed 's/^.*string &quot;\(.*\)&quot;/\1/')

            if [ -z &quot;$app_name&quot; ]; then
                app_name=&quot;$value&quot;
            elif [ -z &quot;$icon&quot; ]; then
                icon=&quot;$value&quot;
            elif [ -z &quot;$title&quot; ]; then
                title=&quot;$value&quot;
            else
                capturing_body=true
                body=&quot;$value&quot;
            fi
        elif $capturing_body; then
            # Continue capturing body text if we're in the body section
            if [[ &quot;$line&quot; == *&quot;array [&quot;* ]]; then
                capturing_body=false
            else
                # Strip leading spaces and trailing quotes from the body
                line=$(echo &quot;$line&quot; | sed -e 's/^ *//' -e 's/&quot;$//')
                body+=&quot; $line&quot;
            fi
        elif [[ &quot;$line&quot; == *&quot;dict entry(&quot;* ]]; then
            capturing_body=false
            hint_key=&quot;&quot;
            hint_value=&quot;&quot;
        elif [[ &quot;$line&quot; == *&quot;string \&quot;&quot;* ]]; then
            if [ -z &quot;$hint_key&quot; ]; then
                hint_key=$(echo &quot;$line&quot; | sed 's/.*string &quot;\(.*\)&quot;/\1/')
            else
                hint_value=$(echo &quot;$line&quot; | sed 's/.*string &quot;\(.*\)&quot;/\1/')
                hints+=&quot;$hint_key: $hint_value\n&quot;
            fi
        elif [[ &quot;$line&quot; == *&quot;]&quot;* ]]; then
            break
        fi
    done

    # Remove the `string &quot;` prefix and trailing `&quot;` from the body, and trim leading/trailing whitespace
    body=&quot;${body#string \&quot;}&quot;
    body=&quot;${body%\&quot;}&quot;
    body=&quot;$(echo -e &quot;${body}&quot; | sed -e 's/^[[:space:]]*//')&quot;

    # Prepare the formatted notification summary
    notification=&quot;----------------------------------\n&quot;
    notification+=&quot;App Name: $app_name\n&quot;
    notification+=&quot;Icon: $icon\n&quot;
    notification+=&quot;Title: $title\n&quot;
    notification+=&quot;Body: \n$body\n&quot;
    notification+=&quot;Hints:\n$hints\n&quot;

    # Output the notification summary
    output &quot;$notification&quot;
fi

done