diff --git a/mininet/cli.py b/mininet/cli.py
index 23aaac5ef954fd70611a30474ba3187e027aeb7c..a8c93bee9ef0760f72e53847e182df193e0f9bb8 100644
--- a/mininet/cli.py
+++ b/mininet/cli.py
@@ -45,6 +45,10 @@ class CLI( Cmd ):
     prompt = 'mininet> '
 
     def __init__( self, mininet, stdin=sys.stdin, script=None ):
+        """Start and run interactive or batch mode CLI
+           mininet: Mininet network object
+           stdin: standard input for CLI
+           script: script to run in batch mode"""
         self.mn = mininet
         # Local variable bindings for py command
         self.locals = { 'net': mininet }
@@ -56,7 +60,21 @@ def __init__( self, mininet, stdin=sys.stdin, script=None ):
         Cmd.__init__( self )
         info( '*** Starting CLI:\n' )
 
-        # Set up history if readline is available
+        if self.inputFile:
+            self.do_source( self.inputFile )
+            return
+
+        self.initReadline()
+        self.run()
+
+    readlineInited = False
+    @classmethod
+    def initReadline( cls ):
+        "Set up history if readline is available"
+        # Only set up readline once to prevent multiplying the history file
+        if cls.readlineInited:
+            return
+        cls.readlineInited = True
         try:
             import readline
         except ImportError:
@@ -67,22 +85,26 @@ def __init__( self, mininet, stdin=sys.stdin, script=None ):
                 readline.read_history_file(history_path)
             atexit.register(lambda: readline.write_history_file(history_path))
 
-        if self.inputFile:
-            self.do_source( self.inputFile )
-            return
+    def run( self ):
+        "Run our cmdloop(), catching KeyboardInterrupt"
         while True:
             try:
                 # Make sure no nodes are still waiting
                 for node in self.mn.values():
                     while node.waiting:
+                        info( 'stopping', node, '\n' )
                         node.sendInt()
                         node.waitOutput()
                 if self.isatty():
-                    quietRun( 'stty echo sane intr "^C"' )
+                    quietRun( 'stty echo sane intr ^C' )
                 self.cmdloop()
                 break
             except KeyboardInterrupt:
-                output( '\nInterrupt\n' )
+                # Output a message - unless it's also interrupted
+                try:
+                    output( '\nInterrupt\n' )
+                except:
+                    pass
 
     def emptyline( self ):
         "Don't repeat last command when you hit return."