<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title type="text">Blog entries :: mwop.net</title>
  <updated>2026-05-04T08:35:08-05:00</updated>
  <generator uri="https://getlaminas.org" version="2">Laminas_Feed_Writer</generator>
  <link rel="alternate" type="text/html" href="https://mwop.net/blog/"/>
  <link rel="self" type="application/atom+xml" href="https://mwop.net/blog/atom.xml"/>
  <id>https://mwop.net/blog/</id>
  <entry xmlns:xhtml="http://www.w3.org/1999/xhtml">
    <title type="html"><![CDATA[Determining if a reboot is required on Linux]]></title>
    <published>2026-05-04T08:35:08-05:00</published>
    <updated>2026-05-04T08:35:08-05:00</updated>
    <link rel="alternate" type="text/html" href="https://mwop.net/blog/2026-05-04-reboot-required.html"/>
    <id>https://mwop.net/blog/2026-05-04-reboot-required.html</id>
    <author>
      <name>Matthew Weier O'Phinney</name>
      <email>contact@mwop.net</email>
      <uri>https://mwop.net</uri>
    </author>
    <content xmlns:xhtml="http://www.w3.org/1999/xhtml" type="xhtml">
      <xhtml:div xmlns:xhtml="http://www.w3.org/1999/xhtml"><xhtml:p>I've been using the construct <xhtml:code>sudo run-parts
/etc/update-motd.d/</xhtml:code> to determine if recent system updates
required a reboot.</xhtml:p>
<xhtml:p>Today I learned I can simply check for the existence of the file
<xhtml:code>/var/run/reboot-required</xhtml:code>.</xhtml:p>
<xhtml:div class="h-entry"><xhtml:img class="u-photo photo" width="50" src="https://avatars0.githubusercontent.com/u/25943?v=3&amp;u=79dd2ea1d4d8855944715d09ee4c86215027fa80&amp;s=140" alt="matthew"/> <xhtml:a class="u-url u-uid p-name" href="https://mwop.net/blog/2026-05-04-reboot-required.html">Determining
if a reboot is required on Linux</xhtml:a> was originally published
<xhtml:time class="dt-published" datetime="2026-05-04T08:35:08-05:00">4
May 2026</xhtml:time> on <xhtml:a href="https://mwop.net">https://mwop.net</xhtml:a>
by <xhtml:a rel="author" class="p-author" href="https://mwop.net">Matthew
Weier O'Phinney</xhtml:a>.</xhtml:div>
</xhtml:div>
    </content>
  </entry>
  <entry xmlns:xhtml="http://www.w3.org/1999/xhtml">
    <title type="html"><![CDATA[PHP DateTimeImmutable::createFromFormat Reset Character]]></title>
    <published>2026-04-16T10:30:00-05:00</published>
    <updated>2026-04-16T10:30:00-05:00</updated>
    <link rel="alternate" type="text/html" href="https://mwop.net/blog/2026-04-16-php-create-from-format-reset.html"/>
    <id>https://mwop.net/blog/2026-04-16-php-create-from-format-reset.html</id>
    <author>
      <name>Matthew Weier O'Phinney</name>
      <email>contact@mwop.net</email>
      <uri>https://mwop.net</uri>
    </author>
    <content xmlns:xhtml="http://www.w3.org/1999/xhtml" type="xhtml">
      <xhtml:div xmlns:xhtml="http://www.w3.org/1999/xhtml"><xhtml:p>I was recently building something that was taking date input
from an HTML form field, and casting it to a PHP
<xhtml:code>DateTimeImmutable</xhtml:code>. I was then comparing that to
another date, and got thrown off during testing when I compared the
resulting instance to <xhtml:code>new DateTimeImmutable('today')</xhtml:code>;
the instances were not considered equal.</xhtml:p>
<xhtml:p>To recreate the conditions, you can try the following:</xhtml:p>
<xhtml:pre><xhtml:code class="language-php hljs php" data-lang="php">$date     = <xhtml:span class="hljs-string">'2016-06-16'</xhtml:span>;
$fromForm = DateTimeImmutable::createFromFormat(<xhtml:span class="hljs-string">'Y-m-d'</xhtml:span>, $date);
$today    = <xhtml:span class="hljs-keyword">new</xhtml:span> DateTimeImmutable(<xhtml:span class="hljs-string">'today'</xhtml:span>);
<xhtml:span class="hljs-keyword">echo</xhtml:span> $fromForm == $today ? <xhtml:span class="hljs-string">'Equal'</xhtml:span> : <xhtml:span class="hljs-string">'Not equal'</xhtml:span>; <xhtml:span class="hljs-comment">// outputs "Not equal"</xhtml:span>
</xhtml:code></xhtml:pre>
<xhtml:p>What's happening? Well, if you were to echo the results of each
of <xhtml:code>$fromForm-&gt;format('c')</xhtml:code> and
<xhtml:code>$today-&gt;format('c')</xhtml:code>, the difference is clear: the
<xhtml:code>$fromForm</xhtml:code> value includes the <xhtml:em>time</xhtml:em> when the
instance was created, while <xhtml:code>$today</xhtml:code> has the time set to
midnight.</xhtml:p>
<xhtml:p>So, how do you zero out the time when using
<xhtml:code>createFromFormat()</xhtml:code>?</xhtml:p>
<xhtml:p>It turns out that one of the format characters you can use is
the <xhtml:code>|</xhtml:code> operator. When you include this at the end of
your format string, any fields not included in the format are
zero'ed out:</xhtml:p>
<xhtml:pre><xhtml:code class="language-php hljs php" data-lang="php">$fromForm = DateTimeImmutable::createFromFormat(<xhtml:span class="hljs-string">'Y-m-d|'</xhtml:span>);
</xhtml:code></xhtml:pre>
<xhtml:hr/>
<xhtml:h4>Reference</xhtml:h4>
<xhtml:ul>
<xhtml:li><xhtml:a href="https://www.php.net/manual/en/datetimeimmutable.createfromformat.php#datetimeimmutable.createfromformat.parameters">
DateTimeImmutable::createFromFormat() Parameters</xhtml:a></xhtml:li>
</xhtml:ul>
<xhtml:div class="h-entry"><xhtml:img class="u-photo photo" width="50" src="https://avatars0.githubusercontent.com/u/25943?v=3&amp;u=79dd2ea1d4d8855944715d09ee4c86215027fa80&amp;s=140" alt="matthew"/> <xhtml:a class="u-url u-uid p-name" href="https://mwop.net/blog/2026-04-16-php-create-from-format-reset.html">
PHP DateTimeImmutable::createFromFormat Reset Character</xhtml:a> was
originally published <xhtml:time class="dt-published" datetime="2026-04-16T10:30:00-05:00">16 April 2026</xhtml:time> on <xhtml:a href="https://mwop.net">https://mwop.net</xhtml:a> by <xhtml:a rel="author" class="p-author" href="https://mwop.net">Matthew Weier
O'Phinney</xhtml:a>.</xhtml:div>
</xhtml:div>
    </content>
  </entry>
  <entry xmlns:xhtml="http://www.w3.org/1999/xhtml">
    <title type="html"><![CDATA[SQL ENUM Modification]]></title>
    <published>2026-04-08T15:34:00-05:00</published>
    <updated>2026-04-08T15:34:00-05:00</updated>
    <link rel="alternate" type="text/html" href="https://mwop.net/blog/2026-04-08-sql-enum-modification.html"/>
    <id>https://mwop.net/blog/2026-04-08-sql-enum-modification.html</id>
    <author>
      <name>Matthew Weier O'Phinney</name>
      <email>contact@mwop.net</email>
      <uri>https://mwop.net</uri>
    </author>
    <content xmlns:xhtml="http://www.w3.org/1999/xhtml" type="xhtml">
      <xhtml:div xmlns:xhtml="http://www.w3.org/1999/xhtml"><xhtml:p>I'm doing a little DB work recently, and needing to choose how
to represent certain data in the database. For a few fields, ENUM
would be the correct choice, but there's a possibility I would need
to expand the ENUM later to add values.</xhtml:p>
<xhtml:p>My question: is this safe?</xhtml:p>
<xhtml:p>The short answer, in my research, is "yes", but with
caveats.</xhtml:p>
<xhtml:p>For Postgres, it's trivial; you can easily add values to ENUM
types:</xhtml:p>
<xhtml:pre><xhtml:code class="language-sql hljs sql" data-lang="sql"><xhtml:span class="hljs-keyword">ALTER</xhtml:span> <xhtml:span class="hljs-keyword">TYPE</xhtml:span> some_previously_defined_enum <xhtml:span class="hljs-keyword">ADD</xhtml:span> <xhtml:span class="hljs-keyword">VALUE</xhtml:span> <xhtml:span class="hljs-string">'new-value'</xhtml:span>;
</xhtml:code></xhtml:pre>
<xhtml:p>For MySQL, it's a bit more complex. ENUMs are defined within the
table schema, and to change them, you use an <xhtml:code>ALTER
TABLE</xhtml:code> statement:</xhtml:p>
<xhtml:pre><xhtml:code class="language-sql hljs sql" data-lang="sql"><xhtml:span class="hljs-keyword">ALTER</xhtml:span> <xhtml:span class="hljs-keyword">TABLE</xhtml:span> some_table
<xhtml:span class="hljs-keyword">MODIFY</xhtml:span> some_previously_defined_enum ENUM(<xhtml:span class="hljs-string">'value-1'</xhtml:span>,<xhtml:span class="hljs-string">'value-2'</xhtml:span>);
</xhtml:code></xhtml:pre>
<xhtml:p>Essentially, you're <xhtml:em>replacing</xhtml:em> the definition. This is
fine... so long as you don't change the order, or remove any
previously defined value in the ENUM. In other words,
<xhtml:em>append</xhtml:em> to the existing list if you want to safely change
it.</xhtml:p>
<xhtml:div class="h-entry"><xhtml:img class="u-photo photo" width="50" src="https://avatars0.githubusercontent.com/u/25943?v=3&amp;u=79dd2ea1d4d8855944715d09ee4c86215027fa80&amp;s=140" alt="matthew"/> <xhtml:a class="u-url u-uid p-name" href="https://mwop.net/blog/2026-04-08-sql-enum-modification.html">SQL
ENUM Modification</xhtml:a> was originally published <xhtml:time class="dt-published" datetime="2026-04-08T15:34:00-05:00">8 April
2026</xhtml:time> on <xhtml:a href="https://mwop.net">https://mwop.net</xhtml:a> by
<xhtml:a rel="author" class="p-author" href="https://mwop.net">Matthew
Weier O'Phinney</xhtml:a>.</xhtml:div>
</xhtml:div>
    </content>
  </entry>
  <entry xmlns:xhtml="http://www.w3.org/1999/xhtml">
    <title type="html"><![CDATA[CSS Grid Lanes]]></title>
    <published>2026-04-07T10:38:00-05:00</published>
    <updated>2026-04-07T10:38:00-05:00</updated>
    <link rel="alternate" type="text/html" href="https://mwop.net/blog/2026-04-07-css-grid-lanes.html"/>
    <id>https://mwop.net/blog/2026-04-07-css-grid-lanes.html</id>
    <author>
      <name>Matthew Weier O'Phinney</name>
      <email>contact@mwop.net</email>
      <uri>https://mwop.net</uri>
    </author>
    <content xmlns:xhtml="http://www.w3.org/1999/xhtml" type="xhtml">
      <xhtml:div xmlns:xhtml="http://www.w3.org/1999/xhtml"><xhtml:p>I've been using the experimental "<xhtml:code>display: masonry</xhtml:code>"
