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
-e
as 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! 🥳