使用netcat的最小Web服务器

时间:2013-05-19 22:17:28

标签: bash webserver netcat

我正在尝试使用netcat(nc)设置最小的Web服务器。例如,当浏览器调用localhost:1500时,它应该显示一个函数的结果( date 在下面的例子中,但最终它将是一个产生一些数据的python或c程序) 。 我的小netcat web服务器需要在bash中成为一个真正的循环,可能就像这样简单:

while true ; do  echo -e "HTTP/1.1 200 OK\n\n $(date)" | nc -l -p 1500  ; done

当我尝试此操作时,浏览器会在nc启动时显示当前可用的数据。我希望浏览器在浏览器请求时显示数据。我怎样才能做到这一点?

15 个答案:

答案 0 :(得分:37)

试试这个:

while true ; do nc -l -p 1500 -c 'echo -e "HTTP/1.1 200 OK\n\n $(date)"'; done

-c使netcat在shell中执行给定命令,因此您可以使用echo。如果您不需要回声,请使用-e。有关此问题的详细信息,请尝试man nc。请注意,使用echo时,您的程序(date - 替换)无法获取浏览器请求。所以你可能最终想做这样的事情:

while true ; do nc -l -p 1500 -e /path/to/yourprogram ; done

yourprogram必须执行协议之类的操作,例如处理GET,发送HTTP 200等。

答案 1 :(得分:34)

唐诺怎么或为什么但我设法找到这个并且它对我有用,我有问题我想要返回执行bash的结果

$ while true; do { echo -e 'HTTP/1.1 200 OK\r\n'; sh test; } | nc -l 8080; done

注意:此命令来自:http://www.razvantudorica.com/08/web-server-in-one-line-of-bash

执行bash脚本测试并将结果返回给连接到端口8080上运行此命令的服务器的浏览器客户端

我的脚本执行此ATM

$ nano test

#!/bin/bash

echo "************PRINT SOME TEXT***************\n"
echo "Hello World!!!"
echo "\n"

echo "Resources:"
vmstat -S M
echo "\n"

echo "Addresses:"
echo "$(ifconfig)"
echo "\n"


echo "$(gpio readall)"

我的网络浏览器正在显示

************PRINT SOME TEXT***************

Hello World!!!


Resources:
procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa
 0  0      0    314     18     78    0    0     2     1  306   31  0  0 100  0


Addresses:
eth0      Link encap:Ethernet  HWaddr b8:27:eb:86:e8:c5  
          inet addr:192.168.1.83  Bcast:192.168.1.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:27734 errors:0 dropped:0 overruns:0 frame:0
          TX packets:26393 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:1924720 (1.8 MiB)  TX bytes:3841998 (3.6 MiB)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)


GPIOs:
+----------+-Rev2-+------+--------+------+-------+
| wiringPi | GPIO | Phys | Name   | Mode | Value |
+----------+------+------+--------+------+-------+
|      0   |  17  |  11  | GPIO 0 | IN   | Low   |
|      1   |  18  |  12  | GPIO 1 | IN   | Low   |
|      2   |  27  |  13  | GPIO 2 | IN   | Low   |
|      3   |  22  |  15  | GPIO 3 | IN   | Low   |
|      4   |  23  |  16  | GPIO 4 | IN   | Low   |
|      5   |  24  |  18  | GPIO 5 | IN   | Low   |
|      6   |  25  |  22  | GPIO 6 | IN   | Low   |
|      7   |   4  |   7  | GPIO 7 | IN   | Low   |
|      8   |   2  |   3  | SDA    | IN   | High  |
|      9   |   3  |   5  | SCL    | IN   | High  |
|     10   |   8  |  24  | CE0    | IN   | Low   |
|     11   |   7  |  26  | CE1    | IN   | Low   |
|     12   |  10  |  19  | MOSI   | IN   | Low   |
|     13   |   9  |  21  | MISO   | IN   | Low   |
|     14   |  11  |  23  | SCLK   | IN   | Low   |
|     15   |  14  |   8  | TxD    | ALT0 | High  |
|     16   |  15  |  10  | RxD    | ALT0 | High  |
|     17   |  28  |   3  | GPIO 8 | ALT2 | Low   |
|     18   |  29  |   4  | GPIO 9 | ALT2 | Low   |
|     19   |  30  |   5  | GPIO10 | ALT2 | Low   |
|     20   |  31  |   6  | GPIO11 | ALT2 | Low   |
+----------+------+------+--------+------+-------+
简直太神奇了!

