top | item 6221879

Web server in one line of bash

180 points| mikegirouard | 12 years ago |razvantudorica.com | reply

63 comments

order
[+] WestCoastJustin|12 years ago|reply
If you have python, then these are really useful, just serves up the current directory.

  Python 2.x:
  python -m SimpleHTTPServer

  Python 3.x:
  python -m http.server 8000
[+] gmac|12 years ago|reply
Or for https (e.g. when developing for Chrome's speech recognition API):

    twistd --nodaemon web --path=. -c snakeoil.crt -k snakeoil.key --https=8443
And to generate a 100-year localhost key/cert for use with this:

    openssl genrsa -passout pass:dummy -out snakeoil.secure.key 1024
    openssl rsa -passin pass:dummy -in snakeoil.secure.key -out snakeoil.key
    openssl req -new -subj "/commonName=localhost" -key snakeoil.key -out snakeoil.csr
    openssl x509 -req -days 36500 -in snakeoil.csr -signkey snakeoil.key -out snakeoil.crt
[+] sprobertson|12 years ago|reply
Easier to remember, plus Python is probably more likely to exist on a given machine than netcat.
[+] mikegirouard|12 years ago|reply
This is still my go-to solution, though I couldn't help but to share when I found the other solution.
[+] tga|12 years ago|reply
Since everyone uses the one line of bash to just start their favourite complex network utility, I'll also contribute mine:

while true; sudo /usr/sbin/apachectl start; break; done;

[+] tga|12 years ago|reply
And, for the sake of accuracy, the proper bash syntax would be:

  while true; do sudo /usr/sbin/apachectl start; break; done;
[+] jiggy2011|12 years ago|reply
I came to this thread to post the exact same joke.
[+] knome|12 years ago|reply
> As root you can run:

Unless the specified 'index.html' is only readable by root, you don't have to be root to run that.

Only the low ports are restricted from regular users.

[+] anakron|12 years ago|reply
We've used a similar trick to copy files between coworkers:

  on server: while true; nc -l $PORT < $FILE; done
  on client: nc $SERVER $PORT > $FILE
Quick, simple and easy to fire up. You can continue to hack on the file and nc will serve up the latest saved version.
[+] gamegoblin|12 years ago|reply
Is your while loop missing a "do" statement, or am I missing something?
[+] raldi|12 years ago|reply
That's not a one-line script. That's a multi-line script with the linebreaks removed.
[+] jlgreco|12 years ago|reply
I suggest you don't say things like that around Perl programmers.
[+] mrhazel|12 years ago|reply
It is 85 characters long. Strip some spaces from it, and it qualifies as a one-liner.
[+] lambda|12 years ago|reply
socat version; no loop, as it forks a separate process for each connection:

    socat TCP-LISTEN:8080,fork,crnl SYSTEM:'printf \"HTTP/1.1 200 OK\\n\\n\"\; cat test.html'
The extra quoting you need to do the the SYSTEM argument makes this rather cumbersome. socat is a powerful tool, but can sometimes be a pain to use.

Here's one use I found for it recently, when I wanted to do some experimentation with multicast:

    socat - UDP-DATAGRAM:239.255.1.1:4242,ip-add-membership=239.255.1.1:10.0.0.10,ip-multicast-loop=0,bind=:4242
This causes socat to bind to the multicast group 239.255.1.1 on the interface that has the unicast IP 10.0.0.10, sending and receiving on port 4242 over UDP, reading from stdin and writing to stdout. It basically gives you a simple chat service over the local network.
[+] hyperair|12 years ago|reply
$ busybox httpd

Works even in an initramfs, and in some embedded systems. Serves up the current directory, and you can even have CGI scripts in cgi-bin.

[+] mcpherrinm|12 years ago|reply
Woah, I didn't realize busybox had an httpd. Truly a sweet piece of software.
[+] voltagex_|12 years ago|reply
Thanks! I'd forgotten about busybox, but that's often how your home router is doing things.

* Side note: if it is, make sure your router manufacturer provides the GPL source release.

[+] kokey|12 years ago|reply
I remember trying to write a web server that can respond to requests in bash, several years ago. Since it didn't have sockets support that part was going to be handled by netcat. The problem I ended up with was that bash couldn't read and write to the same pipe. The mkfifo solution was the closest that I got to. It turns out that ksh was perfectly capable of reading and writing to the same pipe at that stage. Not long after I got stuck with bash, awk started to support sockets so I used that. Then bash started to support sockets, and many more features, so I suspect it's possible to write a solution in bash now that doesn't need netcat, but might still need a fifo.
[+] fooyc|12 years ago|reply
Nice. However:

    $ curl localhost:8080 & curl localhost:8080
    <!doctype html>
    [...]
    curl: (7) Failed connect to localhost:8080; Connection refused
Yes, the server "restarts" after each request, and during the restart, it's not listening.

That's not what I would call a "server".

[+] theone|12 years ago|reply
If you have node-static installed.

  npm install -g node-static
  # serve up the current directory
  $ static
  serving "." at http://127.0.0.1:8080
More at https://github.com/cloudhead/node-static
[+] adduc|12 years ago|reply
Similarly, if PHP 5.4 (or greater) is installed:

    php -S 127.0.0.1:8080
[+] amitamb|12 years ago|reply
Since nobody mentioned ruby version

ruby -run -e httpd . -p 5000

[+] thefox|12 years ago|reply
On Debian 7.0 (Wheezy) argument "-l 8080" without "-p" causes netcat (v1.10-40) to listen on a random port. I must run "nc -l -p 8080" to listen at 8080.
[+] gcmalloc|12 years ago|reply
Adding my two cent:

    twistd web --path . --port 8080