
Turn any application that uses stdin/stdout into a WebSocket server - adito
https://github.com/joewalnes/websocketd
======
xxchan
Amazing how the old is new again. Welcome back, CGI! I hope everyone's aware
that this is just a toy and should never be used to do any real work, because
most command line tools were never written to be exposed to the internet at
large.

~~~
baq
caveat: real work != internet. cgi is still very useful for those super small
internal one-shot scripts.

~~~
danieldk
Well, for some folks it works fine on the internet as well:

[http://www.mail-archive.com/fossil-users@lists.fossil-
scm.or...](http://www.mail-archive.com/fossil-users@lists.fossil-
scm.org/msg02065.html)

tl;dr: sqlite.org and fossil-scm.org run using a simple HTTP server via inetd
and some parts of the website are CGI scripts. In 2010 they served over a
quarter million requests per day on a tiny VPS with only 3% CPU load.

~~~
mikeash
I run my entire web site on CGI scripts invoked by Apache. I really don't get
the hate for it. It's extremely convenient and works great.

~~~
ajbetteridge
Same here. And to get the flame bait machine started, we even do it in Perl!

------
joewalnes
Author here.

If you use this on top of programs like bash, well ermm, you get what you
deserve ;).

Here's an example of how I used websocketd to create a little dashboard for
monitoring Linux CPU/memory/IO stats. It basically uses websocketd to stream
the output of vmstat to a web-page that plots the numbers:
[https://github.com/joewalnes/web-vmstats](https://github.com/joewalnes/web-
vmstats)

Other useful examples: tailing log files, executing long running job and
monitoring output, or interactive querying of datasets that require a long
running 'cursor'.

This is not for everyone or everything. Remember that like CGI, a process is
forked for each connection so it's not the kind of thing if you want to handle
a million concurrent connections on a single server.

However for dashboards, admin tools, quick mashups, visualizations, etc - it's
a pretty handy tool.

~~~
tlrobinson
You should probably include a warning anyway. When I was starting out
programming I would do stuff like exec-ing shell scripts from PHP, oblivious
to the consequences.

------
tlrobinson
Basically the same thing in Node.coffee, just because:

    
    
        { Server } = require 'ws'
        { spawn } = require 'child_process'
    
        command = process.argv[2]
        args = process.argv[3..]
    
        wss = new Server port: 8080
        wss.on 'connection', (ws) ->
          ps = spawn command, args
          ps.stdout.on 'data', (data) -> ws.send data.toString()
          ws.on 'message', (data) -> ps.stdin.write data.toString()
          ws.on 'close', -> ps.kill()
          ps.on 'close', -> ws.close()
    

(Needs a bit more error handling)

~~~
pmelendez
Sorry if the question is too basic (I don't code in Node.js) but where is the
websocket handshaking and the envelop management on this?

~~~
CGamesPlay
Creating a new server will start listening for connections, and the connection
event will only be emitted after the handshake has finished.
[http://socket.io/](http://socket.io/) has more info on how the node api
works.

    
    
        wss = new Server port: 8080
        wss.on 'connection', (ws) ->

------
gren

        websocketd --port=8080 bash
    

Then in the browser console:

    
    
        ws.send("ls")
    

I just ported bash to the web :)

~~~
mrspeaker
Ha ha! That's so cool. Hey, off topic... what's your IP? ;)

~~~
huhtenberg
Don't know his, but I've got the best one 127.123.234.345!

------
babby
For some stupid reason I hadn't considered that logging stdin/out/err to a web
interface for my node.js web apps via websockets. To think, I made a browser-
side web IRC interface, and didn't consider this. It would be so useful for my
clients, who don't know how, or find it too archaic to ssh in.

To just open up the admin area and see what's going on, provided they're
indeed full-permission admins. Then, to actually send input from said
interface, that could make ssh'ing into the server something one need not do
often beyond initially setting up the app.

Thanks for the idea. Assuming we're not running as root, and the admin side of
things is secure, am I not considering any critical pitfalls of this approach?
Also, any frameworky cmsy thingers that already do this? Is this new, am I a
unique snowflake?

~~~
X4
yup new, but use a restricted jailed and chrooted shell. Ask your #sysadmin of
choice =) You can even build a REST like API wrapper for this. That's what I
was going to do.

~~~
babby
Yeah, I thought the same thing concerning the REST api, after mulling it over
a bit. Being tied directly to an app could be a bit awkward in practice (Bit
of a problem when either can take either's process down).

------
phaed
This is beautiful. I can think of a dozen use cases for this right now for one
of my pet projects.

~~~
schappim
Call me unimaginative. What uses are you thinking?

~~~
phaed
I run a popular Minecraft server, we have tons of scripts between the mc
server, forum, admin interfaces, and all the other supporting stuff we run.
This makes it so easy to create new functionality that interfaces with our
various scripts. I'm hacking away as we speak.

------
hepek
isn't this reimplementing netcat -e command?

[http://linux.die.net/man/1/ncat](http://linux.die.net/man/1/ncat)

~~~
Sanddancer
Seems more like an inetd to me. Give a command and run it again and again.

~~~
joewalnes
It's similar to netcat -e and inetd, except it also handles the WebSocket
protocol (negotiating the handshake and message framing), so your apps don't
need to.

~~~
sgt
If you're on Ubuntu (and maybe other distros as well), be sure to install the
nc-traditional package. Otherwise you don't get the nifty features such as -e

------
minikomi
Awesome.. I use the same kind of thing to monitor adb output sometimes:

[https://github.com/minikomi/pipesock](https://github.com/minikomi/pipesock)

also in go.

Edit: Doesn't do any receiving, only pipes to a socket what it gets.

~~~
babby
That image made me chuckle. Had to confirm that it was just sourced from
google images; but still. :)

------
ykumar6
Here is a live version [http://runnable.com/UqkIJXqriJwGAATm/basic-count-
example-for...](http://runnable.com/UqkIJXqriJwGAATm/basic-count-example-for-
shell-bash-and-websocketd#)

------
eddywebs
If the shells script takes input parameters can we pass that and eventually
turn it into some kind of web service ?

~~~
joewalnes
I don't recommend any kind of input parsing in a shell script. You're better
of having websocketd fork something like Python, Ruby, Perl, PHP, etc.

Like CGI, websocketd will pass additional URL path and query parameters as
environment variables.

So you could access something like ws://somehost/?a=b and you'd access the
QUERY_STRING environment variable in your script (which contains "a=b").
Virtually every scripting language already has a library for parsing CGI
environment variables so you can do that.

Basically, websocketd tries to emulate CGI as much as possible, but provide
WebSocket streams instead of HTTP responses.

------
schrodinger
anyone getting an HTTPS warning? It's telling me that github.com cert was
signed by an untrusted issuer...

~~~
mappu
Chrome tells me it's valid (signed by DigiCert) with a sha1 thumbprint of ‎d7
12 e9 69 65 dc f2 36 c8 74 c7 03 7d c0 b2 24 a9 3b d2 33.

Check your system time?

------
guard-of-terra
Is this just xinetd for the ignorant?

~~~
X4
no. you can still chain xinetd.

