[bash] netcat을 사용하는 최소 웹 서버

netcat (nc)을 사용하여 최소 웹 서버를 설정하려고합니다. 예를 들어 브라우저가 localhost : 1500을 호출 할 때 함수의 결과를 표시해야합니다 ( 아래 예에서는 날짜 이지만 결국 일부 데이터를 생성하는 파이썬 또는 c 프로그램이됩니다). 내 작은 netcat 웹 서버는 bash에서 while true 루프 여야합니다. 아마도 다음과 같이 간단합니다.

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

이것을 시도하면 브라우저는 nc가 시작되는 순간 현재 사용 가능한 데이터를 보여줍니다. 그래도 브라우저가 요청하는 동안 브라우저가 데이터를 표시하고 싶습니다. 이것을 어떻게 할 수 있습니까?



답변

이 시도:

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

-c당신이 에코 사용할 수 있도록 만든다은 쉘에 주어진 명령을 실행 netcat을. 에코가 필요하지 않으면 -e. 이에 대한 자세한 내용을 보려면를 시도하십시오 man nc. 를 사용할 때 echo프로그램 ( date대체)이 브라우저 요청을받을 수있는 방법이 없습니다 . 따라서 마침내 다음과 같이하고 싶을 것입니다.

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

yourprogramGET 처리, HTTP 200 전송 등과 같은 프로토콜 작업은 어디에서 해야합니까?


답변

방법 또는 이유가 없지만 주변에서 이것을 찾을 수 있고 나를 위해 작동합니다. 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   |
+----------+------+------+--------+------+-------+

단순히 놀랍습니다!


답변

추가 -q 1받는 netcat명령 행 :

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


답변

당신이 직면 한 문제는 nc가 웹 클라이언트가 요청에 응답 할 수 있도록 웹 클라이언트가 언제 완료되었는지 알지 못한다는 것입니다.
웹 세션은 다음과 같이 진행되어야합니다.

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 주소 및 전체 브라우저 요청을 로그 파일에 기록하고 서버 헤더 응답에 대한 콘텐츠 길이를 계산합니다.

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

해피 배싱!


답변

나는 똑같은 필요 / 문제가 있었지만 여기서는 나를 위해 일하지 않았거나 (또는 ​​모든 것을 이해하지 못했습니다) 이것이 내 해결책입니다.

내 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


답변

이를 수행하는 또 다른 방법

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)를 자유롭게 바꾸십시오.


답변

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