Knowledge Base

Preserving for the future: Shell scripts, AoC, and more

Send desktop notifications through ssh X forwarding

last updated: 2023-12-05

Thanks directly to a user at StackExchange! If you have desktop notifications on your ssh server that you wish to display on your local X server, you can accomplish that with a few steps. In the session you intend to forward desktop notifications, you need to make sure the DBUS_* environment variables are set. From Unix.SE:

START="dbus-launch --exit-with-session"
# set dbus for remote SSH connections
if [ -n "$SSH_CLIENT" -a -n "$DISPLAY" ]; then
   machine_id=$(LANGUAGE=C hostnamectl|grep 'Machine ID:'| sed 's/^.*: //')
   x_display=$(echo $DISPLAY|sed 's/^.*:\([0-9]\+\)\(\.[0-9]\+\)*$/\1/')
   dbus_session_file="$HOME/.dbus/session-bus/${machine_id}-${x_display}"
   if [ -r "$dbus_session_file" ]; then
      export $(grep '^DBUS.*=' "$dbus_session_file")
      # check if PID still running, if not launch dbus
      ps $DBUS_SESSION_BUS_PID | tail -1 | grep dbus-daemon 1> /dev/null 2>&1
      [ "$?" != "0" ] && export $(${START}) 1> /dev/null 2>&1
   else
      export $(${START}) 1> /dev/null 2>&1
   fi
fi

I set this ~/bin/forward-notifications.sh, but the author places it directly in his ~/.bashrc. If this snippet is in a separate script the way I use it, you need to dot-source it.

. forward-notifications.sh

But you still also need at least one .service file that handles org.freedesktop.Notifications. I use Xfce on my X server system, so I just installed its notification library.

$ apt-file search .service | grep -i notif
xfce4-notifyd: /usr/lib/systemd/user/xfce4-notifyd.service
$ sudo apt-get install xfce4-notifyd

And then your notify-send or zenity --notification commands will work!

Package for Devuan: xpipe

I came across a great little tool, xpipe, recently. Very few distros provide xpipe, so I have bundled it into a dpkg for Devuan GNU+Linux and similar distros. It's available on my OBS space. To quote directly from the project readme:

The xpipe command reads input from stdin and splits it by the given number of bytes, lines, or if matching the given pattern. It then invokes the given utility repeatedly, feeding it the generated data chunks as input. You can think of it as a Unix love-child of the split(1), tee(1), and xargs(1) commands. It's usefulness might best be illustrated by an example. Suppose you have a file 'certs.pem' containing a number of x509 certificates in PEM format, and you wish to extract e.g., the subject and validity dates from each. The openssl x509(1) utility can only accept a single certificate at a time, so you'll have to first split the input into individual files containing exactly one cert, then repeatedly run the x509(1) command against each file.

Coincidentally, parsing a large .pem file was exactly what I was trying to do! It was not my very first case where xpipe would have been useful (splitting paragraphs) but is definitely my most prominent use case.

Recipes, as in food, and easy focaccia bread

I was inspired by a github repo for food recipes that I came across recently. I was amused the author had to specify "actual food recipes," because the word recipe can mean so much in this technical world we live in. I store my recipes in plain text, in a format fairly similar to jschauma does. Here is one such recipe:

Recipe: Easy focaccia bread
Source: https://www.womanscribbles.net/easy-focaccia-bread/
Date: 2020-04-19

Ingredients:
2 3/4 cups all-purpose flour
1 tsp salt
1 tsp sugar
1 tbsp active dry yeast (1 packet is only 2.25 tbsp, so add a pinch of baking powder)
1/2 tsp dried oregano
1/4 tsp dried basil
1 pinch ground black pepper
1 cup warm water 105-115 F
1 tbsp vegetable oil
1 clove garlic minced
2 tbsp olive oil
1/4 cup grated parmesan

Oven: 425°F, 12-16m

Directions:
1. In a large bowl, stir together flour, suguar, yeast, salt, ground pepper, and spices. Stir water and oil in. When the dough is "shaggy," turn it over onto a lightly floured surface.
2. Add the garlic and knead for 6-8 minutes.
3. Cover and let rise in a greased bowl for 45 minutes. It might not necessarily double in size.
4. Punch down dough, and place on a baking sheet. Form no thicker than 1/2inch. Cover again and let rise for 25 minutes.
5. Indent surface with fingertips, all over. Brush with a small amount of olive oil, and do not let it pool. Sprinkle parmesan cheese (more is better), and some salt.
6. Bake at 425°F for 12-16 minutes or until lightly golden.

Python3 run command and convert stdout from csv to json

Because apparently this is a non-trivial process to find on the Internet.

import os, sys, subprocess, json, csv

