Questions tagged [mksh]

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

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). namerefs 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.

13 questions
14
votes
4 answers

Where are zsh and mksh incompatible with bash?

To what extent can other POSIX-compatible shells function as reasonable replacements for bash? They don't need to be true "drop-in" replacements, but close enough to work with most scripts and support the rest with some modification. I want to have…
DanL4096
  • 831
  • 6
  • 16
5
votes
3 answers

What shells support "value substitution" like MirBSD Korn Shell?

On Android (which uses mksh, MirBSD Korn Shell), there's a special syntax of string substitution (called "value substitution"): ${|commands} Instead of collecting output of the commands (as with `` and $()), the substitution result is taken from…
iBug
  • 3,428
  • 1
  • 24
  • 57
5
votes
2 answers

How do you implement process substitution (using a bash script) in a shell that doesn't have it?

I've seen Fish shell implement process substitution as a function: # === Fish shell lang: function psub mkfifo $the_pipe cat >$the_pipe & echo $the_pipe # remove pipe when bg job is done end # Example: diff (echo abc | psub) (echo…
dgo.a
  • 769
  • 1
  • 8
  • 23
3
votes
3 answers

How to enable ksh command history between sessions

If I start ksh or mksh, my upwards arrow does nothing: $ ksh $ ^[[A^[[A^[[A^[[A^[[A But it works with bash if I start bash and press the upwards arrow. $ bash developer@1604:~$ ssh [email protected] -p 2223 I have no history if I start ksh or mksh. I…
Niklas Rosencrantz
  • 4,112
  • 6
  • 36
  • 58
2
votes
1 answer

Get the last executed command line in ksh

Is there a way to get the last executed command possibly together with the arguments within a ksh script? I am using mksh with cygwin. I tried fc -nl -1, but the script throws a "“fc: history functions not available” error. I don't see an equivalent…
user917279
  • 447
  • 1
  • 4
  • 16
2
votes
1 answer

Is it possible to get working history for multi-line commands in mksh, using vi editing mode?

On my Debian systems, I have always used pdksh as my interactive shell. Originally, command-line history behavior was similar to what I grew up with on platforms like AIX and Solaris. Recently, since pdksh on Debian is now implemented by mksh,…
1
vote
1 answer

Variable name completion in ksh

While I am in bash , I am able to do a tab complete with environment variable names, but with ksh I am not able to do so. How can I get it done with KSH? I am using mksh with cygwin.
user917279
  • 447
  • 1
  • 4
  • 16
1
vote
1 answer

When does order matter in redirection?

I've written a script that has a few log outs with printf "..." 1>&2 inside a function. Running that script (build.sh) and I've noticed that if I want to redirect stderr to stdout and stdout to a file[0], success is dependent on order: ./build.sh…
user304684
1
vote
2 answers

Is there a way to localize variables to the current function in `mksh` but not to others?

Is there a way for $val to be set in a () but not be seen by b ()? set -u -e -o pipefail a () { local +x val="myval" echo "in a: VAL= $val" b } b () { echo "in b: VAL= $val" } a Produces: in a: VAL= myval in b: VAL= myval # This should…
dgo.a
  • 769
  • 1
  • 8
  • 23
1
vote
1 answer

How to make mksh for loop go from 1 to N

So I've tried to do this for x in {1..7000} do echo $x done The output is {1..7000} I've also learned that the C-style for loop doesn't work in mksh I've done a bit of googling but mostly there is information about ksh, not mksh So what is the…
Sergiy Kolodyazhnyy
  • 16,187
  • 11
  • 53
  • 104
0
votes
1 answer

Resetting color in end of PS1 resets commands colors in MirBSD KornShell

I have \033[0m color code in the end of my PS1 prompt for resetting, so what I enter won't be colored. But when I used ls I saw that its colors don't work - everything is white. Same for other commands. How to make results colorful?
fluentpwn
  • 19
  • 4
0
votes
1 answer

Is it possible to make mksh use the tilde (~) for home in the PS1?

for example, instead of displaying user@hostname:/home/user in the prompt as per the example in the manpage, could one make mksh display user@hostname:~ ?
pernia
  • 3
  • 2
0
votes
1 answer

mksh complete when moving to parent directory

I just installed the mksh and don't know how to solve one litte problem I have. When trying to change directory to the parent directory mksh does not complete when pressing "tab". Let me visualize: $ cd .."tab" will not end in $ cd ../ What needs…
famfop
  • 136
  • 6