Hello and welcome to Zephyr On Call. My name is Andrew Quinn.
Pardon the spartan look, as I am redesigning my blog’s CSS from scratch, using my minimum-viable-hugo repository on GitHub, as well as figuring out a blogging strategy that works for me. I hope you take something from here regardless.
Software engineers are, if not unique, then darn near
unique in the ease with which we can create tools to improve
our own professional lives; this however can come at a steep
cost over time for people who constantly flit back and
forth between different tools without investing the time to
learn their own kit in depth. As someone with a healthy
respect for the tacit knowledge of people better than
me, I
think a great 80/20 heuristic is “Learn the oldies
first”: venerable Unix tools like cat
, ls
, cd
, grep
,
and cut
. (sed
and awk
, too, if you have the good
fortune of landing yourself in an actual modern sysadmin
role.)
But there are tools whose return on investment is so
immediate, and whose value prop is so unique, that the 80/20
heuristic breaks down entirely for them. fzf
is one of
them. And it makes me sad to see so many people download it,
run it as-is at the command line, and then just shake their
heads and walk away, saying “I don’t get it”.
Here I want to change that. Pretend you live on a
more-or-less standard Ubuntu box. You’ve just installed
fzf
– now what?
Ctrl+R
…In most terminals, Linux and Windows alike, Ctrl+R
gives
you backwards search for your commands. The reason you,
like me, may not have heard about this until you had already
been hacking away for ten flippin' years at the shell is
because the base version kind of sucks for 2 reasons:
fzf
is a bit of a weird program because installing it
actually overwrites a whole bunch of keyboard shortcuts, in
the interest of making them better. Normally I would hate
this. But…
… This is a considerable improvement on the baseline.
Alt+C
Let’s say you boot into an empty terminal. You’re trying to
quickly find your nascent SaaS side hustle repos and cd
to
it - but it’s been weeks since you’ve been there, your
actual full time job has been unusually fun and engaging…
How do you find it?
Answer: With fzf
. fzf
rewrites Alt+C
into a souped-up
fuzzy-cd
shortcut that lets you hop around very quickly
when all you remember is the vague name of the directory in
question.
fzf
commandOkay, we’ve got the shortcuts out of the way. Honestly these
two guys alone provide the majority of the value I get out
of fzf
- but let’s look at what the command, by itself,
does.
It fuzzy-finds file locations! Relative ones, at least, to your own directory. This… isn’t that useful, by itself.
vi $(fzf)
, and…!!!And you get a fuzzy-open-in-editor experience!
(There’s nothing special about vi
in this regard, btw. You
can call it with emacs
,
nano
,
code
, whatever floats your boat!)
vi $(find . '/' | fzf)
: For finding random config filesThe other day I was trying to hack together baby’s first
live-reload with a Firefox extension, entr
, and nginx
.
And I found myself asking: Where the heck is nginx.conf
?
I reviewed my options. I could
trees
and grep
s, orfind
. ‘/’ to fzf
and start searching.I like this clip a lot because it shows some of the subtle
tradeoffs of using fzf
, as well as one of the more
advanced searching features - searching for conf$
will
filter out any line that doesn’t end in conf
. Notice
that fzf
temporarily wigs out when find
hits a whole lot
of “Permission denied” errors - but then recovers itself a
few seconds later.
Are those extra few seconds worth the tradeoff for being able to find config files in such a braindead manner? It is for me.
rg
: Fast, recursive-by-default grep
Everything I say below can be done with grep
as well,
but the recursive-by-default nature of rg
(also known as
ripgrep
) is where the tool really comes into its own. I
highly recommend you download it and use it for the
following examples as well. But if you’re toolshy, don’t
worry!
rg . | fzf
: Fuzzy search every line in every filerg . | fzf | cut -d ":" -f 1
: Fuzzy search every line, in every file, and return the file locationvim $(rg . | fzf | cut -d ":" -f 1)
: Fuzzy search every line, in every file, and open that fileHello from sunny Kalajoki! My wife and I are in this little agrarian town because she is retaking a few of her Finnish high school exams, which requires her to go back to where she grew up to do so. She’s retaking her exams in English and math, after a ~6 month Anki-based training regimen we put her through. I think she’ll do extremely well, and I’m immensely proud of her.
As for moi, I have the good fortune of a very understanding boss, who allowed me to work remotely for this week. (I already get 3/5 days remote, but one of the exams was scheduled on one of our in-office days - one of the many perks of working in tech.) And so now I’m looking out the window of our Airbnb, at the clear blue sky and the yellowing sunlight and the green spruce trees and the blood red branches of a bush I remember walking past so many times when we used to live here, and thinking about challenges.
The world offers no shortage of challenges to all of us. The variety of what we’re allowed to take on is bewildering, beyond what nature was capable of providing for a very long time. When you look at the natural ecosystem what you see is an inherently unstable, but learning system - one which slowly converges in on hard dependence on the few things which stay constant. Old growth forests come to depend on the few trees which have lived for thousands of years there, content to assume they will live for thousands more; this stability in turn depends upon the sun waking up and circumambulating our globe once a day, upon the soil staying clean and detoxified. All the critters of the forest, with their exponentially more ephemeral lives, learn to accept these as constants – or as good as constant for ones with such short lives.
Humans turn this into an anomaly, by virtue of our long lives and will to power. Our intellects have allowed us to slowly but surely reconfigure everything in our environment to the point where we can truly go anywhere, and take anything on, and it all feels meaningless to the great mass of people who think this means it is equally okay to take nothing on. How strange!
After taking on the challenge of getting an elite education in the West, I decided to take on a quite different challenge - that of relocating myself to Northern Europe, learning to brave the cold, learning to speak the strange Finnish language. Sometimes I wonder to myself why I took all this on in the first place - I could surely make more money elsewhere, right?
But these challenges are the ones I chose. At some level, that has to trade off against financial concerns.
I know that GPT-4 is all the rage right now, but I decided to spend some time this weekend on something a little less sexy: learning to work with Microsoft’s original attempt at a Java killer, C#. Some quick projects:
dc
, the reverse Polish notation
calculator. This
one’s a fun one because it’s very easy, but finally gets
you to use an honest-to-God data structure.“Really, C#? Why? You already know like, Python and Haskell and a million random command-line tools. What’s the appeal?” Money, baby. Outside of the Valley everyone and their uncle is still using either Java or C#, and I had enough Java in AP Computer Science twelve years ago. Besides, working my way through Haskell Programming from First Principles last year while I was unemployed was something I did for me, not for the market; I’m a firm believer in listening to the market when it’s giving you hints.
I’m also a firm believer in the wisdom of the traveling salesman. Your first programming language might be an arbitrary choice, but your second one almost certainly won’t be, nor will the first database you work with, the first third-party library import, etc. How do you choose what to learn or do next? Turns out you can get pretty far just learning the most obvious, popular thing.
In my case, the “most obvious, popular thing” is C#. I already know PowerShell better than I have any reason to, and C# ties in to PowerShell beautifully. The backend developers at my current job all use C# - and a lot of them are veterans, having progressed to C# from the halcyon days of Finnish ’90s and ’00s C++. These guys know their stuff! And, finally, I’ve already been immersed in the Microsoft and Azure twin ecosystem for months now – SQL Server is in my bloodstream right now, as are all the most common assets created on that cloud platform. C# works with all of those technologies impressively well.
Here’s what my setup looks like so far:
It’s a quiet Saturday morning here in lovely Tampere, and I’m watching the update progress on an ancient bit of fintech from Windows COM programming days. It’s as simple as it gets, operationally speaking. There’s a handful of Windows server VMs; a few SQL Server machines, a few more for the business logic, and a few for the frontend. An SFTP server for flavor - don’t sleep on SFTP just because REST APIs are all the rage nowadays.
‘Bag of VMs’ of course means ‘mandatory OS patching’, which is what I’m up to
today. One of Microsoft’s many sins is not including a command line OS patcher,
so schlubs like me have to resort to a third party PowerShell package called
PSWindowsUpdate
to automate the job.
Getting this baddie on these Internet-shy machines Internet is a story for another day. Once I did get it on, I got to use a tool which is much better than I was expecting it to be: Octopus Deploy, a system orignally designed for CI/CD stuff but which happens to serve admirably as a remote script executor in a pinch. Since I inherited this architecture with Octopus already in place anyway, I just stuck with this instead of installing something sane like Ansible.
The setup is simple:
oct-vm
.Write-Debug
s you included get
streamed to the front-end as well, letting you watch in real time as your
scripts whir elsewhere.There’s a lot of flexibility in the Octopus web frontend. And what I’m a
particular fan of is just how discoverable all of this flexibility feels –
that’s something you don’t get out of the box with ordinary CLIs, even if their
composability is exactly what I’d reach for in past a certain bar of
complexity. (I have a coworker who is a big fan of this new wave of
halfway-house TUIs that is mostly getting baked up by the Rust community, which
shows some promise towards bringing GUI-level composability direct to the
terminal. I’m not fully sold yet - but I do have to admit fzf
’s minimalistic
TUI has fast become a mainstay in my workflows. So maybe there’s a there there,
I don’t know.)
I later realized PSWindowsUpdate
was probably hanging due to all of the
logged-in but disconnected users. So I added a step using quser
, msg
, and
some awk
-flavored splitting to kick everyone off the server with a short 5
minute leadup. This SO answer contained
a script which I used almost unaltered, save for a
above the logoff
.