Linux, Unix, and whatever they call that world these days

Restoring Screen Backlight Brightness in Ubuntu

One of many details available in Windows but not in Ubuntu is automatic backlight change when system switches from AC to battery. And it’s not just a dumb change to predefined value either. Every switch from AC to battery and vice versa restores the last value system had. Ubuntu on the other hand just keeps the backlight as is resulting in me manually adjusting it every time. Lookup on Internet for applications providing this functionality gave me no warm fuzzy feeling so I decided to roll my own. I mean, how hard can it be.

Well, actually annoyingly hard if you want to support every interface out there. As I wanted to support only my Dell XPS 15, I had quite a bit easier work.

The main part of the story is in two files: /sys/class/power_supply/AC/online and /sys/class/backlight/intel_backlight/brightness. All what’s needed was actually a small script handling tracking and restoring brightness values every once in a while. This is roughly what I ended with:

#!/bin/bash

STORED_AC=`cat /var/cache/.backlight.ac`
STORED_BAT=`cat /var/cache/.backlight.bat`

while(true); do
    BRIGHTNESS=`cat /sys/class/backlight/intel_backlight/brightness`
    IS_AC=`cat /sys/class/power_supply/AC/online`
    if [[ "$IS_AC" != "$LAST_AC" ]]; then
        if [[ "$IS_AC" != "0" ]]; then
            if [[ "$STORED_AC" != "" ]]; then
                echo -e "Restoring AC backlight to $STORED_AC"
                echo $STORED_AC > $FILE_BRIGHTNESS
            fi
        else
            if [[ "$STORED_BAT" != "" ]]; then
                echo -e "Restoring battery backlight to $STORED_BAT"
                echo $STORED_BAT > $FILE_BRIGHTNESS
            fi
        fi
        LAST_AC=$IS_AC
    else
        if [[ "$IS_AC" != "0" ]]; then
           if [[ "$STORED_AC" != "$BRIGHTNESS" ]]; then
               echo $BRIGHTNESS > /var/cache/.backlight.ac
               STORED_AC=$BRIGHTNESS
           fi
        else
           if [[ "$STORED_BAT" != "$BRIGHTNESS" ]]; then
               echo $BRIGHTNESS > /var/cache/.backlight.bat
               STORED_BAT=$BRIGHTNESS
           fi
        fi
    fi

    sleep 0.5
done

As you can see, the script is just checking in loop if there was an AC status change. If computer was plugged or unplugged, it simply restores the last saved value for that power state. If power status remained the same, it will track any brightness change so it’s possible to restore it later. Really simple and really working.

And yes, the script above contains no error handling. If you want to see the real stuff, it’s available on GitHub. Even better, it’s available as a Debian package if you want to install it.

Using Ctrl+Shift+Escape for System Monitor in Ubuntu

Moving from Windows to Ubuntu, there is one shortcut I surely miss - Ctrl+Shift+Escape. On Ubuntu this does absolutely nothing.

Fortunately one can always add a custom shortcut to System Monitor:

gsettings set org.gnome.settings-daemon.plugins.media-keys custom-keybindings \
    "['/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0/']"
GSCHEMA=org.gnome.settings-daemon.plugins.media-keys.custom-keybinding
GPATH=/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0/
gsettings set $GSCHEMA:$GPATH name "System Monitor"
gsettings set $GSCHEMA:$GPATH command "gnome-system-monitor"
gsettings set $GSCHEMA:$GPATH binding "<Primary><Shift>Escape"

However, this is not quite “it”. The major issue is that, if System Monitor is already open, it will remain in background. As this is Linux, of course there is a command line solution for this.

First we need to install wmctrl package

sudo apt install wmctrl

Then we can setup a script to run System Monitor and activate it’s window. Since application itself is single instance, this does exactly what we need:

#!/bin/bash
nohup gnome-system-monitor >/dev/null 2>&1 & >/dev/null
wmctrl -Fa 'System Monitor'

To make it runnable, we shouldn’t forget chmod:

$ chmod +x ~/bin/system-monitor

And now finally we can adjust our key binding to call that newly created script:

gsettings set org.gnome.settings-daemon.plugins.media-keys custom-keybindings \
    "['/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0/']"
GSCHEMA=org.gnome.settings-daemon.plugins.media-keys.custom-keybinding
GPATH=/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0/
gsettings set $GSCHEMA:$GPATH name "System Monitor"
gsettings set $GSCHEMA:$GPATH command "$HOME/bin/system-monitor"
gsettings set $GSCHEMA:$GPATH binding "<Primary><Shift>Escape"

I call this close enough.

PIA in Encrypted Home Directory

Upon getting Linux Mint installed, I went ahead with installing VPN by Private Internet Access. Went through the same motions as usually albeit now with slightly different result - it wouldn’t connect.

Looking at logs ($HOME/.pia_manager/log/openvpn.log) just gave cryptic errors:

SIOCSIFADDR: Operation not permitted
: ERROR while getting interface flags: No such device
SIOCSIFDSTADDR: Operation not permitted

Quick search on internet brought me to Linux Mint forum where exactly the same problem was described. And familiarity didn’t stop there; author had one other similarity - encrypted home folder. Sounded like a perfect fit so I killed PIA client and went with slightly modified procedure:

sudo mkdir /home/pia
sudo chown -R $USER:$USER /home/pia
mv ~/.pia_manager /home/pia/.pia_manager
ln -s /home/pia/.pia_manager ~/.pia_manager

However, this didn’t help. Still the same issue in my log files. So I decided to go with atomic option. First I killed PIA client (again) and removed PIA completely together with all my modifications:

rm ~/.pia_manager
sudo rm ~/.local/share/applications/pia_manager.desktop
rm -R /home/pia

With all perfectly clean, I decided to start with fresh directory structure, exactly the same as in the original solution:

sudo mkdir -p /home/pia/.pia_manager
sudo chown -R $USER:$USER /home/pia
ln -s /home/pia/.pia_manager ~/.pia_manager

With directory in place I repeated installation of PIA client:

cd ~/Downloads
tar -xzf pia-v72-installer-linux.tar.gz
./pia-v72-installer-linux.sh

And it worked! :)

Better Vi Coloring

On my default Ubuntu server installation vi is very colorful. However, most of colors are so dark that I cannot really see what’s written against dark window background. This is fortunately mitigated by setting background into “dark mode”.

set background=dark

Second issue I faced was inability to copy/paste from other applications without the whole text being indented like crazy. Of course, there is setting for that too.

filetype indent off

With these two settings, my vi was usable again.

Syncing Time Zone via IPMI

After using UTC time zone exclusively on my servers for a while, I decided to give local time a try for the next 6 months or so. In addition to “normal” shenanigans time zones bring, I got another interesting one - my IPMI servers required me to manually tell them whether daylight saving is in effect or not. What that meant is that, even with time zone set correctly, every daylight saving time change my server’s BMC will be 1 hour off.

As all my servers were Supermicro (M11SDV-4CT-LN4F and A1SRi-2558F) I decided to use Supermicro’s powerful IPMI to programmatically deal with that issue.

My thoughts were going in the following direction. As long as I keep script on my main server that will update time zone information (if needed) twice a day (at 02:00 and 03:00), it should be enough to keep me happy. As retrieving time zone information via IPMI is not something that’s standardized, I contacted Supermicro’s support to get the details. While they didn’t really provide those details, they did point me toward their SMCIPMITool utility.

Unfortunately this didn’t fully solve it for me as it didn’t support FreeBSD. However, it did have debug mode (in SMCIPMITool.properties set debug_level=1) and this really helped.

./SMCIPMITool ^^192.168.1.1^^ ^^admin^^ ^^password^^ ipmi oem x10cfg ntp timezone
 …
 [ YOU -&gt; BMC : ^^30 68 01 00 00^^ ]
 [ YOU &lt;- BMC : 00 01 2D 30 37 30 30 01 ]

With these response bytes it was easy enough to construct ipmitool raw bytes:

ipmitool -I lanplus -H ^^192.168.1.1^^ -U ^^admin^^ -P ^^password^^ raw ^^0x30 0x68 0x01 0x00 0x00^^
 01 2d 30 30 30 30 00

The first byte tells us if NTP is enabled or not, next 5 bytes tells time zone in ASCII (+0000), while the last byte says if daylight saving is on or not.

Using the same principle, it’s easy enough to update IPMI:

ipmitool -I lanplus -H ^^192.168.1.1^^ -U ^^admin^^ -P ^^password^^ raw 0x30 0x68 0x01 0x
 01 0x00 ^^0x01 0x2d 0x30 0x37 0x30 0x30 0x00^^

Trying to script this change is a bit tricky. There isn’t really easy and fireproof method of determining if daylight savings is active. However, I decided to ignore that field and just set offset every time as that’s really easy to determine (date +%z).

The final script was looking something like this:

#!/bin/bash

IP="^^192.168.1.1^^"
USER="^^admin^^"
PASSWORD="^^password^^"

CURR_STATE=`ipmitool -I lanplus -H $IP -U $USER -P $PASSWORD raw 0x30 0x68 0x01 0x00 0x00 | xargs | tr ' ' '\n' | awk '{printf " 0x" $1}' | xargs`
NEXT_STATE="0x01 `date +%z | hexdump -C | head -1 | cut -d' ' -f3-7 | tr ' ' '\n' | awk '{printf " 0x" $1}'| xargs` 0x00"

if [[ "$CURR_STATE" != "$NEXT_STATE" ]]; then
    ipmitool -I lanplus -H $IP -U $USER -P $PASSWORD raw 0x30 0x68 0x01 0x01 0x00 $NEXT_STATE 2>/dev/null
