A script that processes system events using DBus

    Dbus is an interprocess communication tool. In other words, a tool that allows one program to “give orders” to another program.
    It is easy to find examples on the net how to manage various programs from the command line using DBus. But the topic of how to track signals coming from other programs is poorly disclosed. In this article I want to correct this injustice and analyze an example of processing events received from the system via Dbus.

    In addition to bindings to programming languages ​​for Dbus, there are a number of console programs that allow you to use it from the command line.
    • qdbus - allows you to display a list of services and their interfaces on the console, as well as send commands to applications.
    • dbus-send - allows you to send commands to applications.
    • dbus-monitor - displays information on the received signals to the console at the time they are received.

    Also, when working with DBus, the qdbusviewer program is of interest - a graphical application that allows you to study existing programs in the system that support DBus.

    And so, the promised example.


    Task: write a script that, when establishing a connection to the Internet, will launch the Yandex.Disk client.
    We start qdbusviewer and look for which service can report a change in network status. On the System bus tab, we see the service org.freedesktop.NetworkManager. If in this service we go along the path / org / freedesktop / NetworkManager, we find an object that implements the interface org.freedesktop.NetworkManager. There is a StateChanged signal in this interface. Check: Right-click on the signal and select Connect. We disconnect, connect the network interface, we see incoming signals reporting the status of the network. What we need.
    Now we will achieve the same result on the command line. We will use the dbus-monitor command. Enter at the command line:
    dbus-monitor --system "sender=org.freedesktop.NetworkManager, path=/org/freedesktop/NetworkManager, member=StateChanged"
    

    Here the option --system is an instruction to listen to the system bus. The quotation marks indicate the filter of the signal of interest to us. The service org.freedesktop.NetworkManager, the path / org / freedesktop / NetworkManager, and the StateChanged signal.
    Disconnect, connect the network interface. In the process of changing the network status, the console displays all new lines:
    signal sender=org.freedesktop.DBus -> dest=:1.540 serial=2 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=NameAcquired
       string ":1.540"
    signal sender=:1.2 -> dest=(null destination) serial=1870 path=/org/freedesktop/NetworkManager; interface=org.freedesktop.NetworkManager; member=StateChanged
       uint32 20
    signal sender=:1.2 -> dest=(null destination) serial=1883 path=/org/freedesktop/NetworkManager; interface=org.freedesktop.NetworkManager; member=StateChanged
       uint32 40
    signal sender=:1.2 -> dest=(null destination) serial=1899 path=/org/freedesktop/NetworkManager; interface=org.freedesktop.NetworkManager; member=StateChanged
       uint32 70
    

    For each received signal, 2 lines are output. The first with a description of the signal, the second with the value of the argument. By the way, if the signal has more arguments, then there will be more lines.
    It has been experimentally determined that the value of the connected network corresponds to 70.
    Strictly speaking, you need to look at the constant values ​​in the NM_STATE documentation (thanks to avalak for the link)

    Now we need to process the received signals and form the Yandexdisk launch command. Enter at the command line:
    dbus-monitor --system "sender=org.freedesktop.NetworkManager, path=/org/freedesktop/NetworkManager, member=StateChanged" | sed -u -n 's/   uint32 70/yandex-disk start/p'
    

    We added the previous command line | sed -u -n 's / uint32 70 / yandex-disk start / p'. Here we process each line received from dbus-monitor using the sed program. The -u option tells sed to output the result immediately, without delaying the buffer. The -n option does not display anything until there is an explicit command. In single quotes, the command is indicated to the sed program: replace the phrase "uint32 70" with the phrase "yandex-disk start" in the string and display the result. Such a command converts text
    signal sender=org.freedesktop.DBus -> dest=:1.540 serial=2 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=NameAcquired
       string ":1.540"
    signal sender=:1.2 -> dest=(null destination) serial=1870 path=/org/freedesktop/NetworkManager; interface=org.freedesktop.NetworkManager; member=StateChanged
       uint32 20
    signal sender=:1.2 -> dest=(null destination) serial=1883 path=/org/freedesktop/NetworkManager; interface=org.freedesktop.NetworkManager; member=StateChanged
       uint32 40
    signal sender=:1.2 -> dest=(null destination) serial=1899 path=/org/freedesktop/NetworkManager; interface=org.freedesktop.NetworkManager; member=StateChanged
       uint32 70
    signal sender=:1.2 -> dest=(null destination) serial=1870 path=/org/freedesktop/NetworkManager; interface=org.freedesktop.NetworkManager; member=StateChanged
       uint32 20
    signal sender=:1.2 -> dest=(null destination) serial=1883 path=/org/freedesktop/NetworkManager; interface=org.freedesktop.NetworkManager; member=StateChanged
       uint32 40
    signal sender=:1.2 -> dest=(null destination) serial=1899 path=/org/freedesktop/NetworkManager; interface=org.freedesktop.NetworkManager; member=StateChanged
       uint32 70
    

    in
    yandex-disk start
    yandex-disk start
    

    That is, at each connection to the network, the yandex-disk start command is generated.

    Finally, the final version:
    dbus-monitor --system "sender=org.freedesktop.NetworkManager, path=/org/freedesktop/NetworkManager, member=StateChanged" | sed -u -n 's/   uint32 70/yandex-disk start/p' | sh
    

    Sends the generated Yandex.Disk command for execution.

    Save to file
    #!/bin/bash
    dbus-monitor --system "sender=org.freedesktop.NetworkManager, path=/org/freedesktop/NetworkManager, member=StateChanged" | sed -u -n 's/   uint32 70/yandex-disk start/p' | sh
    

    We make the file executable. And add to autorun. Now, when connected to the Internet, the Yandex.Disk client will automatically start.

    Similarly, you can process the signals of any application supporting DBus.

    The article examined the possibility of automating the processing of signals from various applications using DBus. To monitor signals in the console, the dbus-monitor program is used. This program allows you to catch as all the signals of all services, and filter out only what interests us.
    A few examples:
    • dbus-monitor - all driven from all applications.
    • dbus-monitor --system "sender = org.freedesktop.NetworkManager" - all signals from NetworkManager.
    • dbus-monitor --system "sender = org.freedesktop.NetworkManager, path = / org / freedesktop / NetworkManager" - all signals from the / org / freedesktop / NetworkManager object in the NetworkManager service.
    • dbus-monitor --system "sender = org.freedesktop.NetworkManager, path = / org / freedesktop / NetworkManager, member = StateChanged" - only the StateChanged signal from the / org / freedesktop / NetworkManager object in the NetworkManager service

    dbus-monitor displays several lines for each received signal. In the first description of the signal, in the subsequent values ​​of the arguments.
    Next, we process the received signals as we please.

    Also popular now: