Skip to Content.
Sympa Menu

grouper-dev - [grouper-dev] GSH readline support on *NIX

Subject: Grouper Developers Forum

List archive

[grouper-dev] GSH readline support on *NIX

Chronological Thread 
  • From: Carl Waldbieser <>
  • To:
  • Subject: [grouper-dev] GSH readline support on *NIX
  • Date: Thu, 28 Aug 2014 22:32:00 -0400

I've just started experimenting with Grouper.  I used the Grouper installer and have started watching the various admin tutorials.

One thing I noticed right away is that the `gsh` shell seems to be a bit lacking in interactive mode.  There is no command history, nor can I use the arrow keys to move on the command line and make edits.

I am guessing something like rlwrap would work to add readline support to this command on man Linux environments.  The server I am testing on is RHEL6, and didn't have that package, so I put together a quick Python script that does the same thing.

I have attached the script as ''.  You basically put it in the same folder as gsh and you run "$GROUPER_HOME/bin/" instead of gsh.  Almost magically, you will have command line history and the use of arrow keys (if your system Python has readline support).

It is a bit dodgy about overwriting the prompts if you scroll through the history to a blank line, but I find the benefits outweigh this issue, at least until gsh grows its own readline support (hopefully with tab-completion?).

Carl Waldbieser
System Programmer
Lafayette College

#! /usr/bin/env python

import cmd
import os
import os.path
import pty
import re
import sys
from threading  import Thread

class MyCmd(cmd.Cmd):
    def __init__(self):
        self.prompt = ""
        pid, fd = pty.fork()
        if pid == 0:
            pth = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'gsh')
            sys_shell = os.environ.get("SHELL", '/bin/sh')
            os.execl(sys_shell, sys_shell, pth)
            self.child_pid = pid
            self.pty_fd = fd
            t = Thread(target=self.printer)
            t.daemon = True

    def printer(self):
        pat = re.compile(r"^gsh \d+%")
        stdout = sys.stdout
        fd = self.pty_fd
        lines = []
        leading = ''
        while True:
            chunk =, 1024)
            if chunk != "":
                lines.extend(("%s%s" % (leading, chunk)).split('\n'))
                leading = ''

            line_count = len(lines)
            while line_count > 0:
                line = lines[0]
                lines = lines[1:]
                line_count -= 1
                if line_count > 0:
                    m =
                    if m is None:
                        leading = line

    def do_EOF(self, line):
        return True

    def do_help(self, line):
        self.default('help%s' % line)

    def emptyline(self):

    def default(self, line):
        fd = self.pty_fd
        os.write(fd, line + '\n')

def my_repl():
    cmd = MyCmd()

if __name__ == "__main__":

Archive powered by MHonArc 2.6.16.

Top of Page