2015-11-17 3 views
0

У меня проблема с ksh в том, что цикл while не подчиняется условию «while». Теперь я должен добавить, что это ksh88 в ящике Solaris моего клиента. (Это отдельная проблема, которая не может быть решена на этом форуме.;) Я видел Lance's question и некоторые подобные, но ни один из них, которые я нашел, по-видимому, не затрагивает этого. (Отказ от ответственности: НЕТ Я не смотрел на каждый КШ вопрос в этом форуме)while [[condition]] stalls on loop exit

Вот очень вырубить кусок кода, который воспроизводит проблему:

1 #!/usr/bin/ksh 
    2 # 
    3 go=1 
    4 set -x 
    5 tail -0f loop-test.txt | while [[ $go -eq 1 ]] 
    6 do 
    7 read lbuff 
    8 set $lbuff 
    9 nwords=$# 
10 printf "Line has %d words <%s>\n" $nwords "${lbuff}" 
11 if [[ "${lbuff}" = "0" ]] 
12 then 
13  printf "Line consists of %s; time to absquatulate\n" $lbuff 
14  go=0  # Violate the WHILE condition to get out of loop 
15 fi 
16 done 
17 printf "\nLooks like I've fallen out of the loop\n" 
18 exit 0 

Как я проверить это:

  • Run loop-test.sh в фоновом режиме
  • в другом окне я бегу команды, как «эхо какой-то бред >> loop_test.txt» (без кавычек, конечно)
  • Когда я ИСВ h для выхода, я печатаю «echo 0 >> loop-test.txt»

Что происходит? Он действительно устанавливает go = 0 и отображает строку:

Линия состоит из 0; время, чтобы абсцитировать

, но не выходит из цикла. Чтобы разразиться, я добавляю еще одну строку в txt-файл. Цикл НЕ обрабатывает эту строку и просто выпадает из цикла, выдавая это «выпавшее» сообщение перед выходом.

Что происходит с этим? Я не хочу использовать «break», потому что в реальном скрипте цикл отслеживает журнал механизма базы данных, а флаг устанавливается, когда он видит сообщения, которые отключает двигатель. Фактический скрипт должен обрабатывать эти окончательные строки перед выходом.

Открыт для идей, кто-нибудь?

Большое спасибо!

- J.

+0

Не уверен, что я действительно понимаю проблему (время для меня, чтобы Гото спать ;-), но бы использовать 'continue' вместо' break' получить вам что-нибудь? ИЛИ подавать 'tail -f' вывод в эквивалентную программу' awk'? Я не понимаю 'set $ lbuff' Какие значения будут отображаться в' $ lbuff'? ИЛИ Вы можете пометить это с помощью '[bash]' и получить гораздо больше глаз на проблему. Я не думаю, что здесь есть эксклюзивный код ksh. Если завтра это не будет, я буду экспериментировать. Удачи. – shellter

+0

Шелтер, «набор $ lbuff» предназначен для создания выходных «n слов». Я хотел, чтобы моя петля сделала что-то *, кроме просто тупо прочитанных строк. – Jake

+0

О, да, также нужно знать вывод 'echo KSH_Version = $ {. Sh.version}; uname -a'. Пожалуйста, внесите изменения в свой вопрос. Ночь ;-) Удачи. – shellter

ответ

0

После озвучивания проблемы и спать на ней, причина описанного поведения пришла ко мне: После установки go=0, поток управления петли еще зависит от другой линии данных поступая из STDIN через эту трубу.

И теперь, когда я осознал причину странности, я могу размышлять об альтернативном способе чтения из потока. На данный момент я имею в виду следующее решение:

  • Откройте входной файл в STDIN (нужно исследовать EXEC синтаксис для этого)
  • При возникновении условия, близко STDIN (Опять же, нужно исследовать синтаксис для этого)

Тогда должно быть безопасным использовать более интуитивно понятный: while read lbuff в верхней части петли.

Я проверю это сегодня и опубликую результат. Я надеюсь, что кто-то еще выиграет от метода (если он работает).

0

ОК, что на флопе довольно быстро.Прочитав несколько других сообщений, я нашел answer given by dogbane, который обошел всю мою схему «труба-время». Его второй ответ на вопрос (с 2013 года), где я вижу, что neeraj использует ту же схему, которую я использую.

Что случилось? Труба-в-время всегда работала для ввода, который завершится, как файл или команда с отдельным концом для выхода. Однако из команды tail нет четкого EOF. Следовательно, пока-в-подоболочке не известно, когда прекращать.

Решение Dogbane: Не используйте трубу. Применяя свою логику к моей ситуации, основной цикл:

while read line do # put loop body here done < <(tail -0f ${logfile})

Нет подоболочка, нет проблем.

Предостережение об этом синтаксисе: между двумя операторами < должно быть пробел; в противном случае он выглядит как документ HEREIS с плохим синтаксисом.

Er, еще один улов: синтаксис не Работа в ksh, даже в mksh (под cygwin), который имитирует ksh93. Но это сделал Работа в bash. Так что мой босс будет смеяться над мной, потому что он знает, что мне не нравится баш.

Так что спасибо MUCH, dogbane.

- J

+0

'<<(tail -0f $ {logfile})' все еще выглядит как подоболочка для меня. Способ ksh88 справиться с этим, вероятно, будет совместным процессом и 'read -p'. Когда вы выходите из цикла, вы отправляете «kill -1» в совместный процесс, убивая «tail -0f». У меня больше нет доступа к ksh88, или я мог бы дать правильный ответ и рабочий пример. –