The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]




Версия для распечатки Пред. тема | След. тема
Новые ответы [ Отслеживать ]
Как из pipe офильтровать строки,а если их не было, то прервать?, !*! Sphk, 08-Июл-12, 16:36  [смотреть все]
Есть некий текстовый поток (gpspipe -r). Задача: получить первые 10 строк, проверить есть ли в них волшебное слово. Если нет слова, то - "аврал"

Проблема: в потоке может появиться только 3 строки, например. После чего gpspipe ждёт не появится ли чего. Чего-либо может не появится совсем, пока не будет устроен "аврал". Соответственно, есть время 10 секунд, больше которого нет смысла ждать.

Как отловить момент, что поток остановился и не потерять то, что оттуда уже получено?

Изобрёл нечто через fifo буфер, но, подозреваю, есть простые и давно реализованные средства и приёмы.


#!/bin/bash

magicWord="_abc"
wantedSign="DATA IS FOUND"
isSuccess="false"

# Если не ..., то создать ...
[ ! -e "/tmp/fifo" ] \
    && mkfifo --mode=600 /tmp/fifo

# Иммитатор потока + фильтр искомого. В фоне.
while read fakeData ; do
    [ "${fakeData}" == "${magicWord}" ] \
        && echo "${wantedSign}" > /tmp/fifo
done <<< "$( echo -en "${magicWord}\n_def\n_ghi\n" | head -n 10 )" \
&
while read fakeData ; do
    # cat /dev/zero = зависание, имитация паузы в потоке
    true
done <<< "$( cat /dev/zero | head -n 10 )" \
&
jobPId=${!}

# Даю время на сбор данных
echo "Job launched. Sleeping now."
sleep 5
echo "Going forward."

# Чтобы было, что прочитать из буфера и не зависнуть на чтении.
echo "stub" > "/tmp/fifo" &

# Поиск нужного в буфере, заодно опустошение буфера.
while read str ; do
    if [ "${str:0:${#wantedSign}}" == "${wantedSign}" ] ; then
        echo "Marker is found: ${str}"
        isSuccess="true"
    else
        echo "Stub found also: ${str}"
    fi
done < "/tmp/fifo"

# Конечная проверка - было ли найдено событие.
if [ "${isSuccess}" == "true" ] ; then
    echo "SUCCESS: Wanted data detected."
else
    echo "FAILURE: Data not found or timeout."
    exit 1
fi

[ -n "$( ps -o pid | grep ${jobPId})" ] \
    && kill -9 ${jobPId}


  • Как из pipe офильтровать строки,а если их не было, то прервать?, !*! Andrey Mitrofanov, 17:35 , 08-Июл-12 (1)
    > Есть некий текстовый поток (gpspipe -r). Задача: получить первые 10 строк, проверить
    > есть ли в них волшебное слово. Если нет слова, то -
    > "аврал"
    > не будет устроен "аврал". Соответственно, есть время 10 секунд, больше которого
    > нет смысла ждать.

    10 строк или 10 секунд... Как-то так...

    N=1000
    S1=$(SECONDS+10))
    while [ $SECONDS -lt $S1 -a $N -le 1010 ]; do
      read -t 1 line
      if [ $? -lt 128 ]; then
        echo "${N:1} : $line"
      fi
    done


    Может, ещё корректировку на скорость шела сделать:

    -while [ $SECONDS -lt $S1 -a $N -le 1010 ]; do
    -  read -t 1 line
    +while [ $SECONDS -lt $S1 -a $N -le 1010 ]; do
    +  while [ $N -le 1010 ] && read -t 1 line && [ $? -lt 128 ]; do
    -  if [ $? -lt 128 ]; then
        echo "${N:1} : $line"
    -  fi
    +  done

    • Как из pipe офильтровать строки,а если их не было, то прервать?, !*! Andrey Mitrofanov, 17:37 , 08-Июл-12 (2)
      >   fi

      Кто-то пропустил -

          let N++

      - но это _такие :) мелочи.

      > done

      • Как из pipe офильтровать строки,а если их не было, то прервать?, !*! Sphk, 21:01 , 08-Июл-12 (3)
        Ниже оба переработанных варианта в рабочей обёртке.

        1) Можно ли как-то обойтись без kill в обоих вариантах? Если kill убрать, то зависнет. Висеть будет на строке возврата return, или - после её выполнения, но до выхода из блока. Кстати, тоже вопрос - где висит, как объяснить?

        2) Не очевидно и тем неприятно, что до return убивается процесс источник потока. После | вызывается отдельный экземпляр shell, в котором и выполняется while. Возникает подозрение, о иерархии родитель-наследник, и тогда, что родитель (gpspipe) тушится до вызова возврата из наследника (блоки while). Всегда ли код возврата будет предсказуем?

        3) В чём идея второго способа, относительного первого?

        Вариант 1


        #!/bin/bash

        codeDataFound=11
        codeTimeout=22

        function probeGPS {
            local timeout=1 # Sec
            local maxStrQuantity=10
            local N=0

            gpspipe -r | while [ ${N} -le ${maxStrQuantity} ]; do
                read -t 1 line
                if [ ${?} -gt 128 ] ; then
                    echo "Timeout at: N=${N}; line=${line};"
                    #kill -9 $( pgrep -P ${$} gpspipe )
                    return ${codeTimeout}
                fi
                if [ "${line:1:5}" == "GPRMC" ] ; then
                    return ${codeDataFound}
                fi

                echo " S1=${S1}; N=${N}; line=${line:0:10};"

                ((N++))
            done
            return ${?}
        }

        probeGPS
        case ${?} in
        ${codeDataFound})
            echo "Data found."
        ;;
        ${codeTimeout})
            echo "Timed out."
        ;;
        esac

        Вариант 2


        #!/bin/bash

        codeDataFound=11
        codeTimeout=22

        function probeGPS2 {
            local N=0
            local M=0
            local maxQuantity=10
            local timeout=1 # Sec

            echo "Level 0"
            gpspipe -r | while : ; do
                echo "Level 1 : Q=$((N+M));"
                while [ ${N} -le 10 ] && read -t ${timeout} line && [ ${?} -lt 128 ]; do
                    echo "Level 2 : Q=$((N+M)); line=${line:0:10};"
                    if [ "${line:1:5}" == "GPRMC" ] ; then
                        return ${codeDataFound}
                    fi
                    ((M++))
                done
                ((N++))
                if [ $(( N+M )) -ge ${maxQuantity} ] ; then
                    kill -9 "$( pgrep -P ${$} gpspipe )"
                    return 22
                fi
            done
            return ${?}
        }

        probeGPS2
        case ${?} in
        ${codeDataFound})
            echo "Data found."
        ;;
        ${codeTimeout})
            echo "Timed out."
        ;;
        esac





Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2025 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру