Jan 4, 2016 - Swapping display outputs with i3

In the (unofficial) #i3 IRC channel on freenode, someone recently asked if i3 has a command to switch between display outputs. Somewhat suprisingly, i3-msg doesn’t have such a command, but I realized that one could be written pretty easily by getting the list of workspaces and finding which one is visible but not focused, then switch to that workspace. Here’s the command I came up with, shown as a full binding from ~/.i3/config:

bindsym $mod+Next exec i3-msg workspace $(i3-msg -t get_workspaces|jq '.[] | select(.visible == 'true') | select(.focused == 'false') | .name')

You’ll need to have ‘jq’ installed.

The logic for this is pretty simple:

  • Get a list of all workspaces
  • Iterate through the list
  • Find workspaces that are visible
  • Find workspaces that are not focused
  • Print the workspace names

With two displays, you can only have two visible workspaces, and only one of those will be focused. I simply find a visible workspace that is not focused.

This won’t work as-is if you have more than 2 monitors, but you could easily have a different binding for each display, filtering for a specific “output” in place of the filter that looks for the non-focused workspace.

With a little more work, you could rotate through displays by parsing things out with python or awk (or whatever) and enumerating all the displays to determine which should be “next” or “prior”.

But, if you only have two displays, like I do, the above binding will let you easily jump back and forth between outputs.

Nov 3, 2015 - autofs with NTFS

I ran into an interesting issue recently when I wanted to set up autofs with an NTFS filesystem on an external USB drive (this drive, unfortunately, could not be btrfs like everything else).

The version of autofs shipped with Debian Jessie (and many other varieties of Linux, including Ubuntu), has a bug where it passes an invalid mount option (-s) to ntfs-3g, and as a result NTFS filesystems can’t be mounted. This bug has been fixed in a newer version of autofs, but instead of building it from source (it’s not available in jessie-backports), I just did a silly hack instead.

The relevant portion of my autofs map looks like:

somedrive      -fstype=ntfs,rw :/dev/disk/by-uuid/EA59283A9207245F1

Without enabling debugging, you don’t get much useful output:

$ ls /media/somedrive
ls: cannot access /media/somedrive: No such file or directory

However, after enabling automount debugging (I just hacked up the init script), the problem becomes clear:

do_mount: /dev/disk/by-uuid/EA59283A9207245F1 /media/somedrive type ntfs options rw using module generic
mount_mount: mount(generic): calling mkdir_path /media/somedrive
mount_mount: mount(generic): calling mount -t ntfs -s -o rw /dev/disk/by-uuid/EA59283A9207245F1 /media/somedrive
spawn_mount: mtab link detected, passing -n to mount
>> ntfs-3g: Unknown option '-s'.
>> ntfs-3g 2014.2.15AR.2 integrated FUSE 28 - Third Generation NTFS Driver
>> #011#011Configuration type 7, XATTRS are on, POSIX ACLS are on
>> Copyright (C) 2005-2007 Yura Pakhuchiy
>> Copyright (C) 2006-2009 Szabolcs Szakacsits
>> Copyright (C) 2007-2014 Jean-Pierre Andre
>> Copyright (C) 2009 Erik Larsson
>> Usage:    ntfs-3g [-o option[,...]] <device|image_file> <mount_point>
>> Options:  ro (read-only mount), windows_names, uid=, gid=,
>>           umask=, fmask=, dmask=, streams_interface=.
>>           Please see the details in the manual (type: man ntfs-3g).
>> Example: ntfs-3g /dev/sda1 /mnt/windows
>> News, support and information:  http://tuxera.com
mount(generic): failed to mount /dev/disk/by-uuid/EA59283A9207245F1 (type ntfs) on /media/somedrive

My hack to fix this is pretty simple: I created a wrapper around the real ntfs-3g binary that strips the -s option out of the command line. Very brute force.

I dropped my script into /bin/ntfs-3g_wrapper, renamed /bin/ntfs-3g to /bin/ntfs-3g_real, and made a symbolic link from /bin/ntfs-3g to the wrapper.

Here’s the script, placed in /bin/ntfs-3g_wrapper:


OPTS=$(echo [email protected] | sed "s/ -s / /")

exec /bin/ntfs-3g_real $OPTS

And now let’s move things around and create the symlink:

$ sudo mv /bin/ntfs-3g /bin/ntfs-3g_real
$ sudo ln -s /bin/ntfs-3g_wrapper /bin/ntfs-3g

BE CAREFUL IF YOU DECIDE TO TO DO THIS - I take no responsibility if you break your system. And remember: any update to the ntfs-3g package will require at a minimum moving the binary again and recreating the symlink, or maybe even more work depending…

This is, in general, the wrong way to solve these sorts of problems - you have to remember what you did for when it breaks again, and you never know what other issues it may cause.

In my case this was a quick and dirty solution, and if a newer version of autofs ends up in jessie-backports, I can easily undo it. Hopefully this helps others, as this is apparently a pretty common problem with autofs.

Jul 11, 2015 - Using TPM for better random entropy

Did you know your system might have a TPM chip that can act as a hardware random number generator (RNG)? Me neither, until recently.

If you’ve ever been generating a GPG, or other cryptographic key, and had to wait for the kernel to fill it’s random entropy pool, then you’ll find this really useful. Doubly-so if you’ve ever been generating keys on a headless server and been amused at the message suggesting you move the mouse or type on the keyboard to generate some entropy. Uhh… Right. This can turn an operation that should take a few seconds into one that takes several minutes or more.

TPM, or Trusted Platform Module is a standard interface that does a bunch of different things - none of which we really care about for Linux except the RNG. TPM is common on corporate laptops and desktops, but even some consumer grade hardware has a TPM chip built-in or one can be added. I have a Linux server built on an MSI motherboard and found it supports a TPM daughterboard which costs under $20.

How do I know if my system supports TPM? It’s pretty simple to check. Do a “dmesg | grep -i tpm” (after a recent boot so boot-time output is still available). Then, based on the output:

  1. Disabled or unavailable: This is good news. It means the kernel found a TPM module, but it’s disabled in your BIOS. How to enable it is entirely BIOS and system dependent, but you should be able to figure it out. Only enable the base TPM support, nothing else.

  2. No output: This probably means your hardware doesn’t have TPM support. You can try weeding through all the BIOS options in hopes that it’s just disabled such that the kernel couldn’t detect it, but likely this is not good news. Double check that the tpm kernel module is loaded with lsmod. If not, try probing the kernel modules, as described below.

  3. Active: If the output shows a device-id or other output suggesting that a TPM device was detected, then you are golden. Here’s an example output from a Lenovo Thinkstation: “tpm_tis 00:05: 1.2 TPM (device-id 0x1A, rev-id 16)”.

You’ll need to have kernel modules for tpm and tpm_rng loaded. On all the systems I’ve had with TPM support, I found tpm already loaded, but had to add tpm_rng to /etc/modules so it loads at boot. To manually probe these, do “sudo modprobe tpm” and “sudo modprobe tpm_rng”, and use “lsmod | grep tpm” to see what modules are loaded.

Ok, so now you’ve got a working hardware RNG, but it’s not doing anything by default. We need to use rng-tools to feed this source into the kernel entropy pool. On Debian, all I had to do was “sudo aptitude install rng-tools” with no further configuration.

To check that it’s working:

  • Look for rng-tools/rngd messages in your logs.
  • Check for loaded kernel modules, as discussed above.
  • Check for /dev/hwrng.
  • Check the size of the entropy pool via “cat /proc/sys/kernel/random/entropy_avail” - if it’s working, this value will always be above around 2000 or so.

If I don’t have a TPM device can I still use rng-tools to feed entropy to the kernel? rng-tools supports additional hardware sources, and you can certainly give them a try - I have yet to have a system with the needed CPU or hardware support aside from TPM, but you just might.

Lastly, don’t be tempted to feed rng-tools using /dev/urandom. You’ll find a lot of tutorials out on the net suggesting setting this up so you don’t have to wait for entropy. This is a bad idea - /dev/urandom will never block, but it’s source of entropy is a weak pseudo-random number generator. If you are generating encryption keys and want secure ones, it’s better to wait for the entropy pool to fill on it’s own than use a weak source!

