backups wisdom

Monitor Your Backups!

In which I find out things have gone awry

Hey you! Yes, you! The one reading this. You have backups, right? Go check that they i) actually exist ii) are backing up at the right frequency iii) work. This is important, I’ll wait.

borg: Great for Backing Up

I’ve been using borg for backups for a couple of years now. It’s great- it does deduplication (saving tons of space!), only backs up what has changed (efficient! incremental!), and is somehow fun to use while doing so.

I wrote a script to take the backups, run as a systemd service each hour. All was well- it did error detection and emailed me when a backup failed.

But I had the occasion to check on the backups a couple days ago, and the latest one was from January. My first thought was disk space, but there was enough (albeit getting close to the limit). So I then checked the systemd output:

$ systemctl status periodic-backup
? periodic-backup.service - Take a periodic backup of directories
     Loaded: loaded (/usr/lib/systemd/system/periodic-backup.service; enabled; vendor preset: disabled)
     Active: inactive (dead) since Wed 2020-02-12 12:03:06 GMT; 45min ago
TriggeredBy: ? periodic-backup.timer
   Main PID: 1168530 (code=exited, status=0/SUCCESS)

Feb 12 12:03:02 zeus systemd[1]: Started Take a periodic backup of directories.
Feb 12 12:03:06 zeus systemd[1]: periodic-backup.service: Succeeded.

So the job was running and… succeeding, but not backing up?

Next step in diagnosis is to run the script manually, and make sure it still works. The script didn’t error, but it took a long time to complete- longer than a straightforward case of “large increment to backup since January”.

So I broke it down even further, and ran the borg command as written in the script. I got a prompt:

Warning: The repository at location ssh://bertieb@pandora/home/bertieb/backups/borg/zeus was previously located at ssh://pandora/~/backups/borg/zeus

Aha! It was waiting on input to proceed. One form is how the script access the repo, the other is how it is accessed from the command line. It’s a bit strange as the repo clearly didn’t move, and I’m not sure why it started treating the two differently.

Fortunately, borg has an environment var for just such an occasion: BORG_RELOCATED_REPO_ACCESS_IS_OK=yes


I asked in #borgbackup on Freenode about the issue, and folks said they had used a few things for independently monitoring backups:

I am indebted to Armageddon for mentioning the last one. While full-on monitoring with Prometheus looks interesting (especially in conjunction with grafana), it’s way overkill for my needs. Ditto Zabbix.

Healthchecks is a relatively simple tool which implements the concept, “we expect a ping/health-check at <such-and-such> a frequency; if we don’t get it then alert”.

Armageddon/Lazkani’s blog has a worked example of setting up Healthchecks to work with borgmatic (a tool to simplify borg backups). The official borgmatic ‘getting started’ guide is pretty good too.

The env vars in the Healthchecks docker image are used on creation; after they can be changed in

I set up Healthchecks using the linuxserver Docker imagebig note: the env vars listed there are used on creation, after that they can be changed in the data volume / directory under; that one held me up for a bit when i was trying to sort out email integration — and have added both my pre-existing scripts, and some new borgmatic backups.

Looking good!

If you use the helpful ‘crontab’ format for the period, make sure to match the timezone, or you’ll get period emails saying the backup has failed. Ask me how I know…


The Sam Vimes Theory of Economic Injustice

The reason that the rich were so rich, Vimes reasoned, was because they managed to spend less money.

Take boots, for example. He earned thirty-eight dollars a month plus allowances. A really good pair of leather boots cost fifty dollars. But an affordable pair of boots, which were sort of OK for a season or two and then leaked like hell when the cardboard gave out, cost about ten dollars. Those were the kind of boots Vimes always bought, and wore until the soles were so thin that he could tell where he was in Ankh-Morpork on a foggy night by the feel of the cobbles.

But the thing was that good boots lasted for years and years. A man who could afford fifty dollars had a pair of boots that’d still be keeping his feet dry in ten years’ time, while the poor man who could only afford cheap boots would have spent a hundred dollars on boots in the same time and would still have wet feet.

This was the Captain Samuel Vimes ‘Boots’ theory of socioeconomic unfairness.

— Terry Pratchett, Men at Arms

(brought to mind by recent musings on cheap hardware)

python wisdom

Project Euler Problem 25 Pitfalls

Project Euler problem 25 is reasonably straighforward. It asks you to find the first term in the Fibonacci sequence with more than 1000 digits. In ones like these, not reading the question properly is more likely to be your downfall than anything else. So:

  • Give the number of the first term which has 1000 digits, not the 1000-digit number itself
  • Make sure your Fibonacci number generator gives you the sequence correctly: ie F(1)=1 and F(2)=1. If you have F(1)=1 and F(2)=2, you’ll be off by one!
  • Lastly, and this only really applies to my own thickness… If the comment for your Fibonacci number generator says “returns nth Fibonacci number”, make sure it returns the nth Fibonacci number and not a Fibonacci number less than n.
  • If you’re getting a number greater than 5000 you’re off, recheck. Good luck!

all posts wisdom

[Solved] Could not create java implementation loader / No JRE Found

After installing LibreOffice Portable (from here), I tried to install the Google Docs Sync extension, ooo2gd. However, installation failed with the error message “Could not create java implementation loader”. There are many posts about this, most of which suggest either

  1. disabling, then re-enabling “Use a Java runtime environment” on the Tools > Options > LibreOffice > Java menu page
  2. Deleting a user profile

That didn’t work in my case because that menu page had no JRE listed, in spite of me installing the latest JRE from (at time of writing JRE 7). What sorted it was installing the last version, which is confusingly also called the latest, recommended version (Version 6 Update 27 at time of writing). I got it from here: After installing it appeared in the JRE list on the Java options page in LibreOffice and oo2gd installed correctly.


Unzip Multiple Archives (Optionally With Password Protection) Using PowerShell on Windows

Short version: You need 7-zip to go with it if you want to do the password protection bit

Most of the shell posts here are to do with Linux, and particularly bash, but today I’d like to share a useful Powershell nugget. By the way, to get a powershell, open up a command prompt (Win + R -> cmd [enter]) and type powershell. Just like that.

Now, I wanted to unzip a big folder of zip archives, protected with a simple password. Well, turns out that is relatively easy to do with PowerShell and 7-zip, both of which I had. BWAIN*dump got me started, and I changed it to work with password protection and added a couple refinements. The code:

$shell=new-object -com shell.application




$ZipFiles = get-childitem *2010*.zip | where {$_.length -gt 22} | sort-object -property LastWriteTime -descending

$ZipFiles.count | out-default

foreach ($ZipFile in $ZipFiles)

C:\7z.exe e -y -oC:\directory -psomepass $ZipFile.Name


  • The first four lines are basic setup, saying “we’re going to work in the current directory”
  • $ZipFiles = get-childitem *2010*.zip – get all zip files that have “2010” in the name. This was for my own purposes, you could instead use *.zip for all zip files.
  • | where {$_.length -gt 22} – a pipe to select all files with a size of 22 bytes or more, as I didn’t want any empty files to be included
  • | sort-object -property LastWriteTime -descending – a pipe to sort by date modified, descending. Handy if you are only doing a subset of files, eg to test.
  • foreach ($ZipFile in $ZipFiles) – loop through the files
  • C:\7z.exe e -y -oC:\directory -psomepass $ZipFile.Name – the important bit, using 7-zip to extract the password-ed files. THis does assume they have all the same password, incidentally. If you have 7-zip in the same directory as the files (as I did), you can write:
    \7z e -y -oC:\directory -psomepass $ZipFile.Name, but you need to escape the 7 of “7z” for some reason. Note there are no spaces between -o and the output directory, nor -p and the password. -y just means answer “yes” to all questions, making it non-interactive. This will overwrite stuff that has the same name, I’m happy with that but you might not be.

Anyway, that code should extract files from zip archives with a password to a specified directory. Modify it to your purposes as I did!

counter strike source pc games wisdom

Display Hit Damage Plugin For Counter-Strike Source

I’ve been getting a Counter-Strike Source server up and running for giggles, and one thing I’ve been enjoying is when damage on hitting someone is shown. Long story short, Google comes up short on searching for this (there’s a couple of commands in the old AMX Mod X apparently, for CS 1.6). However, exvel has written a lovely plugin to display damage that actually works in all Source games (at least in DODS, TF2, CSS and L4D). You can find it on the AliiedMods site.

all posts cool linux software wisdom

Extract A Single Image From A Video Using FFMPEG

Update: Still using this 8 years later, but in the form of a quick script, which is useful if you are doing it more than once

Dead handy, this:

ffmpeg -ss 0.5 -i inputfile.mp4 -t 1 -s 480x300 -f image2 imagefile.jpg

The various options:

  • -vframes 1: limit to 1 frame extracted
  • -ss 0.5: point of movie to extract from (ie seek to 0.5 seconds; you can also use HH:MM:SS.ZZZZ sexagesimal format)
  • -s 480x300: frame size of image to output (image resized to fit dimensions)
  • -f image2: forces format

I use this to generate preview stills for jwplayer to use. Dead handy!

Edit: Thanks to DieBagger who pointed out it is much faster to place the seek argument before the input file, and Matthias his point about the seek time.

life wisdom

Driving Test Stuff

My practical test is in a week. Eep, yikes, etc etc. I had my penultimate lesson (counting the one right before the Real Thingâ„¢) today, and managed to get a couple of silly fails out of my system.

My point point is that the website The Driving Test could be quite useful if you’re in the position where you have a test but aren’t exactly sure of the procedure. It may not look like much, but it has some useful information. It talks you through what will happen in a test – ie what kinds of things the examiner will say – which is very useful in allaying fear of the unknown. The author is a former DSA examiner, so he should know his stuff. Check it out.

all posts cool linux software wisdom

Installing Debian on QEMU

Since I decommissioned my home server in favour of an NSLU2 (a NAS), I’ve found myself without a Linux machine to much about with or develop on while on the go (well, whenever I can’t use my laptop). So instead I’ll be using a virtual machine by running QEMU from my USB drive. Since my old server ran Debian, and since I haven’t checked it out in a while other than using it’s offspring Ubuntu.

Note: I would recommend getting this set up running on a folder on your hard drive, then copying it to your USB drive if you intend to do that. It will probably be faster, and it will save you trouble if your disk image isn’t large enough.

To get a QEMU binary for Windows, you can download from here, although this is no longer outdated and uses the 0.9.0 release. Unzip it wherever.

Open up a command prompt. cd to the QEMU directory. Create two disk images by running:

qemu-img create -f qcow2 debian.img 1024M .

qemu-img create -f qcow2 home.img 1024M .

This creates two 1024Mb sized qcow images for you to work with – one for your system and applications, and one for your home directory(ies). Obviously you can change the name and size to suit. My USB drive is 4Gb – if you have something smaller like 2Gb, use 768M for debian.img and 512M for home.img. If you have a 1Gb drive, you could try smaller sizes, but you’d probably have more luck trying something like DSL (Damn Small Linux) or puppylinux. I originally tried this with a cumulative 512M for the root and swap partitions, and it wasn’t large enough.

Grab a Debian CD image. I would recommend one of the netinst images. I’m using the Lenny Beta 2 image (here, or the .torrent), but you can use a stable image, or one of the weekly / daily snapshots. Put the image in the same directory as QEMU.

Create a file debian.bat, with the command:

qemu.exe -net user,vlan=1 -net nic,model=rtl8139,vlan=1 -L . -m 128 -hda debian.img -hdb home.img -cdrom debian-LennyBeta2-i386-netinst.iso -boot d -soundhw all -localtime

You can change the -m option for more or less virtual RAM, you can leave out the model=rtl8139 to use the default ne2k driver (I just like Realteks, even virtual ones ;-)), and obviously change the -cdrom option if you use a different image. You can also use Kqemu, but I’m not going to go into that.

Additionally, you can use the command -M isapc (ISA network card), but for that you will have to remove the model=rtl8139; and before using the installer, press [TAB] and add noacpi nolacpi to the installer startup options, otherwise QEMU will crash.

Debian can then be installed as normal. I didn’t install anything that depends on X as I don’t want a graphical system, thought QEMU should handle it fine if you do. I used the partition manager to create a swap partition of about 128 megs. Mount your second ‘hard drive’ (home.img) under “/home”. if you don’t do this now you can do it later by editing /etc/fstab.

(My second disk image / hard drive is mounted as:

/dev/hdb1 	 /home   	 ext3   	 errors=remount-ro   	 0   	 1


Depending on the CPU of your host machine, whether or not you are using Kqemu, and the speed of your internet connection it will take anywhere from 10 minutes to two hours to install.

Once installed you can apt-get install build-essential, or apt-get install nethack, or apt-get install python, or whatever floats your boat. Or, if you’re like me, you can faff about trying to enlarge your partitions because they aren’t big enough.

all posts pc games valve games wisdom

TF2 – ‘Lost connection to server’ Solved

Even though I have exams coming up, I still manage to squeeze in the odd round or ten of Team Fortress 2. I blame Valve for releasing the medic achievements recently.

(7 to go! One of them is ‘Family Practice’, so I need some more Steam friends to deploy an ubercharge on, hint hint. Also, for all the spies out there: FYI I am a medic – please call for me sometime eh?)

Anyway, I had been playing for a while, but had developed a problem connecting to servers. The problem was that most of the time I would get into the game, take a few steps, then it would freeze. A second later I would get the red “Connection to server lost. Disconnect in 29…28… seconds”. Sometimes I would only get to “retrieving server info” or “sending client data”, and sometimes I could play for as long as 30 or more seconds before I got ghostbusted (yes, netrek jargon). I’m sure I even got a kill after being disconnected.

Trying to rejoin would give me a “This Steam ID is in use on the server”, while my friends saw many “BertieB(1) has connected”. And I saw a lot of “Disconnected from server. Reason:” … connection to server lost… this steam ID is already in use…

This is not unique problem. Fortunately the fix is fairly straightforward.

You need to open some ports on your router:

TCP 27030 – 27039
UDP 1200
UDP 27000 – 27015

For people with a BeBox (a Speedtouh 780 WL I think, so it should work for similar Speedtouches, like those with BT internet) you can simply log into the router (at, go to Toolbox -> Game & Application Sharing -> Assign a game or application to a local network device -> Half-life 2. Easy!

This may not solve the problem for everyone, but it did for me and others. Good luck!

Update: Thanks to Jeroen, who pointed out the typo that has been there for about 3 years.