A couple months ago I was writing an article about how great Linux is and how easy and fun it was to move from a MacBook to a Librem when I accidentally deleted all my data. All I wanted to do was delete the zip files of some albums I bought. So I opened a new terminal window, ls
'd my ~/Downloads
, verified that the only files in there were okay to delete, then ran rm -rf *
. Then I thought, Huh, this is taking a bit longer than expected. Then I thought, Oh no.
The rest of the day was not fun. And the first thing I installed after the panic subsided was trash-cli
, which is my new rm
.
A little over a decade earlier I had a similar experience. I had built a literary and arts journal with some friends. We posted new content every day for over a year. Then our web host disappeared. We had no backups.
And I thought I had learned a big hard lesson about the importance of making backups but I hadn’t really. Sure, I would make them occasionally. OS X’s Time Machine made the process pretty easy. Still, sometimes the effort of (1) getting off the couch, (2) finding the USB drive, (3) plugging it in, and (4) waiting for Time Machine to start required far more effort than I wanted to invest. That’s four steps. Sometimes I would go months without making backups.
The process with Linux has been even more strenuous. You can’t just plug in the external drive and have some program automatically take over for you. Because where’s the fun in that?
Clearly what I need is an always-on and easily-accessible local file server with two external drives, thereby enabling triple-redundancy, and a command mnemonic and convenient enough that I’d actually run it more than once a month. So obviously I had to buy two external drives, a Raspberry Pi, a mini HDMI monitor, a mouse, and a mechanical keyboard. And of course I had to write the scripts. Such is the cost of convenience.
Look at this adorable little machine.
The external drives are formatted with UDF, which has a number of advantages over the VFAT file system the drives came with. Formatting them was very easy thanks to format-udf
.
The machine is right above the router, so its wifi signal is high. It’s also right next the bluetooth speaker, and Raspberry Pi’s desktop includes a bluetooth widget, so it’s easy pair the two and play the music on the drives.
Here’s a script I called copi
:
#!/usr/bin/env ruby
# target :: string
def target
"pi@10.0.0.151:~/Backups"
end
# command :: string
def command
# a = archive mode
# v = verbose
# z = compress during transfer
# R = use relative path names
"rsync -avzR"
end
# main :: [string]? -> void
def main(args)
if ((args.length == 0) ||
((args.length == 1) &&
((args[0] == '-h') ||
(args[0] == '--help'))))
puts usage
else
sync_files(args)
end
end
# sync_files :: [string] -> void
def sync_files(args)
args.each do |arg|
if (!File.exist?(arg))
puts "Warning: skipping '#{arg}'. It doesn't exist."
next
end
file = File.expand_path(arg)
if (file[-1] == '/')
file = file.chop
end
# Use `system` so the `command`'s output will print to stdout.
# Quote the `file` in case it contains spaces.
system("#{command} \"#{file}\" #{target}")
end
end
# usage :: string
def usage
<<~END
usage: copi [file|dir]...
copi copies files or directories to '#{target}' via '#{command}'.
END
end
main(ARGV)
As you can see, it’s mostly a wrapper around rsync
. It expands the paths it receives, removes trailing slashes, and copies them to the Raspberry Pi over ssh
. So, for example, after I buy some new albums and add them to my laptop’s library, I can back up the new files by running copi ~/Music
. On the Raspberry Pi, ~/Backups
is symlinked to one of the external drives. So the result of running copi
is an up-to-date copy of the laptop’s full directory tree on the external drive, e.g., /media/pi/BACKUP RED/home/rfm/Music/Julius Eastman/Femenine/01 Femenine.mp3
. This way, you could also back up data for other users, maybe your /usr/local/bin
or /usr/share/fonts
, or whatever.
There’s just one pain point: the Raspberry Pi can’t handle both drives at once. It might be a power issue. When both drives are plugged in they start to beep and power off and on in ways that are both annoying and cutely sad—like two little robots struggling and dying, power-cycling themselves to revive the other. So I just leave one plugged in. Every once in a while I’ll have to swap them out and copi
all the new stuff to the swapped-in drive. So it goes.
And there you have it. Piece of cake. May you never experience the sadness and loss one careless command (or one careless web host) can cause. But if you do, may you also be prepared.