Solaris Text Editors on a Bare System: vi Essentials and ed When Nothing Else Works

Solaris Admin Series, part 9. Previous: The Solaris PATH Problem: /usr/bin vs /usr/xpg4/bin vs /usr/sfw/bin vs /usr/gnu/bin. Related: part 6, Shells on Solaris 10 and 11, and part 7, Solaris Man Pages. Next up: basic process management with ps -ef, pgrep, pkill, kill signals and nohup.

The day you really need a text editor on Solaris is rarely a good day. The box is in single-user mode because /etc/vfstab has a typo, you are on a serial console through an ILOM or a terminal server, the TERM variable says something the system has never heard of, and there is no vim or nano on a minimal install. What is always there is the traditional vi and, underneath it, the line editors ex and ed. This post covers what ships on each release, how to fix the terminal so vi works, the vi commands an admin actually uses, and how to make a clean recovery edit with ed when full-screen editing is impossible.

Applies to: both Solaris 10 and Solaris 11 (11.4), SPARC and x86. Differences called out below: on both releases /usr/bin/vi is the classic Sun (Bill Joy derived) vi, not vim, and /usr/xpg4/bin/vi is the XPG4/POSIX-conforming variant. Solaris 10 has no vim in the base OS (it came on the Companion CD or from OpenCSW); Solaris 11 offers vim (and nano) as optional IPS packages that may not be on a minimal or text-only install. ed and ex are part of the core OS on both, and terminal descriptions live in /usr/share/lib/terminfo on both.

Prerequisites

  • A shell on a Solaris 10 or Solaris 11.4 system: console, serial console (ILOM/ALOM/terminal server) or SSH.
  • Root, a role, or an RBAC profile allowing the file edits you need (on Solaris 11, root is a role by default; see the pfedit note below).
  • Knowing which shell you are in (part 6), because the syntax for setting TERM differs between Bourne/ksh/bash and csh.

Step 1: Know what editors ship by default

EditorSolaris 10Solaris 11.4Needs a working TERM?
/usr/bin/vi (also view, vedit, ex, edit)Yes, core OSYes, installed by defaultvi yes; ex no
/usr/xpg4/bin/vi, /usr/xpg4/bin/exYes (XPG4 package)YesSame as above
/usr/bin/ed, red (restricted ed)Yes, core OSYes, core OSNo, works on any terminal
vimNot in base OS (Companion CD /opt/sfw or OpenCSW /opt/csw)Optional IPS package (editor/vim), not always installedYes
nano, GNU emacsNot in base OSOptional IPS packagesYes
dtpad (CDE), gedit (GNOME)dtpad with CDEgedit with the desktop groupGUI only, useless on a console
$ ls -l /usr/bin/vi /usr/bin/ex /usr/bin/view /usr/bin/ed /usr/xpg4/bin/vi
$ type vi vim nano ed

# Solaris 11: which package delivers it, and is vim available?
$ pkg search -l /usr/bin/vi
$ pkg list -a 'editor/*'
# pkg install editor/vim          # optional, needs a configured publisher

# Solaris 10: which package delivers it?
# pkgchk -l -p /usr/bin/vi

vi, ex and view are the same program started in different modes (view is read-only vi). On Solaris 10 they are hard links to one binary; on 11.4 you may see symlinks. Either way, learning plain vi means you can edit on every Solaris box you will ever touch, including the miniroot used for failsafe boots and install media.

Step 2: Fix TERM and terminfo first

Full-screen vi needs a terminal description from the terminfo database so it knows how to move the cursor and clear the screen. If TERM is unset, wrong, or names an entry that does not exist on this system, vi falls back to “open mode” (one line at a time) or draws garbage. Typical symptoms:

$ vi /etc/hosts
xterm-256color: Unknown terminal type
I don't know what kind of terminal you are on - all I have is 'xterm-256color'.
[Using open mode]
"/etc/hosts" 12 lines, 311 characters

Check what you have and whether terminfo knows it. Compiled entries live under /usr/share/lib/terminfo/<first letter>/<name> on both releases (Solaris 11 also has an ncurses database under /usr/gnu/share/terminfo that GNU programs use, which is why vim may work where /usr/bin/vi does not).

$ echo $TERM
xterm-256color
$ ls /usr/share/lib/terminfo/x/ | head
$ ls -l /usr/share/lib/terminfo/v/vt100 /usr/share/lib/terminfo/s/sun
$ infocmp xterm-256color > /dev/null || echo "no terminfo entry for $TERM"
$ tput cols; tput lines
80
24