答案 2 :(得分:22)

-q 1添加到netcat命令行:

while true; do 
  echo -e "HTTP/1.1 200 OK\n\n $(date)" | nc -l -p 1500 -q 1
done

答案 3 :(得分:18)

您面临的问题是,nc不知道Web客户端何时完成其请求,因此它可以响应请求。
网络会话应该是这样的。

TCP session is established.
Browser Request Header: GET / HTTP/1.1
Browser Request Header: Host: www.google.com
Browser Request Header: \n #Note: Browser is telling Webserver that the request header is complete.
Server Response Header: HTTP/1.1 200 OK
Server Response Header: Content-Type: text/html
Server Response Header: Content-Length: 24
Server Response Header: \n #Note: Webserver is telling browser that response header is complete 
Server Message Body: <html>sample html</html>
Server Message Body: \n #Note: Webserver is telling the browser that the requested resource is finished. 
The server closes the TCP session.

以“\ n”开头的行只是空行,甚至没有空格,只包含一个换行符。

我有由xinetd xinetd tutorial发起的bash httpd。它还会将日期,时间,浏览器IP地址和整个浏览器请求记录到日志文件中,并计算服务器标头响应的Content-Length。

user@machine:/usr/local/bin# cat ./bash_httpd
#!/bin/bash
x=0;
Log=$( echo -n "["$(date "+%F %T %Z")"] $REMOTE_HOST ")$(
        while read I[$x] && [ ${#I[$x]} -gt 1 ];do
              echo -n '"'${I[$x]} | sed -e's,.$,",'; let "x = $x + 1";
        done ;
); echo $Log >> /var/log/bash_httpd

Message_Body=$(echo -en '<html>Sample html</html>')
echo -en "HTTP/1.0 200 OK\nContent-Type: text/html\nContent-Length: ${#Message_Body}\n\n$Message_Body"

要添加更多功能,您可以合并。

            METHOD=$(echo ${I[0]} |cut -d" " -f1)
            REQUEST=$(echo ${I[0]} |cut -d" " -f2)
            HTTP_VERSION=$(echo ${I[0]} |cut -d" " -f3)
            If METHOD = "GET" ]; then 
                case "$REQUEST" in

                    "/") Message_Body="HTML formatted home page stuff"
                        ;;
                    /who) Message_Body="HTML formatted results of who"
                        ;;
                    /ps) Message_Body="HTML formatted results of ps"
                        ;;
                    *) Message_Body= "Error Page not found header and content"
                       ;;
                esac

            fi

快乐抨击!

答案 4 :(得分:10)

我有同样的需求/问题,但这里没有任何东西可供我使用(或者我并不了解所有内容),所以这是我的解决方案。

我发布了我的minimal_http_server.sh(使用我的/ bin / bash(4.3.11)但不是/ bin / sh因为重定向):

rm -f out
mkfifo out
trap "rm -f out" EXIT
while true
do
  cat out | nc -l 1500 > >( # parse the netcat output, to build the answer redirected to the pipe "out".
    export REQUEST=
    while read -r line
    do
      line=$(echo "$line" | tr -d '\r\n')

      if echo "$line" | grep -qE '^GET /' # if line starts with "GET /"
      then
        REQUEST=$(echo "$line" | cut -d ' ' -f2) # extract the request
      elif [ -z "$line" ] # empty line / end of request
      then
        # call a script here
        # Note: REQUEST is exported, so the script can parse it (to answer 200/403/404 status code + content)
        ./a_script.sh > out
      fi
    done
  )
done

我的a_script.sh(根据你的需要):

#!/bin/bash

echo -e "HTTP/1.1 200 OK\r"
echo "Content-type: text/html"
echo

date

答案 5 :(得分:8)

另一种方法

while true; do (echo -e 'HTTP/1.1 200 OK\r\n'; echo -e "\n\tMy website has date function" ; echo -e "\t$(date)\n") | nc -lp 8080; done

让我们使用curl

对2个HTTP请求进行测试

在此示例中,172.16.2.6是服务器IP地址。

服务器端

admin@server:~$ while true; do (echo -e 'HTTP/1.1 200 OK\r\n'; echo -e "\n\tMy website has date function" ; echo -e "\t$(date)\n") | nc -lp 8080; done