fi

Muting Sound Every Time Ubuntu Starts

Ubuntu 19.04 doesn’t remember audio settings between reboots. This means that after every reboot I need to mute sound again and again. Since making it remember volume between reboots is hard, I went for the next best thing - mute it on reboot to start with.

Command is easy:

amixer set Master mute

To perform it on every startup, we can use @reboot crontab directive. However, be careful which crontab you’re editing as this statement is applicable only for root. It will simply be ignored for any other account’s crontab.

Keeping that in mind, this is what sorted it out for me

sudo crontab -e
@reboot /usr/bin/amixer set Master mute

Now my laptop starts muted and any unmuting is left to my discretion.

Redirect Only Errors to StdOut

The most usual thing I want with redirect is just throwing errors to null:

command >/dev/null

Alternatively, one can throw everything to null:

command >/dev/null 2>1

However, what if you want only error being shown and proper output ignored? Well, there is a redirect for that too:

$ command 2>1 >/dev/null

Using iSCSI from Ubuntu 19.04

Samba has taken over most of my sharing but I still occasionally need iSCSI. Connecting to it from Ubuntu is straight enough. First step is of course installing necessary package:

sudo apt-get install open-iscsi

Next step is simply connecting to iSCSI and discovering the drive name within dmesg output:

sudo iscsiadm -m discovery -t sendtargets -p ^^192.168.1.1^^
 192.168.1.1:3260,1 iqn.2007-09.jp.ne.peach.istgt:somedisk0

sudo iscsiadm --mode node --targetname iqn.2007-09.jp.ne.peach.istgt:^^somedisk0^^ \
    --portal ^^192.168.1.1^^:3260 --login

sudo dmesg | grep "Attached SCSI disk" | tail -1
 [ 3203.813577] sd 2:0:0:0: [^^sda^^] Attached SCSI disk

Lastly, just use the normal mounting to access the disk:

sudo mkdir /mnt/scsi
sudo mount /dev/sda2 /mnt/iscsi

Installing MPLAB X IDE 5.25 on 64-bit Ubuntu 19.04

While I love seeing companies provide Linux version of their software, it still annoys me when they do it as lazily as possible. For example Microchip not only doesn’t provide repository for their software, making you download and install every version separately, but they also don’t provide up-to-date instructions. Their section describing Ubuntu 14.04 and above simply doesn’t work.

To install MPLAB X on newer Ubuntu one must first explicitly add architecture:

sudo dpkg --add-architecture i386
sudo apt-get update
sudo apt install libc6:i386 libx11-6:i386 libxext6:i386 libstdc++6:i386 libexpat1:i386

Only once those are up you can proceed installing MPLAB IDE X itself:

tar -xvf MPLABX-v*-linux-installer.tar
chmod +x MPLABX-v*-linux-installer.sh
sudo ./MPLABX-v*-linux-installer.sh

Of course, installing compiler follows (XC8 in this case):

chmod u+x xc8-v*-full-install-linux-installer.run
sudo ./xc8-v*-full-install-linux-installer.run

And now MPLAB X IDE is installed.


PS: I won’t even go into the need for 32-bit compatibility libraries in 2019…

ZFS Pool for Virtual Machines

Running VirtualBox on ZFS pool intended for general use is not exactly the smoothest experience. Due to it’s disk access pattern, what works for all your data will not work for virtual machine disk access. Yes, you can play with record size and adding SLOG device but you can also go slightly different route. Add disk specifically for VirtualBox.

My testing has found that simple SSD with the following settings does wonders:

zpool create -o autoexpand=on -m /VirtualBox \
    -O compression=off -O recordsize=4K -O atime=off \
    -O utf8only=on -O normalization=formD -O casesensitivity=sensitive \
    VirtualBox /dev/diskid/^^DISK.eli^^

First of all, you don’t want compression. Not because data is not compressible but because compression can lead you to believe you have more space than you actually do. Even when you use fixed disk, you can run out of disk space just because some uncompressible data got written within VM. Due to copy-on-write architecture, you can still get into the trouble but exposure is greatly limited.

Ideally record size should match your expected load. In case of VirtualBox that’s 512 bytes. However, tracking 512 byte records takes so much metadata that 4K records are actually both more space efficient and perform better. Depending on your exact hardware you might find that going to 8K or even higher might hit the sweet spot. Testing is the only way to know for sure but 4K is a reasonable starting point.

All other options are just plumbing - of course you want UTF-8 and no access time tracking.

Now you can run VirtualBox without complicating your main data pool.


PS: This assumes that you have disks enumerated by diskid and fully encrypted.

PPS: I usually just spin up temporary virtual machines for testing and thus I don’t care much about them long term. If you plan to kick something up long-term, do consider mirrored ZFS.