3

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 even set the $HISTFILE variable and still no history if I start a new shell.

What can I do about it? Is it true that the Korn shell can't remember history between sessions while the bash shell can?

If I like the Korn shell and I want a better and more extensive history, is it possible to use that functionality with ksh?

Jeff Schaller
  • 66,199
  • 35
  • 114
  • 250
Niklas Rosencrantz
  • 4,112
  • 6
  • 36
  • 58
  • 1
    What does the ksh man page have to say about history? – glenn jackman Aug 16 '17 at 03:31
  • @glennjackman Nothing relevant in this case or do you know? – Niklas Rosencrantz Aug 16 '17 at 06:10
  • 3
    Practically the second mention of history in the [mksh Ubuntu manpage](http://manpages.ubuntu.com/manpages/xenial/en/man1/mksh.1.html) is: "**HISTFILE The name of the file used to store command history.**" And you say "nothing relevant"? – muru Aug 16 '17 at 07:17
  • @muru It would be relevant if it said that I must manually create the file before starting the shell. Do I? – Niklas Rosencrantz Aug 16 '17 at 07:18
  • 1
    Uh, what? Who said you must manually create the file? What does that have to do with this question, and why would it affect the relevance of the part I quoted? – muru Aug 16 '17 at 07:21
  • @muru I have absolutely no history if I start ksh or mksh. Therefore something must be done differently. What is it? – Niklas Rosencrantz Aug 16 '17 at 07:21
  • 1
    If that is your actual question, then ask that, while including any shell initialization files involved. Without seeing what settings you have (if any), how do we know? – muru Aug 16 '17 at 07:23
  • @muru I think you can safely assume that I use the default settings i.e. I did no configuration after installing the shell and just started it. I'm amazed that ksh can do almost nothing on Ubuntu. Arrow keys don't even work and ctrl+a and ctrl+e and ctrl+k don't work either. – Niklas Rosencrantz Aug 16 '17 at 07:26
  • I don't know what those shortcuts are supposed to do, but the arrow keys work fine for me. Since you say you set `HISTFILE`, presumably you modified some configuration. – muru Aug 16 '17 at 07:31
  • @DjDac if Ctrl-A also does nothing one of your startup files (`/etc/profile`, `~/.profile`, `${ENV:-~/.mkshrc}`, and anything sourced from there) might be setting “vi” mode, that is, contain `set -o vi` or similar. `mksh` **always** offers “emacs” mode (with Ctrl-A and arrow keys working) by default. -- The mksh maintainer. – mirabilos Aug 26 '17 at 22:47

3 Answers3

7

No, this is not true.

If $HISTFILE is a filename, then the session history will be stored in that file. This is explained in the manual. The number of commands remembered in the shell history is limited by the value of $HISTSIZE.

I believe that the history is flushed to the file after the execution of each command, as opposed to bash that flushes the history to file when the shell session ends. This may depend on which implementation of ksh you are using.

Set HISTFILE to a filename in your ~/.profile file (which is read by login shells), or in the file pointed to by $ENV (which is read by interactive shells and has the default value of $HOME/.kshrc in ksh93). $HISTSIZE is by default 500 or 512 or something thereabouts depending on the implementation of ksh you are using. Neither of these variables need to be exported. The history file does not need to exist before doing this.


In comments you mention that some Emacs movement and command line editing keys do not work. This is because the shell is not in Emacs editing mode. Either set the variable EDITOR (or VISUAL) to emacs or use set -o emacs to enable Emacs command line editing mode. This is also explained in the manual. These variable also do not need to be exported unless you want other programs than the shell to use them.


Summary:

In your $HOME/.profile file:

export ENV="$HOME/.kshrc"

In your $HOME/.kshrc file:

HISTFILE="$HOME/.ksh_history"
HISTSIZE=5000

export VISUAL="emacs"
export EDITOR="$VISUAL"
set -o emacs

This has been thoroughly tested on OpenBSD with both ksh93 and pdksh (which is ksh on OpenBSD). I don't use mksh, but since it's a pdksh derivative, I believe this would work with that shell too.

Note that pdksh and ksh93 (and bash) can not share history file as they have different history formats.

This is usually not a problem if you have separated initialization files for bash and ksh, e.g. .bash_profile and .bashrc for bash and .profile and .kshrc for ksh (with export ENV="$HOME/.kshrc" in .profile). You may further distinguish various ksh implementations by looking at $KSH_VERSION (usually).

Kusalananda
  • 320,670
  • 36
  • 633
  • 936
  • It is not working. Not even if I explicitly create the file and set the env variable. – Niklas Rosencrantz Aug 16 '17 at 07:20
  • @DjDac I can't say much more without knowing what `ksh` implementation you are using and what the steps you are taking are. – Kusalananda Aug 16 '17 at 07:31
  • I have updated the question with more information. I try it with `ksh` and `mksh` from the Ubuntu repositories. I can also try with OpenBSD in a VM with its default `ksh` in the default installation mode. Maybe it is because the shell is in `vi` mode. I'm still trying to learn more shell syntax and its features. I'm used to using the upwards arrow and being able to search my history from ctrl+I but that history is empty if I try ksh but it works with bash. – Niklas Rosencrantz Aug 20 '17 at 14:59
  • @DjDac I updated the answer a couple of days ago, I don't know if you saw it. In particular, note that the history file can't be shared between different shell implementations (i.e. between `ksh` and `bash` for example). – Kusalananda Aug 23 '17 at 14:48
  • "Set HISTFILE to a filename in your `~/.profile` file" <-- make sure, in this case, that you only ever use either bash or ksh on that box or you might get into trouble ... – thecarpy Aug 25 '17 at 08:06
  • @thecarpy Not if you specify separate history files for separate shell implementations. – Kusalananda Aug 25 '17 at 08:09
  • Yeah. like this: `HISTORY=~/$(ps -p $$ | awk '$1 != "PID" {print $(NF)}')_history` -- better use `.bashrc` and `.mkshrc`, respectively, imho. Only trying to help ;-) – thecarpy Aug 25 '17 at 08:11
  • @thecarpy Sure or use `${SHELL##*/}`. I'm presuming that someone who switches between `bash` and `ksh` has `.bash_profile` for `bash` and a `.profile` for `ksh`. – Kusalananda Aug 25 '17 at 08:19
  • `${SHELL##*/}` ? What happens if login shell is, say bash, and I call ksh from that or vice-versa ? – thecarpy Aug 25 '17 at 08:41
  • 1
    @thecarpy It will fail since non-login shells doesn't usually set `$SHELL`. I was thinking explicitly about login shells. I also don't usually switch my interactive shell between `bash` and `ksh` (I only use `bash` non-interactively). – Kusalananda Aug 25 '17 at 08:47
  • Upvoted, but it would have been a worthy mention, imho! – thecarpy Aug 25 '17 at 11:23
  • `mksh` defaults to `emacs` mode independent of `$EDITOR` setting, so you only get unfriendly `vi` mode if you *explicitly* ask for it. Oh, and just install mksh on OpenBSD to validate the answer… – mirabilos Aug 26 '17 at 22:48