def get_json(username):
   result = []
   # https://stackoverflow.com/a/19706994
   # https://stackoverflow.com/a/33927495
   # https://stackoverflow.com/a/8880539
   cmd = "/path/to/csv-generator.sh"
   a = subprocess.Popen([cmd,username], stdout=subprocess.PIPE) # output is a CSV
   b = a.communicate()[0].decode('utf-8')
   c = csv.DictReader(b.splitlines())
   # fieldnames must be left undefined, to read first row as column titles
   for row in c:
      try:
         row.pop("") # try removing blank key, because CSV is proper format and ends with trailing comma
      except:
         pass
      result.append(row)
   return json.dumps(result)

if __name__ == "__main__":
   print(get_json("bgstack15"))

And in the future, use AD groups for access control instead of a custom database, devs...

Extending my vpn to route all my traffic for my vpn clients

I read on the Internet that you can route all traffic through your vpn to your house to take advantage of everything you already run for your home network. For me, this includes robust ad- blocking, and of course various network services not available to the public. To extend my new, fancy wireguard vpn, I took some extra steps so I could route all traffic through my home network.

On server

On my wireguard "server" (the peer that is at my house) I added firewall rules. At first I fiddled with nftables (which has supplanted iptables), but eventually found that I was supposed to use firewalld on CentOS 8.

sudo firewall-cmd --add-masquerade --permanent

And then set sysctl value to allow forwarding.

sudo sysctl net.ipv4.ip_forward=1

And for permanency, set file /etc/sysctl.d/wg.conf:

net.ipv4.ip_forward = 1

On client

And then add on the Android client the allowed IP address 0.0.0.0/0. The Android app adds the correct routing already!

References

Weblinks

  1. How to setup a VPN server using WireGuard (with NAT and IPv6)
  2. Beginners Guide to nftables Traffic Filtering - Linux Audit
  3. WireGuard on Alpine Linux with nftables
  4. Using FirewallD as a Linux Router | A Little Guy and His Blog

Connecting my mobile phone to my home network for playing media

I use Plex, which is OK, but I don't like having to depend on an external service to access my own media files. I have successfully set up a VPN to my home network, so that my mobile phone can access my media files from anywhere! I set up WireGuard as a vpn, so VLC on Android can play my files from my nfs server at home!

On Linux server

On my nfs server (CentOS 8), I installed wireguard, the up-and-coming VPN solution that can be included in the Linux kernel! I used method two, using kmod, but from rpmfusion which I already had enabled.

sudo yum install kmod-wireguard wireguard-tools

Then I set up file /etc/wireguard/wg0.conf. There was a template file somewhere with some better notes, but this is the boiled-down version.

[Interface]
Address = 10.222.0.1/24
ListenPort = 51820
# from `wg genkey`
PrivateKey = 123456789009876543211234567890=
# server1 public key, from `echo "${PrivateKey}" | wg pubkey`
# 123456789012345678901234567890=
[Peer]
# my mobile phone's public key, from below instructions
PublicKey = 01982643901625901902283497598275=
AllowedIPs = 10.222.0.2/32
PersistentKeepalive = 25

I chose to save the public key right there in the config file, in case I need to retrieve it often! And then I had to open the firewall, of course.

sudo firewall-cmd --add-port=51820/udp --permanent

I also had to forward port 51820 in my router to my server's IP address. And then I took virtual NIC up!

sudo wg-quick up wg0

Because my plan included accessing NFS with VLC for Android, I needed to add a rule in /etc/exports :

/var/server1/shares 10.222.0.0/24(ro,sync,insecure)

And update the current export list.

sudo exportfs -ra

And to make sure the wireguard interface

On android mobile phone

I installed the official Wireguard app from F-droid. I appreciate how the app lets you configure interfaces and peers in a manner that looks basically identical to the contents of the config file used to define an interface+peers on a full GNU/Linux system! I named the interface, and added my IP address of 10.222.0.2/32. I also listed DNS servers that are on my home network. I hard-coded the listen port to 51820. For the peer, I added the public key from my server1 above. Allowed IPs: 10.222.0.0/24,192.168.1.0/24 As I understand it, the allowed IP addresses indicate what networks will be routed through the VPN. So here I am including the VPN network, and also my home network's main IP network. Endpoint: (my ddns name):51820 Persistent keepalive: 25 seconds.

Conclusion

I don't know how to perform low-level network diagnostics from Android such as ping or netcat, so I really only tested from my server. I pinged the client (once all wireguard interfaces were up on both devices). And for the final test, I was out driving in my car, and I had an opportunity to enable my wireguard interface on my phone, run VLC, and connect to my nfs server and play music! So this was a successful operation (even if it is a bit flaky, due to nfs's dislike of spotty networks). And now I don't need

Package for Devuan: gtk3-automnemonics

