Enable vi Command-Line Editing in ksh for Oracle DBA Shells
Enable vi Command-Line Editing in ksh for Oracle DBA Shells
Purpose
Recalling and editing the prior command without retyping it is the single most-used operation in a long DBA shift on an Oracle host. On the Korn shell (ksh) — the default login shell on AIX 7.x, Solaris 11, HP-UX 11i, and many older Oracle 11g/12c reference builds — that operation is gated behind one line in .profile: set -o vi. Without it, the up-arrow key prints a literal escape sequence and the only way to repeat a long RMAN BACKUP DATABASE PLUS ARCHIVELOG ... invocation is to type it again.
With vi-mode enabled, the shell treats the command line as a single-line vi buffer. Press Esc to leave insert mode, then k to walk backward through history, /pattern to incremental-search a previous command, b/w/e to jump words, x/dd/cw to delete, and i/a to re-enter insert mode and edit. The keystroke vocabulary is identical to vi proper, so the muscle memory carries from script editing to command-line recall.
The same one-liner works on pdksh, mksh, and ksh93 — the variants installed across the major commercial UNIX distributions Oracle still supports. Bash also honours set -o vi, so the snippet ports unchanged to Oracle Linux and RHEL shells once a DBA's hands are trained on it.
Code
1# Add to ~/.profile for the oracle user on AIX/Solaris/HP-UX
2set -o vi
3
4# Optional: remap arrow keys to history/cursor motions while in insert mode
5alias __A=$'\020' # up arrow -> Ctrl-P (previous history)
6alias __B=$'\016' # down arrow -> Ctrl-N (next history)
7alias __C=$'\006' # right arrow -> Ctrl-F (forward char)
8alias __D=$'\002' # left arrow -> Ctrl-B (back char)
9
10# Optional: enable completion on Esc-\ in ksh93 (vi-esccomplete equivalent)
11# ksh93 supports this natively; older ksh88 does not.
12set -o vi-esccomplete 2>/dev/null
1# Verify vi-mode is active in the current shell
2set -o | grep -i vi
3# Expected output:
4# vi on
5# vi-esccomplete on (ksh93 only)
Code Breakdown
set -o vi
Switches the shell's line editor from the default emacs mode (or no-edit mode on bare ksh88) to vi mode. The change takes effect immediately for the current shell; place it in .profile so every new login picks it up. No reverse toggle is required between sessions — sourcing .profile again is idempotent.
Arrow-key remap aliases (alias __A, __B, __C, __D)
In vi-mode, the arrow keys are intercepted as raw escape sequences (Esc[A, Esc[B, etc.) and the shell does not bind them to history motion by default. The four alias lines map the escape-sequence terminators to the control-key equivalents: Ctrl-P for previous-history, Ctrl-N for next-history, Ctrl-F and Ctrl-B for cursor motion. This lets the DBA navigate without dropping to Esc first, while still keeping all the vi command-mode editing keys available after Esc.
set -o vi-esccomplete
ksh93 supports completion-on-Esc-backslash (a vi-mode analogue of Tab completion in emacs-mode). The 2>/dev/null swallows the "bad option" error on ksh88 hosts, keeping a single .profile portable across both ksh dialects.
Key Points
- Default shell matters. AIX, Solaris, and HP-UX ship
kshas the default for theoracleuser; Oracle Linux and RHEL shipbash. Both honourset -o vi, but the surrounding.profileversus.bash_profilefilename differs. Set both if you want one recipe to cover every host. - Vi-mode is non-modal at first keystroke. A new line starts in insert mode, which is what makes the shell usable without thinking about vi at all. The
Esckey flips into command mode, which is when history navigation and editing operators become available. - History size is independent of vi-mode. Set
HISTSIZE=1000andHISTFILE=~/.sh_historyin.profileto make sure there is actually a history to navigate. The defaultHISTSIZEon commercial UNIX is often only 128 entries. set -o emacsis the only other option. There is no "off." Removingset -o vifrom.profilereverts to whatever the shell's default is — usually emacs-mode on Linux/bash, no editing on bare ksh88. Make the choice explicit either way.bind -mfor bash-only remaps. The arrow-key alias trick above is a ksh idiom. On bash, preferbind '"\e[A": previous-history'in.bashrc. Mixing the two is harmless but a single.profilereads cleaner.
Insights and Best Practices
Pair with HISTFILE and HISTSIZE for real session recall
vi-mode without a sized history is a bicycle without wheels. Add to .profile:
1export HISTFILE=~/.sh_history
2export HISTSIZE=1000
This persists the last 1000 commands across sessions, so the morning DBA can find what the on-call DBA did overnight by tabbing through history rather than checking the audit log.
Use /pattern to search backward, not k to spin
Esc then /restore walks backward to the first command containing the string restore. n jumps to the next older match, N jumps newer. This is dramatically faster than tapping k 80 times to find the last RMAN RESTORE invocation from yesterday.
Reach for fc for the multi-line case
set -o vi is single-line editing. When a previous command was a multi-line PL/SQL block submitted via heredoc, vi-mode collapses it into one line on recall — usually unreadable. The fc built-in opens the previous command in $EDITOR (vi by default) for full multi-line editing:
1fc # open the previous command in vi
2fc 245 # open history entry 245
3fc -l 240 250 # list history entries 240-250 without editing
fc is included in every ksh and bash and is the right tool when vi-mode runs out of room.
Standardise the recipe across the DBA team
A one-line set -o vi is easy to add, easy to forget, and easy to lose when a new oracle user is created from a default skeleton. Bake the snippet into the team's .profile template in source control alongside the rest of the Oracle environment exports (ORACLE_BASE, ORACLE_HOME, PATH). Every DBA gets the same shell behaviour on every host on day one.
When to Run This
- During initial setup of a new
oracleOS user on AIX, Solaris, HP-UX, or Oracle Linux - When inheriting a host where the previous DBA worked in emacs-mode and the muscle memory mismatches
- After upgrading from ksh88 to ksh93 (re-test
vi-esccompleteand arrow-key behaviour) - When training a junior DBA who already knows vi and is fighting the shell to recall a long command
- Anywhere
Tab-completion in emacs-mode collides with the team's existing vi workflow
Troubleshooting Common Issues
If set -o vi returns "set: bad option," the shell is sh (Bourne shell), not ksh — common on legacy HP-UX 11.0 boots. Confirm with echo $SHELL and switch the user's login shell via chsh -s /bin/ksh (or /usr/bin/ksh depending on platform).
If arrow keys produce raw escape sequences (^[[A) after set -o vi, the terminal is sending ANSI escapes that vi-mode does not bind by default. Apply the four alias remaps shown above, or accept that history navigation requires Esc-k instead of up-arrow.
If history is empty after every login, HISTFILE is unset or HISTSIZE=0. Export both in .profile and confirm with echo $HISTFILE $HISTSIZE after re-login.
If the prompt feels laggy in vi-mode after pressing Esc, the issue is the escape-timeout interval — the shell is waiting to see whether Esc is the start of an escape sequence (like a remapped arrow key) or a standalone command-mode toggle. Press Esc-Esc to force command mode immediately, or accept the small wait.
References
- Oracle Linux 9 Administrator's Reference Guide — Oracle Linux user-shell configuration including
.profile/.bash_profileprecedence relevant for the oracle OS account - IBM AIX 7.3 Documentation — Korn Shell (ksh) — canonical AIX reference for ksh built-ins, including
set -o vi, history file behaviour, and thefccommand - shutdownabort.com — Miscellaneous Useful UNIX (Wayback, 2013-01-15) — original source of the
set -o viand arrow-key alias recipe in the DBA Quick Guides corpus - oracle-base.com — Linux Articles — Tim Hall's reference set covering shell environment setup for DBAs on Linux, with patterns equally applicable to ksh on commercial UNIX
Posts in this series
- List Files Opened by an Oracle Process with lsof -p
- Delete the 500 Oldest Files in a Directory (Oracle DBA)
- Diagnose Oracle Net and RAC Interconnect Routing with netstat -r
- Unpacking Oracle Patch and Install Media with cpio
- Oracle Export Through a Named Pipe with mknod for Space-Constrained Hosts
- Recursive find and grep to Search Oracle Trace Files for Any String
- Find the Biggest Files First When an Oracle Filesystem Fills Up
- Scan Every Oracle Alert and Trace Log for ORA- Errors with grep
- vi Editor Commands Reference for Oracle DBAs
- Disable vi Autoindent Before Pasting SQL Scripts on Oracle Hosts
- Enable vi Command-Line Editing in ksh for Oracle DBA Shells
- Search UNIX Man Pages for Oracle DBA Tools with man -k