Использование именованных каналов с bash - Проблема с потерей данных

Провел поиск в Интернете, нашел простые "руководства" по использованию именованных каналов. Однако, когда я что-то делаю с фоновыми заданиями, мне кажется, что я теряю много данных.

[[Edit: нашел более простое решение, см. Ответ на сообщение. Итак, вопрос, который я поставил, теперь академический - на случай, если кому-то понадобится сервер заданий]]

Использование Ubuntu 10.04 с Linux 2.6.32-25-generic # 45-Ubuntu SMP Sat Oct 16 19:52:42 UTC 2010 x86_64 GNU / Linux

GNU bash, версия 4.1.5 (1) -release (x86_64-pc-linux-gnu).

Моя функция bash:

function jqs
{
  pipe=/tmp/__job_control_manager__
  trap "rm -f $pipe; exit"  EXIT SIGKILL

  if [[ ! -p "$pipe" ]]; then
      mkfifo "$pipe"
  fi

  while true
  do
    if read txt <"$pipe"
    then
      echo "$(date +'%Y'): new text is [[$txt]]"

      if [[ "$txt" == 'quit' ]]
      then
    break
      fi
    fi
  done
}

Я запускаю это в фоновом режиме:

> jqs&
[1] 5336

А теперь кормлю:

for i in 1 2 3 4 5 6 7 8
do
  (echo aaa$i > /tmp/__job_control_manager__ && echo success$i &)
done

Вывод противоречивый. Я часто не получаю отголоски успеха. Я получаю максимум столько же новых текстовых эхо, сколько эхо успеха, иногда меньше.

Если я удалю '&' из 'фида', кажется, что это сработает, но я заблокирован до тех пор, пока вывод не будет прочитан. Следовательно, я хочу, чтобы подпроцессы были заблокированы, но не основной процесс.

Цель состоит в том, чтобы написать простой сценарий управления заданиями, чтобы я мог запускать, скажем, 10 заданий параллельно, а остальные ставить в очередь для последующей обработки, но достоверно знать, что они выполняются.

Полный диспетчер заданий ниже:

function jq_manage
{
  export __gn__="$1"

  pipe=/tmp/__job_control_manager_"$__gn__"__
  trap "rm -f $pipe"    EXIT
  trap "break"      SIGKILL

  if [[ ! -p "$pipe" ]]; then
      mkfifo "$pipe"
  fi

  while true
  do
    date
    jobs
    if (($(jobs | egrep "Running.*echo '%#_Group_#%_$__gn__'" | wc -l) < $__jN__))
    then
      echo "Waiting for new job"
      if read new_job <"$pipe"
      then
    echo "new job is [[$new_job]]"

    if [[ "$new_job" == 'quit' ]]
    then
      break
    fi

    echo "In group $__gn__, starting job $new_job"
    eval "(echo '%#_Group_#%_$__gn__' > /dev/null; $new_job) &"
      fi
    else
      sleep 3
    fi
  done
}

function jq
{
  # __gn__ = first parameter to this function, the job group name (the pool within which to allocate __jN__ jobs)
  # __jN__ = second parameter to this function, the maximum of job numbers to run concurrently

  export __gn__="$1"
  shift
  export __jN__="$1"
  shift

  export __jq__=$(jobs | egrep "Running.*echo '%#_GroupQueue_#%_$__gn__'" | wc -l)
  if (($__jq__ '<' 1))
  then
    eval "(echo '%#_GroupQueue_#%_$__gn__' > /dev/null; jq_manage $__gn__) &"
  fi

  pipe=/tmp/__job_control_manager_"$__gn__"__

  echo $@ >$pipe
}

Вызов

jq <name> <max processes> <command>
jq abc 2 sleep 20

запускает один процесс. Эта часть работает нормально. Начни второй, хорошо. Один за другим вроде работают нормально. Но запуск 10 в цикле, кажется, приводит к потере системы, как в более простом примере выше.

Любые подсказки относительно того, что я могу сделать, чтобы решить эту очевидную потерю данных IPC, были бы очень признательны.

С уважением, Ален.

14
задан camh 27 November 2010 в 02:12
поделиться