HTTP сервер в одну строку: версия 2.0
Идея с HTTP сервером на bash мне не дает покоя.
Вернуться к ней меня побудила.. попытка воспользоваться старой версией: получалсь не очень :)
Поэтому решил довести его до ума. Что-то дописал, что-то выкинул, полчилось следующее:
:;while [ $? -eq 0 ];do nc -vlp 8080 -c’(r=read;e=echo;$r a b c;z=$r;while [ ${#z} -gt 2 ];do $r z;done;f=`$e $b|sed ‘s/[^a-z0-9_.-]//gi’`;h=”HTTP/1.0″;o=”$h 200 OK\r\n”;c=”Content”;if [ -z "$f" ];then ($e $o;(for n in *;do if [ -f "$n" ]; then $e “`ls -gh \”$n\”`
“;fi;done););elif [ -f "$f" ];then $e “$o$c-Type: `file -ib \”$f\”`\n$c-Length: `stat -c%s \”$f\”`”;$e;$e $f>&2;cat “$f”;else $e -e “$h 404 Not Found\n\n404\n”;fi)’;done
Теперь по URL http://ваш_ip:8080/ можно получить доступ ко всем файлам, находящимся в текущим каталоге. Очевидных и прямолинейных способов сменить каталог нет. Как и раньше, протестировано и работает под Linux, bash 3.2.13, и с хоббитовским netcat v1.10 с поддержкой опции -с (запустите netcat -h и посмотрите. Как минимум в Ubuntu, Debian и Fedora Core такая опция есть).
Теперь строка занимает 434 байт, что на 212 больше, чем прошлая версия. И мне кажется, что я с толком потратил эти байты: новый сервер обрабатывает ошибку 404, кроме того, теперь он работает без задержки, которая раньше требовалась для того, чтобы была возможность его остановить с помощью Ctrl-C. Для успешных запросов сервер отдает нормальные заголовки, с размером файла и даже с его MIME-типом. Например:
dainichi@fujitsu:~/backup$ echo “GET /6.1-RELEASE-i386-disc1.iso HTTP/1.1″ | nc localhost 8080 | head -n3
HTTP/1.x 200 OK
Content-Type: application/x-iso9660
Content-Length: 529784832
Для удобства можно сохранить его в файл и написать в .bash_profile примерно следующее:alias share='sh ~/bash_httpd.sh'
Если у вас получится сэкономить еще пару байтов, то милости просим в комментаторскую :)
UPD: Код обновлен, в него вошли исправления, которые сделал тов. jetxee, за которые ему большое спасибо.
UPD: Заметка попала в топ news2, спасибо dik’у за то, что добавил ее. Я рад, что она многим показалась интересной.
UPD: Товарищ Ed очень здорово прооптимизировал код. Вот, что у него вышло:
while :;do nc -p8080 -vnlc’r=read;e=”echo -e”;$r a b c;while [ -n "`$e $a|tr -d "\r\n"`" ];do $r a;done;f=`$e $b|sed s/.//`;h=”HTTP/1.0″;z=”404 Not Found\n”;[ -z $f ]&&(ls|while $r n;do [ -f $n ]&&$e “$n“;done)||([ -f $f ]&&($e “$h 200 OK\r\nContent-Type: `file -ib $f`\n”;cat $f)||$e “$h $z\n$z”)’;done
Работоспособность проверялась автором на таблетке Nokia N800, а у меня в Kubuntu 7.04 что-то не заработало. Сегодня вечером буду разбираться :). Мне теперь стыдно из-за того, что сам не догадался использовать && и || вместо if..then. :(
UPD: О, на хабре написали.
Для владельцев Ubuntu 10.10: Теперь в дистрибутиве по умолчанию стоит другой вариант netcat’а. Вот так можно вернуть все как было, это абсолютно безвредное для системы действие:
sudo apt-get install netcat-traditional
sudo update-alternatives –set nc /bin/nc.traditional
P.S. Ссылка на скрипт в plain text: http://sveshnikov.ru/httpd.sh, он же, в более удобночитаемом виде: http://sveshnikov.ru/httpd.sh.formatted