CSS for my gallery and a few other areas of my website for over a
year (with a fallback to standard grid columns). However, I noticed
in the last few months that my browser was no longer honoring it,
and finally researched what happened.</xhtml:p>
<xhtml:p>It turns out it's been renamed to "<xhtml:code>display:
grid-lanes</xhtml:code>" in the <xhtml:a href="https://drafts.csswg.org/css-grid-3/#grid-lanes-layout">CSS Grid
Level 3 specification</xhtml:a>. Otherwise, everything else remains the
same; continue using <xhtml:code>grid-template-columns</xhtml:code> and
<xhtml:code>grid-template-rows</xhtml:code> as you did with the the masonry
display.</xhtml:p>
<xhtml:p>Safari has it in preview already, while Firefox and Chrome-based
browsers have it behind a flag. (On Chrome-based browsers, visit
<xhtml:code>chrome://flags</xhtml:code>, and enable the "css-grid-lanes-layout"
flag.)</xhtml:p>
<xhtml:div class="h-entry"><xhtml:img class="u-photo photo" width="50" src="https://avatars0.githubusercontent.com/u/25943?v=3&amp;u=79dd2ea1d4d8855944715d09ee4c86215027fa80&amp;s=140" alt="matthew"/> <xhtml:a class="u-url u-uid p-name" href="https://mwop.net/blog/2026-04-07-css-grid-lanes.html">CSS Grid
Lanes</xhtml:a> was originally published <xhtml:time class="dt-published" datetime="2026-04-07T10:38:00-05:00">7 April 2026</xhtml:time> on
<xhtml:a href="https://mwop.net">https://mwop.net</xhtml:a> by <xhtml:a rel="author" class="p-author" href="https://mwop.net">Matthew Weier
O'Phinney</xhtml:a>.</xhtml:div>
</xhtml:div>
    </content>
  </entry>
  <entry xmlns:xhtml="http://www.w3.org/1999/xhtml">
    <title type="html"><![CDATA[Headless boot for Beelink EQ14]]></title>
    <published>2026-02-24T10:09:08-06:00</published>
    <updated>2026-03-23T14:06:08-05:00</updated>
    <link rel="alternate" type="text/html" href="https://mwop.net/blog/2026-02-24-headless-boot-beelink-eq14.html"/>
    <id>https://mwop.net/blog/2026-02-24-headless-boot-beelink-eq14.html</id>
    <author>
      <name>Matthew Weier O'Phinney</name>
      <email>contact@mwop.net</email>
      <uri>https://mwop.net</uri>
    </author>
    <content xmlns:xhtml="http://www.w3.org/1999/xhtml" type="xhtml">
      <xhtml:div xmlns:xhtml="http://www.w3.org/1999/xhtml"><xhtml:p>A few months back, I purchased a Beelink EQ14 mini server for my