Then set a TERM that exists. Good, safe choices:

Where you areTERM to use
SSH from a Linux or macOS terminal (xterm, GNOME Terminal, iTerm2, PuTTY)xterm (use vt100 if xterm misbehaves)
SPARC framebuffer consolesun (or sun-color)
x86 text consolesun-color (Solaris 10 x86 and Solaris 11 x86 default)
Serial console via ILOM, ALOM, LOM or a terminal servervt100
Anything you are not sure about, or a dumb terminalvt100, or give up on vi and use ed (Step 4)
# sh, ksh, bash
$ TERM=vt100; export TERM

# csh, tcsh
% setenv TERM vt100

# Window size wrong after the change (lines wrap or the screen is cut off)?
$ stty rows 24 columns 80
$ stty -a | head -2

To make the serial console default stick, Solaris uses the console-login SMF service: on Solaris 10 and 11, svccfg -s svc:/system/console-login setprop ttymon/terminal_type = astring: vt100, then svcadm refresh svc:/system/console-login:default and svcadm restart svc:/system/console-login:default. For SSH sessions, set TERM in the client or in your ~/.profile with a guard such as infocmp "$TERM" >/dev/null 2>&1 || TERM=vt100.

Step 3: vi essentials every Solaris admin needs

Classic vi has two main modes: command mode (where you start, and where letters are commands) and insert mode (where letters are text). Esc always takes you back to command mode; if you are lost, press Esc twice. Lines starting with : are ex commands typed on the bottom line.

Getting in and out

KeysWhat it does
vi file, view fileEdit a file; open read-only
:wWrite (save)
:qQuit (refuses if there are unsaved changes)
:wq, :x, ZZWrite and quit (:x/ZZ only write if changed)
:q!Quit and throw away changes
:w!Force a write to a read-only file you own or as root
:e!Discard changes and reload the file from disk
:w /tmp/copyWrite to a different file (handy when the original cannot be written)

Inserting text

KeysEnters insert mode…
i / abefore / after the cursor
I / Aat the start / end of the line
o / Oon a new line below / above
rx(not insert mode) replace one character with x
cw, Cchange to end of word; change to end of line
Escback to command mode

Moving and searching

KeysMovement
h j k lleft, down, up, right (use these when arrow keys print A/B/C/D)
w, b, 0, $next word, previous word, start of line, end of line
G, 1G, 42G or :42last line, first line, line 42
Ctrl-F, Ctrl-Bpage forward, page back
/pattern, ?patternsearch forward, backward
n, Nrepeat search in the same, opposite direction

Deleting, copying, undo

KeysAction
xdelete character
dd, 5dd, dw, Ddelete line, 5 lines, word, to end of line
yy, 5yyyank (copy) line, 5 lines
p, Pput after, before the cursor
uundo the last change (classic vi has one level; u again redoes it)
Uundo all changes on the current line
.repeat the last change
Jjoin next line onto this one

ex commands worth memorizing

:set number          " show line numbers   (:set nonumber to turn off)
:set list            " show tabs as ^I and line ends as $ (find stray whitespace, ^M)
:set showmode        " show INSERT MODE on the status line
:set ic              " ignore case in searches
:%s/old/new/g        " replace everywhere
:10,20s/^/#/         " comment out lines 10-20
:g/^#/d              " delete every comment line
:r /etc/hosts        " read a file in below the cursor
:r !uname -a         " read a command's output in below the cursor
:!ls -l /etc/vfstab  " run a shell command, then return
:%!sort              " filter the whole buffer through sort

Put favorite settings in ~/.exrc (or the EXINIT variable). Keep it to options classic vi understands, for example set showmode number. A .vimrc-style line in .exrc makes Solaris vi print an error every time it starts.

Editing system files as root, safely

# cp -p /etc/vfstab /etc/vfstab.$(date +%Y%m%d)   # keep a dated copy, -p preserves mode/owner/time
# vi /etc/vfstab
# ls -l /etc/vfstab /etc/vfstab.20261107
-rw-r--r--   1 root     sys          542 Nov  7 14:20 /etc/vfstab
-rw-r--r--   1 root     sys          531 Nov  2 09:12 /etc/vfstab.20261107

vi and ed rewrite the existing file in place, so owner, group, mode and hard links are preserved. That is not true of “edit a copy then mv it over the original”, which leaves the new file owned by whoever made it; use cp back over the original, or fix ownership with chown/chmod afterwards. Many files under /etc are mode 0444 or 0644 owned by root; as root you need :w! for the read-only ones.

