Bash: как получить значение переменной внутри фона цикла while - PullRequest
4 голосов
/ 11 марта 2012

В качестве примера рассмотрим следующий скрипт bash.Есть два цикла, первый выполняется в фоновом режиме, а второй печатает myvar значения:

#!/bin/bash

myvar=AAA

while true;
do
    sleep 3
    myvar=BBB
    sleep 3
    myvar=CCC
done &

while true;
do
    echo "${myvar}"
    sleep 1
done

Вывод, который я получаю:

AAA
AAA
AAA
...

Выводполучить:

AAA
BBB
CCC
BBB
CCC
...

Ответы [ 2 ]

7 голосов
/ 11 марта 2012

Это связано с тем, что & создает новую подоболочку для первого цикла while.

Я почти уверен, что для решения этой проблемы вам понадобится какой-нибудь IPC. Было бы разумно использовать канал или именованный канал для реализации настройки производителя / потребителя.

Грубый пример:

#!/bin/bash

myvar=AAA

while true;
do
    sleep 3
    myvar_piped=BBB
    echo $myvar_piped # this goes to the pipe.
    sleep 1
done | # this connects the two loops.

while true;
do
    # if we consumed something (timeout=1) print it, else print our own variable.
    if read -t 1 myvar_piped #
    then
        echo "${myvar_piped}"
    else
        echo "${myvar}"
    fi  
done

Выходы:

AAA
AAA
AAA
BBB
AAA
AAA
AAA
AAA
BBB
5 голосов
/ 11 марта 2012

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

Первый цикл запускается в под-оболочке из-за &; память под-оболочки полностью независима от памяти основной оболочки, и нет никакого способа (если не делать страшных вещей, таких как запуск отладчика на под-оболочке), чтобы получить доступ к памяти ребенка из родительской оболочки.

Если вы можете изменить процесс под-оболочки, чтобы записывать значение его переменной каждую секунду, то родительский объект сможет это обнаружить. В качестве альтернативы, если вложенная оболочка записывает переменную в файл с известным именем каждый раз, когда она меняет переменную, то вы можете читать файл так часто, как хотите в родительском:

#!/bin/bash

tmp=$(mktemp)

trap "rm -f $tmp; exit 1" 0 1 2 3 13 15

myvar=AAA
echo $myvar > $tmp

while true;
do
    sleep 3
    myvar=BBB
    echo $myvar > $tmp
    sleep 3
    myvar=CCC
    echo $myvar > $tmp
done &

while cat $tmp
do
    sleep 1
done

rm -f $tmp
trap 0

Trappery обеспечивает удаление временного файла в большинстве случаев (сигналы HUP, INT, QUIT, PIPE и TERM).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...