homelab. One thing that has frustrated me has been that rebooting
or even powering on... has required I have either my keyboard or my
monitor plugged in (I haven't been able to determine exactly which
one yet). This has made me reluctant to reboot, as I then have to
switch my keyboard from my workstation over to the server, and plug
the HDMI from one of my monitors into it. I hate it.</xhtml:p>
<xhtml:p>In browsing a number of forums, I saw one recommendation to
switch the BIOS to use FastBoot.</xhtml:p>
<xhtml:p><xhtml:del>Can confirm, works!</xhtml:del></xhtml:p>
<xhtml:h4>Update</xhtml:h4>
<xhtml:p>While FastBoot helps, it doesn't entirely fix the issues. What I
discovered was that the server was requiring my keyboard in order
to boot; I tested this by rebooting the machine without cables, and
plugging in only the keyboard.</xhtml:p>
<xhtml:p>Unfortunately, there are no BIOS settings to override this
behavior. I dug up an old USB dongle for a presentation pointer,
plugged that in, and voilá — it boots now. I suspect any USB HID
dongle will likely work.</xhtml:p>
<xhtml:div class="h-entry"><xhtml:img class="u-photo photo" width="50" src="https://avatars0.githubusercontent.com/u/25943?v=3&amp;u=79dd2ea1d4d8855944715d09ee4c86215027fa80&amp;s=140" alt="matthew"/> <xhtml:a class="u-url u-uid p-name" href="https://mwop.net/blog/2026-02-24-headless-boot-beelink-eq14.html">Headless
boot for Beelink EQ14</xhtml:a> was originally published <xhtml:time class="dt-published" datetime="2026-02-24T10:09:08-06:00">24 February
2026</xhtml:time> on <xhtml:a href="https://mwop.net">https://mwop.net</xhtml:a> by
<xhtml:a rel="author" class="p-author" href="https://mwop.net">Matthew
Weier O'Phinney</xhtml:a>.</xhtml:div>
</xhtml:div>
    </content>
  </entry>
  <entry xmlns:xhtml="http://www.w3.org/1999/xhtml">
    <title type="html"><![CDATA[Globbing files to pass to CLI command options]]></title>
    <published>2026-02-18T13:56:00-06:00</published>
    <updated>2026-02-18T13:56:00-06:00</updated>
    <link rel="alternate" type="text/html" href="https://mwop.net/blog/2026-02-18-cli-options-with-globs.html"/>
    <id>https://mwop.net/blog/2026-02-18-cli-options-with-globs.html</id>
    <author>
      <name>Matthew Weier O'Phinney</name>
      <email>contact@mwop.net</email>
      <uri>https://mwop.net</uri>
    </author>
    <content xmlns:xhtml="http://www.w3.org/1999/xhtml" type="xhtml">
      <xhtml:div xmlns:xhtml="http://www.w3.org/1999/xhtml"><xhtml:p>I've been using Helm recently as part of a new product offering,
and as a way to deploy my various websites. Helm allows providing
<xhtml:em>values</xhtml:em> to the templates in a Helm chart via one or more
<xhtml:em>values</xhtml:em> files, which are provided via the option
<xhtml:code>-f</xhtml:code>. It's often useful to break these into several
files, so you can do things like cover common values, and then
environment- or namespace-specific values.</xhtml:p>
<xhtml:p>However, the <xhtml:code>-f</xhtml:code> option only accepts a single value,
and doesn't recognize globs.</xhtml:p>
<xhtml:h2>The printf solution</xhtml:h2>
<xhtml:p>The solution is to pass the glob to <xhtml:code>printf</xhtml:code>, with
the format <xhtml:code>'-f %s '</xhtml:code>. This will print out an option per
file.</xhtml:p>
<xhtml:p>When in a terminal, this can be done using <xhtml:code>printf</xhtml:code>
within a subshell. Now <xhtml:em>how</xhtml:em> you do that depends on the
shell, because the <xhtml:code>-f</xhtml:code> in our format string can be
interpreted as an option/flag to <xhtml:code>printf</xhtml:code> itself
depending on the shell.</xhtml:p>
<xhtml:p>For bash, we can do this:</xhtml:p>
<xhtml:pre><xhtml:code class="language-bash hljs bash" data-lang="bash">helm upgrade -n qa . $(<xhtml:span class="hljs-built_in">printf</xhtml:span> -- <xhtml:span class="hljs-string">'-f % '</xhtml:span> *.values.yaml)
</xhtml:code></xhtml:pre>
<xhtml:p>This is because <xhtml:code>printf</xhtml:code> in bash will emit an error
for any unknown option/flag it encounters; the <xhtml:code>--</xhtml:code>
tells the command when the end of all options/flags have been
reached, so that it treats the remainder as arguments.</xhtml:p>
<xhtml:p>For fish, we don't need the <xhtml:code>--</xhtml:code>, as the
<xhtml:code>printf</xhtml:code> implementation in fish doesn't accept arguments
anyways:</xhtml:p>
<xhtml:pre><xhtml:code class="language-bash hljs bash" data-lang="bash">helm upgrade -n qa . $(<xhtml:span class="hljs-built_in">printf</xhtml:span> <xhtml:span class="hljs-string">'-f % '</xhtml:span> *.values.yaml)
</xhtml:code></xhtml:pre>
<xhtml:h2>Makefile</xhtml:h2>
<xhtml:p>Of course, subshells in a <xhtml:code>Makefile</xhtml:code> require a little
change as well. In a <xhtml:code>Makefile</xhtml:code>, I write the above
as:</xhtml:p>
<xhtml:pre><xhtml:code class="language-vim hljs vim" data-lang="vim">helm upgrade -n <xhtml:span class="hljs-keyword">qa</xhtml:span> . $(<xhtml:span class="hljs-keyword">shell</xhtml:span> <xhtml:span class="hljs-built_in">printf</xhtml:span> -- <xhtml:span class="hljs-string">'-f %'</xhtml:span> *.<xhtml:span class="hljs-built_in">values</xhtml:span>.yaml)
</xhtml:code></xhtml:pre>
<xhtml:p>(And since I also declare <xhtml:code>SHELL=/bin/bash</xhtml:code> at the
top of my <xhtml:code>Makefile</xhtml:code>, I have to use the <xhtml:code>--</xhtml:code>
trick here.)</xhtml:p>
<xhtml:div class="h-entry"><xhtml:img class="u-photo photo" width="50" src="https://avatars0.githubusercontent.com/u/25943?v=3&amp;u=79dd2ea1d4d8855944715d09ee4c86215027fa80&amp;s=140" alt="matthew"/> <xhtml:a class="u-url u-uid p-name" href="https://mwop.net/blog/2026-02-18-cli-options-with-globs.html">Globbing
files to pass to CLI command options</xhtml:a> was originally published
<xhtml:time class="dt-published" datetime="2026-02-18T13:56:00-06:00">18
February 2026</xhtml:time> on <xhtml:a href="https://mwop.net">https://mwop.net</xhtml:a> by <xhtml:a rel="author" class="p-author" href="https://mwop.net">Matthew Weier
O'Phinney</xhtml:a>.</xhtml:div>
</xhtml:div>
    </content>
  </entry>
  <entry xmlns:xhtml="http://www.w3.org/1999/xhtml">
    <title type="html"><![CDATA[Passing script arguments to a Makefile target]]></title>
    <published>2026-02-11T10:41:53-06:00</published>
    <updated>2026-02-11T10:41:53-06:00</updated>
    <link rel="alternate" type="text/html" href="https://mwop.net/blog/2026-02-11-makefile-args.html"/>
    <id>https://mwop.net/blog/2026-02-11-makefile-args.html</id>
    <author>
      <name>Matthew Weier O'Phinney</name>
      <email>contact@mwop.net</email>
      <uri>https://mwop.net</uri>
    </author>
    <content xmlns:xhtml="http://www.w3.org/1999/xhtml" type="xhtml">
      <xhtml:div xmlns:xhtml="http://www.w3.org/1999/xhtml"><xhtml:p>I've many times wondered how I could build a