GET / HTTP/1.1 Host: 172.16.2.6:8080 User-Agent: curl/7.48.0 Accept:
*/*

GET / HTTP/1.1 Host: 172.16.2.6:8080 User-Agent: curl/7.48.0 Accept:
*/*

客户端

user@client:~$ curl 172.16.2.6:8080

        My website has date function
        Tue Jun 13 18:00:19 UTC 2017

user@client:~$ curl 172.16.2.6:8080

        My website has date function
        Tue Jun 13 18:00:24 UTC 2017

user@client:~$

如果您想执行另一个命令,请随意替换$(date)。

答案 6 :(得分:5)

mkfifo pipe;
while true ; 
do 
   #use read line from pipe to make it blocks before request comes in,
   #this is the key.
   { read line<pipe;echo -e "HTTP/1.1 200 OK\r\n";echo $(date);
   }  | nc -l -q 0 -p 8080 > pipe;  

done

答案 7 :(得分:4)

这是a little bash webserver的美丽,我在网上找到了它并分叉了一下并稍微整理了一下 - 它使用了socatnetcat我用{{1}进行了测试 - 它在一个脚本中是自包含的,并生成自己的配置文件和favicon。

默认情况下,它将启动为支持Web的文件浏览器,但配置文件可以轻松配置任何逻辑。对于文件,它传输图像和音乐(mp3&#39; s),视频(mp4&#39; s,avi等) - 我已经测试了各种文件类型到Linux,Windows和Android设备,包括智能手表!

我认为它实际上比VLC更好。我发现将文件传输到无法访问Web浏览器的远程客户端非常有用,例如Android智能手表,无需担心物理连接到USB端口。

如果您想尝试一下,只需将其复制并粘贴到名为bashttpd的文件中,然后使用socat

在主机上启动它

然后你可以去任何其他计算机(假设防火墙没有阻止到端口8080的入站tcp连接 - 默认端口,你可以使用脚本顶部的全局变量将端口更改为你想要的任何端口) 。 $> bashttpd -s

http://bashttpd_server_ip:8080

答案 8 :(得分:3)

LOL,一个超级蹩脚的黑客,但至少curl和firefox接受它:

while true ; do (dd if=/dev/zero count=10000;echo -e "HTTP/1.1\n\n $(date)") | nc -l  1500  ; done

你最好用适当的东西尽快替换它!

是啊,我的nc与你的-p不完全相同,它不喜欢{{1}}选项。

答案 9 :(得分:2)

输入 nc -h ,看看您是否有 -e 选项。如果是,您可以创建脚本,例如:

script.sh

echo -e "HTTP/1.1 200 OK\n\n $(date)"

然后像这样运行:

while true ; do nc -l -p 1500 -e script.sh; done

请注意,编译时需要启用 -e 选项。

答案 10 :(得分:1)

如果您使用的是Apline Linux,则BusyBox netcat会稍有不同:

{{1}}

答案 11 :(得分:1)

while true; do (echo -e 'HTTP/1.1 200 OK\r\nConnection: close\r\n';) | timeout 1  nc -lp 8080 ; done

1秒钟后关闭连接,因此不会卷曲。

答案 12 :(得分:0)

我认为列出的所有解决方案都不起作用的问题是http服务的本质所固有的,建立的每个请求都是使用不同的客户端,并且响应需要在不同的上下文中处理,每个请求必须分叉一个新的响应实例......

我认为目前的解决方案是-e的{​​{1}},但我不知道为什么不起作用...也许是我的netcat版本测试nc ...

openwrt它有效....

我试试这个https://github.com/avleen/bashttpd

并且它可以工作,但我必须使用此命令运行shell脚本。

socat

github上的socat tcp-l:80,reuseaddr,fork EXEC:bashttpd & socat示例对我不起作用,但我使用的netcat无效。

答案 13 :(得分:0)

实际上,正常关闭连接的最佳方法是发送Content-Length标头,如下所示。客户端(例如curl将在收到数据后关闭连接。

DATA="Date: $(date)"; 
LENGTH=$(echo $DATA | wc -c);
echo -e "HTTP/1.1 200 OK\nContent-Length: ${LENGTH}\n\n${DATA}" | nc -l -p 8000;

答案 14 :(得分:0)

在 OSX 上你可以使用:

do echo -e "HTTP/1.1 200 OK\n\n $(date)" | nc -l  localhost 1500 ; done