I have packaged up another nifty little thing that can improve the desktop experience for GTK3-based desktops and applications. Gtk3-automnemonics allows GTK3 themes to set the old "gtk-auto-mnemonics = true" or false, where false means that the underscores that highlight the accelerator keys are always visible. An accelerator key is the F in " F ile" where pressing ALT+F will open that File menu. You can go install gtk3-automnemonics from my OBS now. Its sources are also visible on the OBS. The upstream project is written by Gord Squash. How to use gtk3-automnemonics, once installed, is to modify the gtk-3.0/settings.ini file of a theme directory (probably under /usr/share/themes or ~/.local/share/themes) to include:

[Settings]
gtk-auto-mnemonics = 0
gtk-modules = sgm-flexible-mnemonics

The gtk-modules line is optional, because the gtk3-automnemonics package already adds an Xsession.d snippet that adds to/defines environment variable GTK3_MODULES value "sgm-flexible-mnemonics".

Backstory

GTK 3.10 removed the ability to configure the ability to always show the underscores. It is now hardcoded to 300ms after pressing the ALT key. Some people may prefer to hide the underscores until asked for, by the use of the ALT key. Some of us prefer always showing the underscores. But we all lose when it is no longer configurable.

References

Weblinks

  1. GTK 3.10 Drops Menu Icons and Mnemonics « IgnorantGuru's Blog
  2. gtk - How to enable mnemonics in 12.04 and/or 14.04 GTK3? - Ask Ubuntu
  3. Deprecate and ignore gtk-enable-mnemonics and gtk-auto-mnemonics" pro… · GNOME/gtk@7e3a494

Package for Fedora: xzoom

I was looking for screen magnifier program. Fedora tends to focus almost exclusively on GNOME 3, which includes some sort of magnifier directly in the shell (I'm assuming). KDE has a screen magnifier, but I couldn't justify installing a whole 127MB stack of packages for a screen magnifier. So I found in the Debian repos xzoom package, which has minimal dependencies and actually does the type of magnification I am looking for: focus on a single part of the screen! I guess I was expecting to see a magnifier that follows the mouse focus. If I ever need that, I guess I'm going to have to keep looking for a solution. But, xzoom focuses on a specific part of the screen (which you can move, by clicking and dragging from the xzoom window, to the target area that should be magnified), and this is what I needed. I slapped together some SUSE package components, and some patches from a few places, and put xzoom on my copr. Screenshot showing xzoom magnifying part of the
screen

Show kerberos ticket status in system tray

I came across a great little utility that does exactly what I was considering writing! I want to monitor my kerberos ticket status in my graphical session, and just poking around with apt-cache search led me to krb5-auth- dialog (salsa fedora src). This utility displays a system tray icon (if you tell it to ignore the Gnome3 behavior of not using a tray icon) with the current status of the kerberos ticket(s). It will notify you so many minutes (configurable) before your ticket expiration. I had to poke around in the source code to learn how to get it to show the tray icon. You have to set a debug environment variable to include the string "no-persistence."

KRB5_AUTH_DIALOG_DEBUG="no-persistence,no-app-menu,no-header-bar" gtk3-nocsd krb5-auth-dialog

And this application is still packaged for Debian and Fedora! I'm shocked the Fedora team hasn't disposed of it yet, but I guess it's zero-maintenance so orphaning it is more work than incrementing the rpm version for each new Fedora release.

Convert .lnk shortcut to symlink

Related to my Web gallery solution and Symlink forest generator, I wanted a way to convert Windows-style shortcuts (.lnk files) to symlinks. Apparently I am the first person to publish this research on the Internet. Nobody else in the world has discussed performing this operation. It's probably foolhardy, but it was technically interesting. I wrote the shortcut2symlink python library and cli tool.

Overview

A Windows client is used to maintain a website/ subdirectory of files that will be processed using the gallery project. To facilitate the process of preparing files for this website/ subdirectory, particularly over a wireless network connection, users have been instructed to just make Windows-style shortcuts (using CTRL+SHIFT dragging) in the website subdirectory in whatever layout desired. This project includes components that will scan the designated directory for .lnk files anywhere underneath, and interpret their targets, and generate symlinks in place of the .lnk files. Unfortunately my scanner (inotify) is slightly flaky, and sometimes I still need to manually run the s2s.py command directly. The point of using symlinks in this case is to reduce the disk usage and number of duplicate files and directories. To SMB users on the Windows client, the symlink files will look like copies, but that is acceptable because the main focus is the gallery generation for the web server.

Reason for existence

Reduce disk space by removing duplicate files, while still having a whole directory structure readable by the gallery solution for generating static site pages, and while making it easy for wireless network users to "manage" links to files at least initially.

Example usage

For the inotify script:

/mnt/public/Support/Programs/shortcuts/s2s-inotify.sh /mnt/public/Images/username1-photos/website

And for manually running:

/mnt/public/Support/Programs/shortcuts/s2s.py --indir /mnt/public/Images/username1-photos/website --apply --debug 8 --delete

References

Weblinks

.lnk format reference