<xhtml:code>Makefile</xhtml:code> that would accept arguments to pass to the
command invoked by the build target. It turns out to be relatively
easy.</xhtml:p>
<xhtml:p>There is a <xhtml:code>make</xhtml:code> variable called
<xhtml:code>MAKECMDGOALS</xhtml:code> that contains the list of possible build
targets. We can <xhtml:code>filter-out</xhtml:code> any of those from the
arguments passed to <xhtml:code>make</xhtml:code> (as referenced by
<xhtml:code>$@</xhtml:code>) to get a list of command arguments to pass on to
our program.</xhtml:p>
<xhtml:pre><xhtml:code class="language-makefile hljs makefile" data-lang="makefile"><xhtml:span class="hljs-comment">#!make</xhtml:span>
SHELL := /bin/bash

<xhtml:span class="hljs-meta"><xhtml:span class="hljs-meta-keyword">.PHONY</xhtml:span>: hello</xhtml:span>

<xhtml:span class="hljs-section">default: help</xhtml:span>

<xhtml:span class="hljs-section">hello:  # Hello world</xhtml:span>
        @echo <xhtml:span class="hljs-string">"Hello,"</xhtml:span> <xhtml:span class="hljs-variable">$(<xhtml:span class="hljs-built_in">filter</xhtml:span>-out <xhtml:span class="hljs-variable">$@</xhtml:span>,<xhtml:span class="hljs-variable">$(MAKECMDGOALS)</xhtml:span>)</xhtml:span>


<xhtml:span class="hljs-section">%: # catch-all target to ignore argument "targets"</xhtml:span>
        @: <xhtml:span class="hljs-comment"># no-op</xhtml:span>
