Hacker News new | past | comments | ask | show | jobs | submit login
Web server in one line of bash (razvantudorica.com)
180 points by mikegirouard on Aug 16, 2013 | hide | past | favorite | 63 comments



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


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


Or:

    cat /etc/certs/ssl-cert-snakeoil.pem \
        /etc/priv/ssl-cert-snakeoil.key >> \
        /etc/priv/ssl-cert-and-key-snakeoil.pem
    chmod og-rwx /etc/priv/ssl-cert-and-key-snakeoil.pem
    #note instructions above on how to generate a fresh
    #self-signed cert
    python3 -m http.server 8000 &
    stunnel -p /etc/ssl/private/ssl-cert-and-key-snakeoil.pem -r 8000 -d 4430
Which does require stunnel, in addition to python, obviously.


I can't edit my original comment now, but thought I should add this for cleanup after key/cert generation:

    rm snakeoil.secure.key snakeoil.csr


erm...chrome speech API?!? What exactly are you doing? and how can I do it too?


I'm doing: https://github.com/jawj/pigeonsim (now with speech recognition + geocoding, supporting a beam-me-up gesture).

Web speech API: http://updates.html5rocks.com/2013/01/Voice-Driven-Web-Apps-...


Or if you have PHP, there is an equivalent in 5.4 and above.

http://php.net/manual/en/features.commandline.webserver.php


Easier to remember, plus Python is probably more likely to exist on a given machine than netcat.


This is still my go-to solution, though I couldn't help but to share when I found the other solution.


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;


And, for the sake of accuracy, the proper bash syntax would be:

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


I came to this thread to post the exact same joke.


That's nothing. I made a webserver with just two keystrokes: control-C, control-V. You do have to have Apache installed though.


Why is there a while true?


Otherwise the break has nothing to break out of.


Sarcasm.


This seems to be straight from Wikipedia and then wrapped in a while loop: https://en.wikipedia.org/wiki/Netcat#Setting_up_a_one-shot_w...

netcat's cool, but the post could've gone a bit further. If it's an intro "how to do this", maybe explain the moving parts for beginners?


> 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.


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.


Is your while loop missing a "do" statement, or am I missing something?


In one line, using Go and goe [1]. :)

    $ goe 'net/http' 'ListenAndServe(":8080", FileServer(Dir("/usr/share/doc/")))'
[1] https://github.com/shurcooL/goe


That's not a one-line script. That's a multi-line script with the linebreaks removed.


I suggest you don't say things like that around Perl programmers.


Most Perl one-liners don't have semicolons.


The language lends itself to that, but as far as I am aware there is no prejudice against Perl one-liners that do contain semicolons.


It is 85 characters long. Strip some spaces from it, and it qualifies as a one-liner.


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.


$ 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.


Woah, I didn't realize busybox had an httpd. Truly a sweet piece of software.


It often won't, as features ("applets") are chosen at compile-time.


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.


I dont think they usually use it as the web server, as they need some scripting not static pages only. The smallest server I know of that can do cgi is webfsd).


Hmm, there's another investigation to do.


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.


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".


The socat version I posted https://news.ycombinator.com/item?id=6224060 fixes this problem, but is a bit more cumbersome.


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


Similarly, if PHP 5.4 (or greater) is installed:

    php -S 127.0.0.1:8080


This my defacto, PHP is installed on all the Linux servers I manage, mostly Debian/Ubuntu with DotDeb repos. You could probably get nc to pipe the output of php-cli for older PHP installs.

http://stackoverflow.com/questions/3940046/can-i-use-netcat-... seems to have a basic example.


With built-in caching to boot!


I can recommend 'woof' [1] for simple ad-hoc sharing of files through HTTP. It has some extra features, like quickly sharing a directory as tar file.

[1] http://www.home.unix-ag.org/simon/woof.html



You can actually write a web server in pure bash, with no netcat, using /dev/tcp (bash magic). https://www.gnu.org/software/bash/manual/html_node/Redirecti... http://www.linuxjournal.com/content/more-using-bashs-built-d...


That's demonstrating an HTTP client, not a server. I don't think there's a way to make /dev/tcp accept incoming connections.


I like woof,which is a single file and can also serve itself.

http://www.home.unix-ag.org/simon/woof.html


Netcat for 21st Century Ncat -- http://nmap.org/ncat/


Since nobody mentioned ruby version

ruby -run -e httpd . -p 5000


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.


Adding my two cent:

    twistd web --path . --port 8080


  npm install -g serve
  serve


I'm sure I've seen an example of using /dev/tcp - a bash builtin.


Quite interesting, specially with the limitations of the file:// protocol


http-server works well if you have node installed. https://npmjs.org/package/httpserver


Anyone got a one-line or so version with BASIC auth?


netcat is the most handy service I have seen on Linux. Any more like this?


Look into Socat. Socat is to netcat as Vim is to vi.


Neat trick, but probably too limited to be of much use. Also, stopping it is kind of a nuisance.


Why? It only takes one ^C


For me, it doesn't even respond to ^C (or even ^\). I had to ^Z it, and then `kill %1`.

Could be an OS-dependent thing. I'm using OS X.


Indeed. It could use in front of while loop something like:

int_cmd(){exit 1;}trap 'int_cmd' 2;


You get what you pay for.


nice


nice share




Consider applying for YC's W25 batch! Applications are open till Nov 12.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: