Webserver in 100 Zeilen Bash

In Piotr Gabryjeluks Blog habe ich ein interessantes Skript gefunden, welches einen Webserver in 100 Zeilen Bash enthält. Als Parameter erwartet das Skript eine Portnummer, auf die es lauschen soll.

Für Ubuntu muss dieses Skript angepasst werden, da das dort installierte netcat andere Optionen versteht. Das Original kann von obiger Webseite heruntergeladen werden, das für Ubuntu angepasste folgt hier und kann auch als Datei heruntergeladen werden:

  1#!/bin/bash
  2#
  3# httpd.bash :
  4# webserver in 100 lines of bash.
  5#
  6# credits: http://piotr.gabryjeluk.pl/www-server-in-100-lines-bash-script
  7#
  8# This software should be quite safe, since this checks for some nasty tricks like:
  9# .. in URL
 10# / in some places
 11# It binds to port specified from the command line.
 12# It serves only files accessible by the user that runs this script from the current directory (not going up).
 13#
 14# dependencies:
 15# This script depends on nc (netcat package) being installed in PATH.
 16# If you have nc instead of netcat, just change the netcat in script to nc.
 17
 18function debug {
 19    local severity="$1"
 20    shift
 21    local message="$@"
 22
 23    echo -n "`date -u`"    1>&2
 24    echo -ne '\t'        1>&2
 25    echo -n "$severity"    1>&2
 26    echo -ne '\t'        1>&2
 27    echo "$message"        1>&2
 28}
 29
 30function fix_path {
 31    echo -n "$1" | head -n 1 | sed 's|^[/.-]*||' | sed 's|/\.*|/|g'
 32}
 33
 34function serve_dir {
 35    local dir="`fix_path "$1"`"
 36    if [ "$dir" = "" ]; then
 37        dir="./"
 38    fi
 39    echo 'HTTP/1.1 200 OK'
 40    echo 'Content-type: text/html;charset=UTF-8'
 41    echo
 42    echo LISTING "$dir"
 43    echo '<br/>'
 44    ls -p "$dir" | sed -e 's|^\(.*\)$|<a href="/'"$dir"'\1">\1</a><br/>|'
 45}
 46
 47function serve_file {
 48    echo 'HTTP/1.1 200 OK'
 49    echo 'Content-type: application/x-download-this'
 50    echo
 51    local file="`fix_path "$1"`"
 52    debug INFO serving file "$file"
 53    cat "$file"
 54}
 55
 56function process {
 57    local url="`gawk '{print $2}' | head -n 1`"
 58    case "$url" in
 59        */)
 60            debug INFO Processing "$url" as dir
 61            serve_dir "$url"
 62            break
 63            ;;
 64        *)
 65            debug INFO Processing "$url" as file
 66            serve_file "$url"
 67            ;;
 68    esac
 69}
 70
 71function serve {
 72    local port="$1"
 73    local sin="$2"
 74    local sout="$3"
 75
 76    while debug INFO Running nc; do
 77
 78        netcat -l "$port" < "$sin" > "$sout" &
 79        pid="$!"
 80
 81        debug INFO Server PID: "$pid"
 82
 83        trap cleanup SIGINT
 84        head -n 1 "$sout" | process > "$sin"
 85        trap - SIGINT
 86    done
 87
 88    debug INFO Quiting server
 89}
 90
 91function cleanup {
 92    debug INFO Caught signal, quitting...
 93    rm -Rf "$tmp_dir"
 94	kill "$pid"
 95    exit
 96}
 97
 98tmp_dir="`mktemp -d -t http_server.XXXXXXXXXX`"
 99sin="$tmp_dir"/in
100sout="$tmp_dir"/out
101pid=0
102port="$1"
103
104mkfifo "$sin"
105mkfifo "$sout"
106
107debug INFO Starting server on port "$port"
108serve "$port" "$sin" "$sout"
109cleanup