</xhtml:code></xhtml:pre>
<xhtml:p>From here, if I invoke <xhtml:code>make hello world</xhtml:code>, it will
spit out <xhtml:code>Hello, world</xhtml:code>.</xhtml:p>
<xhtml:p>But what about if you want to pass a flag or option? Add a
<xhtml:code>--</xhtml:code> before any flags or options so that
<xhtml:code>make</xhtml:code> won't treat them as its own options. (That said,
I've had limited success with this.</xhtml:p>
<xhtml:h4>References</xhtml:h4>
<xhtml:p>I learned this technique via <xhtml:a href="https://www.codegenes.net/blog/passing-arguments-to-make-run/">a
blog post on CodeGenes</xhtml:a>.</xhtml:p>
<xhtml:div class="h-entry"><xhtml:img class="u-photo photo" width="50" src="https://avatars0.githubusercontent.com/u/25943?v=3&amp;u=79dd2ea1d4d8855944715d09ee4c86215027fa80&amp;s=140" alt="matthew"/> <xhtml:a class="u-url u-uid p-name" href="https://mwop.net/blog/2026-02-11-makefile-args.html">Passing
script arguments to a Makefile target</xhtml:a> was originally published
<xhtml:time class="dt-published" datetime="2026-02-11T10:41:53-06:00">11
February 2026</xhtml:time> on <xhtml:a href="https://mwop.net">https://mwop.net</xhtml:a> by <xhtml:a rel="author" class="p-author" href="https://mwop.net">Matthew Weier
O'Phinney</xhtml:a>.</xhtml:div>
</xhtml:div>
    </content>
  </entry>
  <entry xmlns:xhtml="http://www.w3.org/1999/xhtml">
    <title type="html"><![CDATA[When docker buildx cannot resolve your container registry]]></title>
    <published>2026-02-11T09:49:31-06:00</published>
    <updated>2026-02-11T09:49:31-06:00</updated>
    <link rel="alternate" type="text/html" href="https://mwop.net/blog/2026-02-11-docker-daemon-resolve-conf.html"/>
    <id>https://mwop.net/blog/2026-02-11-docker-daemon-resolve-conf.html</id>
    <author>
      <name>Matthew Weier O'Phinney</name>
      <email>contact@mwop.net</email>
      <uri>https://mwop.net</uri>
    </author>
    <content xmlns:xhtml="http://www.w3.org/1999/xhtml" type="xhtml">
      <xhtml:div xmlns:xhtml="http://www.w3.org/1999/xhtml"><xhtml:p>I had an odd situation today when building and pushing a
container image to a registry.</xhtml:p>
<xhtml:p>I have a private registry in my homelab. I have an internal DNS
server that can resolve it when in my home network, and my machines
in my home network all use that internal DNS server. Great,
fantastic, just works.</xhtml:p>
<xhtml:p>Except for some reason, when running a <xhtml:code>docker buildx build
--push</xhtml:code> operation, it was unable to resolve the internal
name... because it was using the wrong DNS server. It was trying to
resolve via the 8.8.8.8 DNS server. The Google DNS servers. Which
I've not even configured as an upstream in my recursive DNS server
on the local network.</xhtml:p>
<xhtml:p>My guess is that the Docker daemon falls back to Google DNS
servers if the system DNS cannot be reached at any point. Clearly,
it then never tests to see if the system DNS has become reachable
again, so it gets stuck there.</xhtml:p>
<xhtml:p>The solution? Restart the docker service:</xhtml:p>
<xhtml:pre><xhtml:code class="language-bash hljs bash" data-lang="bash">sudo systemctl restart docker
</xhtml:code></xhtml:pre>
<xhtml:p>Once I did that, it resolved using the system DNS next time.</xhtml:p>
<xhtml:div class="h-entry"><xhtml:img class="u-photo photo" width="50" src="https://avatars0.githubusercontent.com/u/25943?v=3&amp;u=79dd2ea1d4d8855944715d09ee4c86215027fa80&amp;s=140" alt="matthew"/> <xhtml:a class="u-url u-uid p-name" href="https://mwop.net/blog/2026-02-11-docker-daemon-resolve-conf.html">When
docker buildx cannot resolve your container registry</xhtml:a> was
originally published <xhtml:time class="dt-published" datetime="2026-02-11T09:49:31-06:00">11 February 2026</xhtml:time> on <xhtml:a href="https://mwop.net">https://mwop.net</xhtml:a> by <xhtml:a rel="author" class="p-author" href="https://mwop.net">Matthew Weier
O'Phinney</xhtml:a>.</xhtml:div>
</xhtml:div>
    </content>
  </entry>
  <entry xmlns:xhtml="http://www.w3.org/1999/xhtml">
    <title type="html"><![CDATA[Removing a filename containing a null byte or binary character on Linux]]></title>
    <published>2026-02-06T11:01:27-06:00</published>
    <updated>2026-02-06T11:01:27-06:00</updated>
    <link rel="alternate" type="text/html" href="https://mwop.net/blog/2026-02-06-linux-null-byte-filename-removal.html"/>
    <id>https://mwop.net/blog/2026-02-06-linux-null-byte-filename-removal.html</id>
    <author>
      <name>Matthew Weier O'Phinney</name>
      <email>contact@mwop.net</email>
      <uri>https://mwop.net</uri>
    </author>
    <content xmlns:xhtml="http://www.w3.org/1999/xhtml" type="xhtml">
      <xhtml:div xmlns:xhtml="http://www.w3.org/1999/xhtml"><xhtml:p>Somehow, I got a file in my tree that started with a null byte.