1

One moment. KSH, by default, does not accept the arrow keys to iterate through command history.

See this question:

https://stackoverflow.com/questions/1623256/make-arrow-and-delete-keys-work-in-kornshell-command-line

From Tim's answer:

For the arrow keys, you can put this into your the .kshrc file [(pdksh and mksh both use .mkshrc, not .kshrc)] in your home directory:

set -o emacs
alias __A=`echo "\020"`     # up arrow = ^p = back a command
alias __B=`echo "\016"`     # down arrow = ^n = down a command
alias __C=`echo "\006"`     # right arrow = ^f = forward a character
alias __D=`echo "\002"`     # left arrow = ^b = back a character
alias __H=`echo "\001"`     # home = ^a = start of line
alias __Y=`echo "\005"`     # end = ^e = end of line

Note that there are two underscore characters before the letters on the left side of the equal sign. On the right-hand side of the equal, the goal is to get the proper control character assigned to the alias. The way this script does that, is by running the command (via back-tics)

echo "\020"

to get the control-n character assigned to __B.

EDIT (thanks mirabilos): I removed the stuff on backticks while sourcing. I was misled by this:

See https://stackoverflow.com/questions/9449778/what-is-the-benefit-of-using-instead-of-backticks-in-shell-scripts

Make sure your $HISTFILE env variable points to a file and you should be good to go.

I have pdksh, from the man page:

NOTE: if HISTFILE isn't set, no history file is used. This is different from the original Korn shell, which uses $HOME/.sh_history; in future, pdksh may also use a default history file.

For mksh it is the same:

Note: If HISTFILE isn't set, no history file is used. This is different from AT&T UNIX ksh.

Note that my pdksh and my mksh both use $HOME/.mkshrc as .kshrc file. Again, a question of RTFM (man ksh), your implementation might use another. (thanks to Kusalananda for hinting at this).

BTW, you can convert ksh history to bash_history easily, using the strings command, and a sed to tidy up, as follows:

strings <history_file> | sed 's/^[ \t]*//' >> $HOME/bash_history

thecarpy
  • 3,885
  • 1
  • 16
  • 35
  • This may depend on what implementation of `ksh` one is using. All `ksh` shells I've been using accepts the arrow keys as expected in `emacs` mode (and `ksh93` does in `vi` mode too). – Kusalananda Aug 25 '17 at 07:52
  • I only used KSH on Solaris back in the day ... this post was a trip down memory lane, reading mksh and pdksh manuals ... I also quickly installed it on my Linux box to test ... and ... you are right. However, I think `$ ksh $ ^[[A^[[A^[[A^[[A^[[A` hints to the fact it is not working for him. Also, `.mkshrc` is the startup file! – thecarpy Aug 25 '17 at 07:56
  • `.mkshrc` may be the default init file for interactive `mksh` shells, and some implementations of `pdksh` may use that too, but not the `pdksh` on my machine. With `export ENV=somefile` in `.profile` you may explicitly set what init file to use for interactive shells. – Kusalananda Aug 25 '17 at 08:05
  • This post is full of technical mistakes. `pdksh` does __not__ use `~/.mkshrc`, the accent gravis is also parsed during sourcing the file, etc. – mirabilos Aug 26 '17 at 22:49
  • My pdksh does use ~/.mkshrc, as stated. I do instruct to read the local manpage as other implementations might use another. As for the backticks, you are right, I blindly copied a comment from a stackoverflow ... should know better ... – thecarpy Sep 01 '17 at 22:48
1

What I think is happening is that coming from bash you are used to use the arrows to access the history commands. That, AFAIK, is not enabled in KSH (unless you go through loops to make it happen), unless you "set -o vi", in which case you can use vi's cursor movement and text editing keys, ie: < h > left, < j > up, < k > down, < l > right, < i > to insert, < x > to delete a char, < d >< w > to delete a word, etc, more details here With all that said, if you can see command history when running the "history" command, you should be able to browse through the history with the above tip. However, if the "history" command doesn't output anything, that I think would be another issue (a common gotcha is the".sh_history" file ownership and permissions). ^_^

FanDeLaU
  • 139
  • 4
  • Hello FanDeLaU. How does this help to save the history across sessions? – roaima Sep 21 '18 at 21:29
  • That's really useful explanation. Could you add the point about the arrow keys not working, but that history _might_ still be saved, to your Answer? – roaima Sep 27 '18 at 13:11