geoffeg has asked for the wisdom of the Perl Monks concerning the following question:

I'm looking for a way to persist a unix application across web (CGI) requests. I have an interactive command line app that I'm wrapping with IPC::Run. I need to start a new instance of the command line app via the web and then access that allready running app via later requests. I have no idea where to start in this. Help!? :)

Replies are listed 'Best First'.
Re: Persist shell app
by bart (Canon) on Apr 02, 2004 at 14:33 UTC
    Perhaps you could use something based on HTTP::Daemon. merlyn has a few excellent articles on his web site doing something similar using Chatbot::Eliza. Check out the articles with a title like "Doctor is IN", namely Column 23 and Column 24.

    The idea is that you have one script that starts out as a CGI, which contains the actual state, and which launches its own small webserver — and keeps running in the background. That one takes over for this session, processing all following requests from the browser, and all in the context of the current application.

Re: Persist shell app
by EdwardG (Vicar) on Apr 02, 2004 at 14:57 UTC

    Remember that the World Wide Web is intrinsically stateless (See What is stateless?), and this means that "trying to persist an application across web requests" is going against the grain from the outset.

    It might be conceptually easier to think of your "persistent" application in client-server terms, where you interact with your application (server) using a web browser (client) to communicate messages. For example, your server application could respond to client "messages" that are queued in a file, taking action when it encounters new messages.

    On the other hand, if you really want to persist with persistence <grin> then there are various options such as cookies (client side persistence) or CGI::persistent (server side persistence).

    Good luck, and let us know what you decide.

Re: Persist shell app
by bbfu (Curate) on Apr 02, 2004 at 14:58 UTC

    Alternatively, you could create a wrapper for the unix application that runs in the background. Your CGI program would then simply forward requests to the unix application via the wrapper, using a unix domain socket, named pipe, or other such bi-directional IPC mechanism, and the wrapper would forward back any replies over the same IPC channel.

    Black flowers blossom
    Fearless on my breath

Re: Persist shell app
by mvc (Scribe) on Apr 02, 2004 at 19:25 UTC

    mod_perl2 can be easily configured to give you a new Perl interpreter per each session, one which will die when the session expires.

    Thus you get the same interpreter for all requests in the same session. A session is identified by an HTTP connection, and it only works if you can use KeepAlive On.

    Just store all your filehandles/sockets/and other non-serializable stuff in variables, and use them when you get a request. Same as you would in any command line app.

    The fact that the web is 'stateless' does not mean you cannot create stateful things on top of it. It is just more difficult.

Re: Persist shell app
by tachyon (Chancellor) on Apr 02, 2004 at 16:37 UTC

    Yet another approach is to whip up an XS interface to your ? C based unix application and use mod_perl to create a persistent instance as you might do with a DB connection. See Swish::API for a typical example used as the interface to the swish-e search engine to avoid forking new instances. This is almost certainly the most complex solution and would probably only be worthwhile if speed is a major issue.



Re: Persist shell app
by Anonymous Monk on Apr 02, 2004 at 16:08 UTC
    I would write a socket server around the running instance of the application, and have my CGIs connect to that socket server on each request.

    Managing which socket the CGI should connect to could be done through sessions/cookies/etc, so the problem just becomes one of killing off abandoned application instances.

Re: Persist shell app
by z3d (Scribe) on Apr 02, 2004 at 18:13 UTC
    Pretty sure IO::Socket::Unix (depending on your platform of course) would allow you to cleanly pass info between the two.

    "I have never written bad code. There are merely unanticipated features."