I only discovered it because <xhtml:code>git status</xhtml:code> was noting it
wasn't added to my branch, and wanted to know if I wanted to add
it.</xhtml:p>
<xhtml:p>No, no, I did not. I wanted to delete it.</xhtml:p>
<xhtml:p>But, of course, you cannot reference such a file by name, so I
had to learn a few tricks.</xhtml:p>
<xhtml:p>First off, you can list names with binary bytes using:</xhtml:p>
<xhtml:pre><xhtml:code class="language-bash hljs bash" data-lang="bash">/bin/ls -lb
</xhtml:code></xhtml:pre>
<xhtml:p>But even better, you can get the inode if you use:</xhtml:p>
<xhtml:pre><xhtml:code class="language-bash hljs bash" data-lang="bash">/bin/ls -li
</xhtml:code></xhtml:pre>
<xhtml:p>When you do, the inode is in the first column of the list for
each file.</xhtml:p>
<xhtml:p>Once you know that, you can delete the file, using find:</xhtml:p>
<xhtml:pre><xhtml:code class="language-bash hljs bash" data-lang="bash">find . -maxdepth 1 -inum &lt;inode_id&gt; -<xhtml:span class="hljs-built_in">exec</xhtml:span> rm -i -- {} +
</xhtml:code></xhtml:pre>
<xhtml:div class="h-entry"><xhtml:img class="u-photo photo" width="50" src="https://avatars0.githubusercontent.com/u/25943?v=3&amp;u=79dd2ea1d4d8855944715d09ee4c86215027fa80&amp;s=140" alt="matthew"/> <xhtml:a class="u-url u-uid p-name" href="https://mwop.net/blog/2026-02-06-linux-null-byte-filename-removal.html">
Removing a filename containing a null byte or binary character on
Linux</xhtml:a> was originally published <xhtml:time class="dt-published" datetime="2026-02-06T11:01:27-06:00">6 February 2026</xhtml:time> on
<xhtml:a href="https://mwop.net">https://mwop.net</xhtml:a> by <xhtml:a rel="author" class="p-author" href="https://mwop.net">Matthew Weier
O'Phinney</xhtml:a>.</xhtml:div>
</xhtml:div>
    </content>
  </entry>
  <entry xmlns:xhtml="http://www.w3.org/1999/xhtml">
    <title type="html"><![CDATA[From zsh to fish]]></title>
    <published>2025-11-17T17:00:10-06:00</published>
    <updated>2025-11-17T17:00:10-06:00</updated>
    <link rel="alternate" type="text/html" href="https://mwop.net/blog/2025-11-17-from-zsh-to-fish.html"/>
    <id>https://mwop.net/blog/2025-11-17-from-zsh-to-fish.html</id>
    <author>
      <name>Matthew Weier O'Phinney</name>
      <email>contact@mwop.net</email>
      <uri>https://mwop.net</uri>
    </author>
    <content xmlns:xhtml="http://www.w3.org/1999/xhtml" type="xhtml">
      <xhtml:div xmlns:xhtml="http://www.w3.org/1999/xhtml"><xhtml:p>I'm a longtime zsh user. A colleague introduced me to it in
2009, and I was an instant convert, if nothing else than for
directory aliases and simpler <xhtml:code>$PATH</xhtml:code> management. Within
a couple of years, I discovered <xhtml:a href="https://ohmyz.sh">oh-my-zsh</xhtml:a>, which put my shell on steroids,
giving me a ton of completion capabilities, better prompts, and
more.</xhtml:p>
<xhtml:p>But a few years ago, I started noticing that my shell load times
were getting worse and worse. At that time, I discovered I could
easily switch to vanilla zsh with <xhtml:a href="https://zplug.github.io">zplug</xhtml:a> managing a small number of
plugins I used (nvm, fzf, and a few others). I also discovered
<xhtml:a href="https://startship.rs">starship</xhtml:a>, which gave me more
prompt options, with faster startup times.</xhtml:p>
<xhtml:p>And yet...</xhtml:p>
<xhtml:p>I kept reading <xhtml:a href="https://jvns.ca">Julia Evans</xhtml:a>
recommending <xhtml:a href="https://fishshell.com">fish</xhtml:a>. She often
would note that fish just does things that other shells need
plugins or customization for: decent tab completion, better history
capabilities, etc.</xhtml:p>
<xhtml:p>So I took the plunge finally in the past couple weeks to give
fish a try.</xhtml:p>
<xhtml:h2>Configuration</xhtml:h2>
<xhtml:p>First off, the switch more than halved the amount of
configuration I needed to have an equivalent setup. I was able to
remove a ton of configuration I had in zsh around history
management, autocompletion, and overrides.</xhtml:p>
<xhtml:p>As I noted, with zsh, I was using zplug, and I had a half-dozen
plugins. With fish, initially I had no plugins, but in order to get
<xhtml:a href="https://github.com/nvm-sh/nvm">nvm</xhtml:a> running, I needed
to install <xhtml:a href="https://github.com/jorgebucaran/fisher">fisher</xhtml:a>, the de facto
fish plugin manager. But that's literally the only plugin I'm now
using.</xhtml:p>
<xhtml:p>I continued to use starship and fzf, which meant two lines of
configuration in my fish configuration, and no changes
otherwise.</xhtml:p>
<xhtml:p>And there's no lag whatsoever when starting up a shell. With
zsh, even with my minimal config, I would sometimes wait a second
or two for a shell to spawn. With fish, no wait.</xhtml:p>
<xhtml:h2>Discoveries</xhtml:h2>
<xhtml:p>One thing I've kept from oh-my-zsh is a utility called
<xhtml:code>take</xhtml:code>, which does the following:</xhtml:p>
<xhtml:ul>
<xhtml:li>If given a directory name, it creates it, and then enters
it</xhtml:li>
<xhtml:li>If given an archive file, it unarchives it into a directory,
and then enters that directory</xhtml:li>
<xhtml:li>If given a git repository name, it clones it, and then enters
that directory</xhtml:li>
</xhtml:ul>
<xhtml:p>When porting this to fish, I discovered some really cool
features of that shell.</xhtml:p>
<xhtml:p>First, fish will automatically autoload functions from the
<xhtml:code>functions/</xhtml:code> subdirectory of your fish configuration. So
if you name the function the same as the file (e.g.,
<xhtml:code>functions/take.fish</xhtml:code>), it will load it <xhtml:em>on
demand</xhtml:em>. This is a nice performance improvement over loading
<xhtml:em>everything</xhtml:em>.</xhtml:p>
<xhtml:p>Second, fish uses a standard syntax for any block statement.
Instead of sometimes needing braces, sometimes needing a keyword
(which generally varies BASED on the block type - e.g.
<xhtml:code>fi</xhtml:code> to end a conditional, <xhtml:code>done</xhtml:code> to end a
loop), all blocks use an <xhtml:code>end</xhtml:code> keyword. This makes it
far simpler to remember and less prone to errors.</xhtml:p>
<xhtml:p>Third, when defining a function, you can specify variable names
to which to capture arguments. This is far easier to visually parse
and use than standard posix shells, where you use positional
parameters. As an example:</xhtml:p>
<xhtml:pre><xhtml:code class="language-shell hljs shell" data-lang="shell">function takedir -a newpath
    mkdir -p $newpath &amp;&amp; cd $newpath
