How to enable ksh command history between sessions

14,757

Solution 1

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

Solution 2

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). ^_^

Solution 3

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

Share:
14,757

Related videos on Youtube

Niklas Rosencrantz
Author by

Niklas Rosencrantz

Updated on September 18, 2022

Comments

  • Niklas Rosencrantz
    Niklas Rosencrantz almost 2 years

    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?

  • Niklas Rosencrantz
    Niklas Rosencrantz almost 7 years
    It is not working. Not even if I explicitly create the file and set the env variable.
  • Kusalananda
    Kusalananda almost 7 years
    @DjDac I can't say much more without knowing what ksh implementation you are using and what the steps you are taking are.
  • Niklas Rosencrantz
    Niklas Rosencrantz almost 7 years
    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.
  • Kusalananda
    Kusalananda almost 7 years
    @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
    Kusalananda almost 7 years
    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).
  • thecarpy
    thecarpy almost 7 years
    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!
  • Kusalananda
    Kusalananda almost 7 years
    .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.
  • thecarpy
    thecarpy almost 7 years
    "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 ...
  • Kusalananda
    Kusalananda almost 7 years
    @thecarpy Not if you specify separate history files for separate shell implementations.
  • thecarpy
    thecarpy almost 7 years
    Yeah. like this: HISTORY=~/$(ps -p $$ | awk '$1 != "PID" {print $(NF)}')_history -- better use .bashrc and .mkshrc, respectively, imho. Only trying to help ;-)
  • Kusalananda
    Kusalananda almost 7 years
    @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.
  • thecarpy
    thecarpy almost 7 years
    ${SHELL##*/} ? What happens if login shell is, say bash, and I call ksh from that or vice-versa ?
  • Kusalananda
    Kusalananda almost 7 years
    @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).
  • thecarpy
    thecarpy almost 7 years
    Upvoted, but it would have been a worthy mention, imho!
  • mirabilos
    mirabilos almost 7 years
    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
    mirabilos almost 7 years
    This post is full of technical mistakes. pdksh does not use ~/.mkshrc, the accent gravis is also parsed during sourcing the file, etc.
  • thecarpy
    thecarpy almost 7 years
    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 ...
  • roaima
    roaima almost 6 years
    Hello FanDeLaU. How does this help to save the history across sessions?
  • roaima
    roaima over 5 years
    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?