At work we had a situation where we needed developers to be able to run a preset number of jobs, to maintain the development-instances we have of some products. We didn't want to give them shell access, so instead I wrote a small node.js-based web-server that they can access, select a job, and run it. The source code is at github if you want to peek.
The cool bits
The cool bits in this is the use of socket.io, or at least that is the cool bit for me, since I have been wanting to play with web sockets or something like it for a while.
What I loved about socket.io was how easy it made it. For me it sort of removed the seperation between client and server. Fire events on the server, listen for them on the client. I use the custom event stuff, not only send packages, because, lets face it, why not when it's there? :)
The main part of the website is a console-window, where the output of any running process shows up, live, to all users on the web-page. Each instance of dev-admin is only allowed to run one script at a time, so it also locks the form-controls, stopping people from running more jobs while one is running.
We wanted the system to be flexible, so what I ended up with was something that could handle groups of scripts, and even let you present forms via the web frontend to configure those scripts. Our concrete need was drupal, so the scripts that is in the repo now as examples are all based around drupal and drush.
In nodejs I spawn a bash process and talk to it via
STDIN (no kiddin', I do :p). The first hurdle was that the output didn't look very good. All input would be sent at once, and then all the output would appear as it was running. Not very satisfactory for debugging jobs, I can tell you that much.
The decission was that ordering was more important than complex scripts, so we went with one line, one statement. What we do then is we output another command (hidden from the user interface) that will send a special sequence on
STDOUT once the command is finished. We then look for this sequence before issuing the next command and so on.
The result? pretty output, yay!
Once the process is done, the border changes color, depending on success or failure (If one of the commands in the script fail, we also exit imideatly). Here is an example of success!