end
</xhtml:code></xhtml:pre>
<xhtml:p>Fourth, while you <xhtml:em>can</xhtml:em> use the notation
<xhtml:code>varname=value</xhtml:code> to define variables, there's a better
built-in, the <xhtml:code>set</xhtml:code> directive, which can:</xhtml:p>
<xhtml:ul>
<xhtml:li>Define block-local (<xhtml:code>set -l</xhtml:code>) and function-local
(<xhtml:code>set -f</xhtml:code>) variables</xhtml:li>
<xhtml:li>Define globally-available variables (<xhtml:code>set -g</xhtml:code>)</xhtml:li>
<xhtml:li>Define environment variables (<xhtml:code>set -x</xhtml:code>, for
e<xhtml:strong>x</xhtml:strong>port) that persist to child shells</xhtml:li>
</xhtml:ul>
<xhtml:p>Using this, it's far easier both to ensure that a variable is
scoped correctly, as well as to reason about the scope of a given
variable. And those captured arguments I mentioned? Automatically
scoped to the function, so they won't bleed outside of it.</xhtml:p>
<xhtml:p>(There's also a "univeral" flag, <xhtml:code>-u</xhtml:code>, which will not
only set it in the current shell, at the globally available level,
but make it available across any other instances, and persist it
for future invocations. This seems dangerous, though!)</xhtml:p>
<xhtml:p>The combination of these meant that the <xhtml:code>take</xhtml:code>
declaration took fewer lines of code, was easier to understand, and
less likely to bleed state. I'll take it!</xhtml:p>
<xhtml:h2>But will I stick with it?</xhtml:h2>
<xhtml:p>I think so. I even put it on some servers I maintain, and it's
instantly given me more and better functionality than the default
shell available on each, which makes being on those servers more
comfortable. Having less configuration is something I've been
keeping an eye on, as more configuration means it's harder to
reason about how things work, and more likely to break or fail in
interesting ways when updating or upgrading.</xhtml:p>
<xhtml:p>I'll still need to keep my bash chops; provisioning scripts for
containers and VMs generally have to depend on this lowest common
denominator. However, having a useful out-of-the-box shell for my
workstation and servers that's easy to script? I'll take it.</xhtml:p>
<xhtml:div class="h-entry"><xhtml:img class="u-photo photo" width="50" src="https://avatars0.githubusercontent.com/u/25943?v=3&amp;u=79dd2ea1d4d8855944715d09ee4c86215027fa80&amp;s=140" alt="matthew"/> <xhtml:a class="u-url u-uid p-name" href="https://mwop.net/blog/2025-11-17-from-zsh-to-fish.html">From zsh
to fish</xhtml:a> was originally published <xhtml:time class="dt-published" datetime="2025-11-17T17:00:10-06:00">17 November 2025</xhtml:time> on
<xhtml:a href="https://mwop.net">https://mwop.net</xhtml:a> by <xhtml:a rel="author" class="p-author" href="https://mwop.net">Matthew Weier
O'Phinney</xhtml:a>.</xhtml:div>
</xhtml:div>
    </content>
  </entry>
</feed>
