Назад | Перейти на главную страницу

xinetd читает данные сообщения

Я пытаюсь написать простой обработчик для веб-перехватчика с использованием xinetd и bash. У меня тривиальный случай работы с этим конфигом для xinetd:

service github-hooks
{
    port            = 61000
    socket_type     = stream
    protocol        = tcp
    wait            = no
    user            = ubuntu
    server          = /home/ubuntu/github-hooks.sh
}

и этот сценарий bash:

#!/bin/bash
echo -e "HTTP/1.1 200 OK"

Теперь я хочу прочитать данные сообщения, которые отправляются в веб-перехватчике, чтобы я мог сделать что-то более интересное, всегда возвращающее 200.

Как мне прочитать данные публикации из моего сценария bash?

Я пробовал:

while read line; do
    echo "$line" >> /home/ubuntu/test
done < /dev/stdin

но это не работает для меня.

редактировать

Благодаря предложению ниже я остановился xinetd и использовал nc чтобы увидеть, какие необработанные данные поступали по сети:

$nc -l 61000

и получил это:

POST / HTTP/1.1
Host: <snip>:61000
Accept: */*
User-Agent: GitHub-Hookshot/375c44e
X-GitHub-Event: pull_request
X-GitHub-Delivery: 2dc1fb00-1c8e-11e6-9955-64afafb6ce32
content-type: application/json
X-Hub-Signature: sha1=45afd85b7d4312fa8ac4c56638e8e9699e2ddb36
Content-Length: 20558

{"action":"opened","number":116,"pull_request": <snip>

Итак, данные отправляются. Теперь, зная, что отправлено ровно 11 строк, я прочитал ровно 11 строк:

for i in {0..10}
do
    read line
    echo "$line" >> /home/ubuntu/test
done

И я получаю тот же результат (большой успех :)

POST / HTTP/1.1
Host: <snip>:61000
Accept: */*
User-Agent: GitHub-Hookshot/375c44e
X-GitHub-Event: pull_request
X-GitHub-Delivery: 2dc1fb00-1c8e-11e6-9955-64afafb6ce32
content-type: application/json
X-Hub-Signature: sha1=45afd85b7d4312fa8ac4c56638e8e9699e2ddb36
Content-Length: 20558

{"action":"opened","number":116,"pull_request": <snip>

Может быть, мне просто прочитать 9 строк, а затем использовать Content-Length параметр читать остальные? Я до сих пор не очень понимаю, что происходит, поэтому любая информация будет очень полезна.

буквально cat, или xargs, или grep . или что-нибудь еще, что читается из stdin.

Чтобы прочитать стандартные почтовые данные для http-запроса xinetd, программа просто читает стандартный ввод.

Я написал сценарий bash, который читает и анализирует заголовки http, переданные через стандартный ввод. Полезно при вызове из xinetd. Я создал это как отправную точку для тех, кто хочет создать службу xinetd, которая может распознавать HTTP-вызовы, подобные REST. https://github.com/rglaue/xinetd_bash_http_service

Но, по сути, чтение ввода HTTP (заголовки и данные POST) в службе xinetd выглядит примерно так:

# Read HTTP Headers, line by line
# We're looking for the Content-Length HTTP header
: ${HTTP_CONTENT_LENGTH:=0}
while read -t 0.01 line; do
    # If the line is empty, stop reading headers
    if [ -z "$line" ]; then break; fi
    # Read each HTTP Header
    if echo "${line}" | grep -qi "^some-header:"; then
      # do something here
    elif echo "${line}" | grep -qi "^Content-Length:"; then
      HTTP_CONTENT_LENGTH="$(echo "${line}"|cut -d" " -f 2-)"
    fi
done
# Next read from standard input into the HTTP_POST_DATA variable
# (This assumes the request is a POST)
while IFS= read -N $HTTP_CONTENT_LENGTH -r -t 0.01 post_buffer; do
    echo "Reading in the HTTP Post Data"
    HTTP_POST_DATA="${HTTP_POST_DATA}${post_buffer}"
    if [ ${#HTTP_POST_DATA} -ge ${HTTP_CONTENT_LENGTH} ]; then
      # Make sure we stop reading, since we have read enough.
      break;
    fi
done

Зачем использовать IFS=

  • В -r flag уже считывает данные, не останавливаясь на разделителях
  • IFS - это внутренний разделитель полей, используемый bash для определения того, как разделяются слова и как разделяются строки.
  • Мы опустошаем IFS чтобы убедиться, что bash не изменяет наши ожидаемые результаты от необработанного чтения read -r.

Для read параметры:

  • В -t 0.01 флаг определяет таймаут чтения в секундах (0,01 сек)
  • В -r flag читает данные в необработанном виде, игнорируя разделители \r\n
  • В -N <num> flag читает символы <num>.

Хорошо, я так и не понял, как читать, пока есть ввод, но я заметил, что в заголовке есть длина. Итак, я анализирую длину, а затем читаю это количество символов:

#!/bin/bash
for i in {1..9}
do
  read line
done

array=(${line})
length=${array[1]}

read line
read -n ${length:0:-1} line

echo "$line" >> /home/ubuntu/test

echo -e "HTTP/1.1 200 OK"

И теперь у меня есть данные, которые отправляет github.