Mar 12, 2015 - Stop using telnet to test network connectivity

It’s common to use Telnet for testing network connectivity to arbitrary systems and ports. People use this method because it’s simple and it works, but this is 2015 and it’s time to stop!

Using Telnet for this is like renting a U-Haul to give a note to your neighbor. Instead, try netcat (to replace Telnet anyway, not to deliver notes to your neighbor :-) ).

Netcat (nc) has been around since 2007 and is a much better tool than Telnet - in fact it was written exactly for this sort of thing, and with the right options will immediately exit, so unlike telnet you don’t have to type ^]^d to exit Telnet every time you run it.


$ nc -vzw 5 google.com 443
DNS fwd/rev mismatch: google.com != lax02s22-in-f14.1e100.net
google.com [] 443 (https) open


Woah! That’s awesome, no? Not only did it confirm that we can get to google (the port is open), but it provided some useful DNS information as well as the protocol name from /etc/services. And, note that it exited straight back to the command line.

Let’s look at the options passed above:

  • -v : Verbose (without this, nc doesn’t output much).
  • -z : Zero-I/O mode (exit as soon as the connection is established).
  • -w 5 : Wait 5 seconds for a connection (default waits much longer).

Now let’s try an example where we cannot establish a connection, and see what that looks like:

$ nc -vzw 5 duckduckgo.com 123
DNS fwd/rev mismatch: duckduckgo.com != ec2-50-18-192-251.us-west-1.compute.amazonaws.com
DNS fwd/rev mismatch: duckduckgo.com != ec2-54-215-176-19.us-west-1.compute.amazonaws.com
DNS fwd/rev mismatch: duckduckgo.com != ec2-50-18-192-250.us-west-1.compute.amazonaws.com
duckduckgo.com [] 123 (ntp) : Connection timed out


That’s nice, right? We again get some useful DNS information and then verification that we couldn’t connect to that port.

You can use netcat for interactive testing too, by eliminating the -z option. Here’s the rough equivalent of doing a curl request. I typed in the HTTP request “GET / HTTP/1.0” and the rest is the response from the server:

$ nc google.com 80
GET / HTTP/1.0
HTTP/1.0 200 OK
Date: Thu, 12 Mar 2015 18:32:13 GMT
Expires: -1
Cache-Control: private, max-age=0
Content-Type: text/html; charset=ISO-8859-1

The Wikipedia entry for netcat provides some great additional examples, and quite a bit more information than the manpage.

So the next time your muscle memory starts to type “telnet”, quickly remind yourself to use “nc” instead!

Feb 8, 2015 - dhclient On wpa_supplicant Associate

As mentioned here, I’m not a fan of NetworkManager or wicd, and prefer using wpa_supplicant directly in /etc/network/interfaces via wpa-roam. A downside to this approach is dhclient isn’t smart enough to keep trying to acquire an IP address when wifi connections are lost and re-established, or when connecting to a different access point.

Fixing this in a reliable way isn’t obvious, but it’s not too hard either. wpa_cli has a -a option where it will run as a daemon and execute an arbitrary script each time the system connects or disconnects from a wifi network. We can hook into this, killing off dhclient on disconnect, and starting it up again on connect.

Here’s my hook script, which I keep in /etc/wpa_supplicant/dhcpaction.sh:



if [ "$CMD" = "CONNECTED" ]; then
    /sbin/dhclient -v -pf /run/dhclient.${IFNAME}.pid -lf /var/lib/dhcp/dhclient.${IFNAME}.leases ${IFNAME}

if [ "$CMD" = "DISCONNECTED" ]; then
    /bin/kill $(/bin/cat /run/dhclient.${IFNAME}.pid)

In my /etc/rc.local file I have the following, which starts wpa_cli in it’s special action script mode on boot (note /var/log/local must exist and have appropriate permissions):

/sbin/wpa_cli -a /etc/wpa_supplicant/dhcpaction.sh >/var/log/local/wpa_action.log 2>&1 &

That’s all there is to having wpa_supplicant reliably keep a wifi interface up!