MirBSD Korn shell, or mksh, is a Free command interpreter (shell) intended for both interactive and shell script use. `mksh` is the default shell on Android, some BSDs and some Embedded Linux distributions, and it is available for most other operating systems. Please use the “ksh” tag for generic Korn Shell questions, and the “mksh” tag (additionally) if your question targets mksh specifically.
About mksh
MirBSD Korn shell, or mksh
, is a command interpreter (shell) intended for both interactive and shell script use. Its command language is a superset of the Bourne/POSIX shell (sh
) language and largely compatible to the original Korn shell (ksh88).
The MirBSD Korn Shell aims at being a compact, consistent, fast, not bloated but also nice to use, shell both for interactive and script use. While some advanced features of other shells (such as programmable/configurable tab completion) are not available, and some design choices have been made to keep it small, many features of other contemporary Unix shells (GNU bash
, AT&T ksh93
, and zsh
) are available; mksh aims at providing the same features on every system it runs on, if at all possible, to aid people trying to script portably (but willing to require a specific shell).
mksh
is OSI approved Open Source Software™ and the actively developed successor to pdksh
and the default shell on Android, some BSD variants, and some (mostly Embedded) Linux distributions. It is also available for most other operating systems and distributions.
External Links
- Home page
- Manual page – PDF – lksh manpage
FAQ
POSIX
mksh is actively developed, as is the POSIX standard; when something in the latter changes, mksh is usually adjusted to match, independent on which version of the standard is currently published.
Because mksh is developed as portable shell, as opposed to integrated within one operating systems, its mission was decided to behave consistent across operating systems (so shell scripts can expect a consistent runtime behaviour), even ignoring POSIX when needed to achieve this. As an example, arithmetics – echo $((2147483647 + 1))
– always use 32-bit integers and define how overflow is handled.
In places where POSIX differs, there are two “knobs” to bring mksh closer to POSIX. One is set -o posix
, which changes some run-time behaviour of the shell (and, as a side effect, turns off brace expansion by default). The other is to use the lksh
binary which most distribution packaging of mksh should offer, instead of the mksh
binary; in lksh
, arithmetics are done POSIX-conformant, i.e. with the host’s C long
data type, and overflow being Undefined Behaviour.
For details on the differences between mksh
and lksh
, and between running without and with set -o posix
, please refer to the manual.
Pipes: a=u; echo x | read a; echo $a
POSIX allows a shell to run both sides of a pipe in a subprocess – making this equivalent to a=u; (echo x) | (read a); echo $a
– or just one. mksh does the former.
If you really need to read out of a pipeline into the current execution environment, you can redesign your program to do things differently, or use a coprocess: a=u; echo x |& read a; echo $a
Process substitution
The GNU bash extension <(command)
is not yet supported natively (although it’s on the TODO list). For now, this answer has a workaround.
Locales (POSIX)
Because mksh is developed independent of any widespread operating system and portable to many weird and/or ancient ones, we cannot use the OS’ locale functions. mksh implements the C
(POSIX) locale, and a “UTF-8” locale. Which one is active is, currently, independent of the POSIX locale parameters but selected with set ±U
(set ±o utf8-mode
); this will eventually change.
To make mksh (or lksh) use UTF-8 mode if the current POSIX locale is UTF-8, and C
mode otherwise, use: set -U; [[ ${LC_ALL:-${LC_CTYPE:-${LANG:-}}} = *[Uu][Tt][Ff]?(-)8* ]] || set +U
If you need to integrate this into an sh
script, run that code only if the script is being run by mksh
or lksh
:
case ${KSH_VERSION:-} in
*MIRBSD KSH*|*LEGACY KSH*)
case ${LC_ALL:-${LC_CTYPE:-${LANG:-}}} in
*[Uu][Tt][Ff]8*|*[Uu][Tt][Ff]-8*) set -U ;;
*) set +U ;;
esac ;;
esac
In near future, mksh will track those environment variables itself though.
Octal integers (POSIX)
POSIX has changed to require integers with a leading 0
to be interpreted as octal digits; this breaks scripts left and right. mksh supports either:
$ echo 1: $((010)); set -o posix; echo 2: $((010))
1: 10
2: 8
Command line history
Persistent history is disabled by default, for privacy reasons. To enable it, set HISTFILE
to the path of a pdksh-style (binary) history file. Do not use a bash-style (ASCII) history file, as it would be overwritten and corrupted. You may also wish to set HISTSIZE
, but not to insanely high values, as the memory is preallocated. You can put this into ~/.mkshrc
:
export HISTFILE=~/.pdksh_history HISTSIZE=65536
The persistent history file is shared between parallel shell sessions; synchronisation happens on pressing Enter after a command.
Some mksh
binaries are not compiled with support for persistent history, e.g. Android’s (because of the phone-specific environment) or for operating systems without mmap
. It will simply not create the file then.
AT&T Korn Shell compatibility notes
Similar to ksh93, functions defined with the function
keyword, as opposed to the name()
syntax, have their own shell flags (in recent versions); this means you can e.g. toggle UTF-8 mode inside the function, and it’s restored upon leaving it.
Unlike ksh93, however, local
variables work in both kinds of functions, and mksh (like all other nōn-AT&T-ksh shells) uses a nested scoping model (meaning local variables of the caller are available to the callee). nameref
s are implemented slightly differently: they resolve to the target each time they are invoked/used, not at definition time, so they can refer to the function’s own local variables if not careful.
The DEBUG
trap and handling of the ERR
and EXIT
traps in functions (from ksh88) are not implemented yet; floating-point handling will not be implemented. Several post-1993 ksh93 extensions are not implemented yet, some will eventually be.
Associative arrays
… are on the to-be-implemented list. mksh/assockit.ksh
in the “shellsnippets” repository contains a currently-usable (if occasionally a tad slow) workaround by means of shell functions; mksh/assoldap.ksh
is a good usage example (LDAP bindings for shell).
When invoked as /bin/sh
…
… on some operating systems (e.g. MidnightBSD, Debian), a compatibility mode is invoked. This involves turning on set -o posix
(better POSIX compatibility), set -o sh
(legacy script quirks), or both. This can change the behaviour.
Reporting bugs, mailing list, further resources
The IRC channel #!/bin/mksh
on the IRC network Freenode is where you can ask questions, report bugs, etc. – there’s usually some volunteer/user around, and the developers read the backlog most of the time. You can also ask in #ksh
(Infopage) if you indicate you’re using mksh. There’s also a mailing list (see the bottom of the manpage) which you can read online, e.g. via GMane.
Since many people learn programming by looking at others’ code, the Shell-Toolkit (shellsnippets) project aims at collecting some. More resources are found in the #ksh
infopage.