11
votes

I wish to suspend a REPL session so that I could shut down the system and then at a later time continue to work on the REPL session as if I'd never closed it, i.e. without having to lose all the environment.

I think that the possible solutions to this could be

  1. Snapshot memory, save to file and load env from file later: I think this would be the neatest solution, like happens when you use the 'hibernate' feature of Windows. I've found this heapdump utility which is intended to take a memory snapshot for analysis of memory leaks, but I don't know if you could resurrect the whole environment from that snapshot and I have found no tools that do so.

  2. Save commands and replay them: A major shortcoming of this method is while it works for simple things like var x = "Hello World";, it wouldn't work for things like var reciptId = bankAccount.makePayment(1000); as it will repeat actions on each replay rather than saving the details of the original function call.

  3. Serialize / Deserialize the whole environment: This would involve making a list of all objects that exist in the environment, and then make a mechanism to write each of them to a file i.e. serialize them, and then make a mechanism that deserializes these and loads them when required. I am yet to see a clean way to serialize and deserialize js variables without limitations. I think that the major limitation of this method is its inability to retain references, so the objects loose their class, things would have to be duplicated upon serialization and lose their equality on deserialization - e.g. var f = function (x) {...}; var a = {}; a.f = f; a.f === f? //is true, not true if your serialization mechanism saves a function defn for f and a.f separately and deserializes them separately and cyclic references would probably not work (x = {}; x.cyclic = x;...). So this method, if it ever works would require a lot of dirty work.

So the question really is, how difficult is it to achieve what I wish to achieve? What could be some other solutions to do this? Is there a major obstruction to achieving this which I'm overlooking?

Also, are there any alternatives to the node repl program (like a console in a browser) that can be suspended like this?

Related :

2
Put it in a VM and snapshot/store/revive that. If you want, you can even "remotely" connect to the VM. In any case, I don't believe the solution lies within node, but rather that there's a generic OS utility to put processes into stasis. - Bergi
But won't I loose the VM if I close the computer? Or does snapshotting and reviving mean saving and retrieving from disk? - Peeyush Kushwaha
Yes, a VM can be saved to disk. - Bergi
Might CRIU be an alternative? It is a Linux tool that lets you take a snapshot of a running application/process, save the snapshot to disk, and resume the application/process at a later time. It won't work on Windows and OS X being built on top of Linux. I have not tried it myself, but I know that Tonic, the visual Node REPL on the web, talks about snapshoting running Node REPLs. They compare using the Virtualbox vs CRIU approach. blog.tonicdev.com/2015/09/10/… - Snorre
Great read @Snorre, that article discusses all the three approaches that I listed in my question, the one that Bergi discussed and then one more! Also seems like that their REPL implementation that has the features that I was asking for, though I haven't tried Tonic personally yet. Please form an answer about the CIRU utility, and I'll accept it as it satisfies all the requirements of the question. - Peeyush Kushwaha

2 Answers

4
votes

So if you want to be able to "suspend" a REPL session and then pick up where you left off after a shut down doesn't seem to be directly available in Node.js's REPL. The closest thing to this is the Persistent History feature of the REPL which was added (i think) in Node 4.2.1. This will allow you to view the history of the commands in your REPL in plain text but thats the closest thing available out of the box with Node.

Persistent History

By default, the REPL will persist history between node REPL sessions by saving to a .node_repl_history file in the user's home directory. This can be disabled by setting the environment variable NODE_REPL_HISTORY="".

Previously in Node.js/io.js v2.x, REPL history was controlled by using a NODE_REPL_HISTORY_FILE environment variable, and the history was saved in JSON format. This variable has now been deprecated, and your REPL history will automatically be converted to using plain text. The new file will be saved to either your home directory, or a directory defined by the NODE_REPL_HISTORY variable, as documented below.

Full docs for the REPL module are available here.

However, there is a REPL "wrapper" node module that will do what you're asking. What you can do is, save your REPL history out to a file and then load the history file on the next session and gain access to what you saved to the file in your next REPL session.The module is Nesh. It has a lot of additional features including configuring your shell and evaluating different version of JS such as ES6/ES7 (Using Babel) & Coffeescript.

Install nesh:

npm install -g nesh

Launch nesh in the terminal by simply typing nesh. Work as you normally would within any other REPL session and when you want to save you can type the following in nesh to save your REPL history to the given file:

.save <filepath>

In your next REPL session, even after a shutdown, you can relaunch your nesh session and reload your history by typing:

.load <filepath>

This will re-evaluate the entire history file and will makes any variables or functions available in the current REPL/nesh session.

Hope this is helpful and I think it meets your needs.

-2
votes

What I think you are looking for is how to suspend and resume a process. See this answer on how to suspend and resume a process