Editing Without an Editor
It doesn't happen often, but it does happen.
You've logged into a machine - or container, more likely - with a very minimal base system that doesn't include any text editors. Not nano or even ed.
But you really need to make just a couple changes to a file or two, and spinning an entirely new image & reploying is such a P.I.T.A. Maybe it's worse: you can't respin and redeploy lest you destroy important state. What to do!?
It won't be fast - you'll be changing one line at a time - but you can make this work.
The key is a scripting language interpreter, ideally perl - that's what we're using here - but the method works with any that allow scripts passed on the command-line. I've yet to meet a base image without at least one of perl or python: their role as "system" languages tends to make their presence a requirement.
Inserting lines
- Locate the line in the file you'd like to change, then note the contents of the line immediately after it. Let's call this
<LINE_POST>from now on. - Run the following, importantly redirecting to a temporary file first so as not to complete clear the file contents! In this example, the inserted text is refered to as
<INSERTED>:
$ perl -n -e 'print "<INSERTED>\n", if (/<LINE_POST>/); print;' the-file-to-edit > /tmp/some-temp-file-name
$ mv /tmp/some-temp-file-name the-file-to-edit
What's going on here?
The -n -e options tell perl to:
- "assume
while (<>) { ... }loop around program" (-n)- the
<>"diamond operator" reads the lines of files provided on the command-line (or STDIN) until none remain- in this case it is reading the contents of
the-file-to-edit
- in this case it is reading the contents of
- the
- to run the string provided as the argument to
-eas a one-line program
The code we've given -e:
- searches for the
<LINE_POST>line and if found, prints the line-to-insert before it:print "<INSERTED>\n", if (/<LINE_POST>/);
- prints all current lines in the file:
print;
(Note: this small code makes heavy use of the implicit variable $_ to be even smaller: for example, the logic clauses here are written in full as $_ =~ /.../)
Removing lines
Changing the logic just a bit to not print a given line (let's call that <LINE_TO_RM> here) and viola you can now remove lines from the file as well:
$ perl -n -e 'print, unless (/<LINE_TO_RM>/);' the-file-to-edit > /tmp/some-temp-file-name
$ mv /tmp/some-temp-file-name the-file-to-edit
(taking advantage of perl's lovely & rare unless keyword)
You may never need this technique - I hope you don't! - but if you do, it's an absolute life-saver.
Happy New Year, Earth! 🥳