On Solaris 11, prefer pfedit for delegated edits: an RBAC authorization such as solaris.admin.edit/etc/hosts lets a non-root user run pfedit /etc/hosts, which opens a copy in $EDITOR, writes it back preserving ownership and logs the change through auditing. On Solaris 10, the equivalent is a role or sudoedit if sudo is installed.

Recovering after a crash or a dropped session

$ vi -r                 # list files that can be recovered
/var/tmp:
No files saved.
/var/preserve/root:
On Sat Nov  7 14:02:11 2026 saved 3 lines of about 2 words of file /etc/hosts

$ vi -r /etc/hosts      # recover; check it, then :w and :q
$ ex -r /etc/hosts      # same thing without full-screen mode

vi keeps its working buffer in /var/tmp (files named Ex…); preserved copies go under /var/preserve. Recovered text is your unsaved work, not the file on disk, so compare before writing.

Step 4: Use ed when nothing else works

ed is a line editor: it never needs cursor addressing, so it works with a broken TERM, on a dumb serial line, through a flaky out-of-band console, inside a script, and in the restricted environments you hit during recovery. It is also terse: it prints a byte count when it reads or writes and a single ? on any error. Type h to explain the last error or H to turn on verbose errors for the session, and use -p to get a prompt.

CommandMeaning
ed -p "*" fileEdit file with * as the prompt
1,$p or ,pPrint all lines; ,n prints them with line numbers
5p, 5,10nPrint line 5; lines 5 to 10 numbered
/pattern/, ?pattern?Go to next / previous line matching and print it
a, i, cAppend after, insert before, change the current line; type text, end with a line holding only .
d, 5,7dDelete current line, lines 5 to 7
s/old/new/, s/old/new/gpSubstitute on the current line (and print it)
g/re/p, g/re/s/a/b/Run a command on every line matching re
uUndo the last command
w, q, QWrite; quit (warns once if unsaved); quit without saving
!cmdRun a shell command

Recovery example: comment out a bad line in /etc/vfstab

Solaris 10 with a UFS root drops to single-user mode (or a maintenance shell) when a vfstab entry cannot be mounted. Root is often mounted read-only at that point, so remount it first, then fix the file:

# mount -o remount,rw /          # Solaris 10 UFS root; ZFS root (11) is normally already rw
# TERM=dumb; export TERM          # we are not going to use vi anyway
# ed -p '* ' /etc/vfstab
542
* ,n
1	#device		device		mount		FS	fsck	mount	mount
2	#to mount	to fsck		point		type	pass	at boot	options
...
9	/dev/dsk/c1t1d0s6	/dev/rdsk/c1t1d0s6	/u01	ufs	2	yes	-
* 9s/^/#/p
#/dev/dsk/c1t1d0s6	/dev/rdsk/c1t1d0s6	/u01	ufs	2	yes	-
* w
543
* q
# mountall -l

The byte count went up by exactly one, which is a quick sanity check that you changed only what you meant to. Solaris vfstab fields are whitespace separated, so a tab versus spaces does not matter, but each entry must stay on one line with all seven fields.

Recovery example: back out a bad tunable in /etc/system

A wrong line in /etc/system can stop the kernel from booting. Boot with the old file (boot -a on SPARC or the GRUB -a kernel option on x86, and answer /dev/null or /etc/system.bak at the “Name of system file” prompt), or boot failsafe / a boot environment, then comment the line out. Comments in /etc/system start with *:

# ed /etc/system
2847
/zfs_arc_max/
set zfs:zfs_arc_max=0x10000000
s/^/* /p
* set zfs:zfs_arc_max=0x10000000
w
2849
q

On Solaris 11.4, Oracle recommends putting your own tunables in a file under /etc/system.d/ rather than editing /etc/system directly; the same ed technique works on those files.

Appending a line and editing from a script

# ed -s /etc/hosts <<'EOF'
$a
192.0.2.50	dbhost01	dbhost01.example.com
.
w
q
EOF
# tail -1 /etc/hosts
192.0.2.50	dbhost01	dbhost01.example.com

ed -s suppresses the byte counts, which makes ed a dependable in-place editor in scripts on Solaris 10, where no sed has -i (see part 8).

ex: vi’s own line mode

If vi drops you into open mode, or you started ex on purpose, you have the same commands as ed with the vi conveniences (:set number, % for all lines). Type vi at the : prompt to switch into full-screen mode once TERM is fixed, and Q in vi to drop back to ex. Accidentally pressing Q is a classic way to “lose” vi; type vi and press Enter to get it back.

Step 5: Set EDITOR and VISUAL

Several Solaris commands open an editor for you and pick it from VISUAL or EDITOR. If neither is set, the fallback is often ed, which is why crontab -e famously answers with nothing but a number: that is ed printing the byte count of your crontab. Type q to leave it.

# ~/.profile (sh, ksh, bash)
EDITOR=/usr/bin/vi; VISUAL=/usr/bin/vi; export EDITOR VISUAL

# ~/.cshrc (csh)
setenv EDITOR /usr/bin/vi
setenv VISUAL /usr/bin/vi

$ crontab -e                         # now opens vi
# svccfg -s svc:/site/myapp editprop # Solaris 11: edit service properties in $EDITOR
# visudo                             # if sudo is installed

Set root’s editor too, and keep it the absolute path /usr/bin/vi rather than vim, so it still works when /usr/gnu/bin or an optional package is missing.

Verification

$ echo $TERM; infocmp $TERM > /dev/null && echo "terminfo OK"
$ tput cols; tput lines             # should match your window
$ echo $EDITOR $VISUAL
$ vi /tmp/vitest                    # o, type a line, Esc, :wq
$ ed -s /tmp/vitest <<'EOF'
,p
q
EOF
$ ls -l /etc/vfstab /etc/system     # owner/mode unchanged after edits

After any recovery edit to /etc/vfstab, run mountall -l (or mount -a-style checks with mount -v) before rebooting; after an /etc/system change, keep the backup copy until the next clean boot.

Troubleshooting and gotchas

  • “Unknown terminal type” or open mode. TERM names an entry missing from /usr/share/lib/terminfo (common with xterm-256color, screen-256color, tmux-256color on older releases). Set TERM=xterm or vt100.
  • Arrow keys type A, B, C, D or the screen redraws oddly. Still a TERM mismatch, or you are in insert mode. Use h j k l, or fix TERM.
  • Screen size wrong on a serial console. Serial lines do not report window size; set it with stty rows 24 columns 80 to match your emulator.
  • “File is read only”. Use :w! as root, or check whether the file system is mounted read-only (mount -v | grep " / ") or immutable inside a Solaris 11 immutable zone.
  • “Tmp file too large” or vi cannot start on huge files. Classic vi works through /var/tmp; if it is full or the file is enormous, view it with more/tail, or edit with ed/sed to a new file. Point the temp directory elsewhere with :set directory=/bigfs in EXINIT.
  • Stale recovery files. Old preserved buffers accumulate under /var/preserve and /var/tmp/Ex*; list them with vi -r and remove the ones you do not need.
  • ^M at the end of every line. The file came from Windows. Check with :set list or cat -v, then convert: dos2unix file.win file.unix, or in vi :%s/Ctrl-VCtrl-M$//. A CR in /etc/vfstab, a script shebang or a crontab line causes baffling failures.
  • Linux vim muscle memory. Classic Solaris vi has no visual mode (v), no multi-level undo or Ctrl-R redo, no syntax highlighting, and no :set paste. Pasting with autoindent on stair-steps text; use :set noai before pasting.
  • vim installed on Solaris 11 but vi is not vim. /usr/bin/vi stays the classic editor. Run vim explicitly or alias it; do not replace /usr/bin/vi, which package updates restore.
  • Sparse-root zones on Solaris 10. /usr is shared read-only from the global zone, so vi and ed are always there, but you cannot add vim inside the zone into /usr; install add-ons in the global zone or under /opt.
  • Separate /usr not mounted in early single-user. On old Solaris 10 layouts with /usr on its own slice, editors under /usr/bin are missing until you mount it (mount /usr). Booting failsafe or from media gives you a miniroot with vi and ed; mount the real root on /a and edit /a/etc/vfstab.

What’s next in the Solaris Admin Series

Next up is basic process management on Solaris 10 and 11: ps -ef, pgrep, pkill, kill signals and nohup. Catch up with part 8, The Solaris PATH Problem, part 7, Solaris Man Pages, part 6, Shells on Solaris 10 and 11, and part 3, Solaris Filesystem Layout Tour.

Official references: vi(1), ex(1), ed(1), terminfo(5), tput(1), infocmp(1), crontab(1) and pfedit(8) in the Oracle Solaris 11.4 Reference Library, and vi(1), ed(1), terminfo(4) and crontab(1) in the Oracle Solaris 10 1/13 Information Library.

Leave a Reply

Your email address will not be published. Required fields are marked *