Захват stdout в переменную, но по-прежнему отображать его в консоли



У меня есть bash-скрипт, который вызывает несколько длительных процессов. Я хочу захватить выходные данные этих вызовов в переменные для обработки причин. Однако, поскольку это длительные процессы, я хотел бы, чтобы вывод вызовов rsync отображался в консоли в в режиме реального времени и не постфактум.



для этого у меня есть нашел способ сделать это, но он полагается на вывод текста в /dev/stderr. Я чувствую, что вывод на /dev / stderr-это не очень хороший способ делать вещи.



VAR1=$(for i in {1..5}; do sleep 1; echo $i; done | tee /dev/stderr)

VAR2=$(rsync -r -t --out-format='%n%L' --delete -s /path/source1/ /path/target1 | tee /dev/stderr)

VAR3=$(rsync -r -t --out-format='%n%L' --delete -s /path/source2/ /path/target2 | tee /dev/stderr)


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



есть ли "более чистый" способ достижения этого?



Если это имеет значение, я использую Ubuntu 12.04, bash 4.2.24.

646   4  

4 ответов:

дублировать &1 в вашей оболочке (в моем examle до 5) и использовать &5 в подрешетке (так что вы будете писать в stdout (&1) родительской оболочки):

exec 5>&1
FF=$(echo aaa|tee >(cat - >&5))
echo $FF

будет печатать aaa два раза, один из-за эха в подрешетке, и второй раз печатать значение переменной.

в коде:

exec 5>&1
VAR1=$(for i in {1..5}; do sleep 1; echo $i; done | tee >(cat - >&5))
# use the value of VAR1

ответ Op De Cirkel имеет правильную идею. Его можно упростить еще больше (избегая использования cat):

exec 5>&1
FF=$(echo aaa|tee /dev/fd/5)
echo $FF

вот пример захвата как stderr и код выхода команды. Это основано на ответе Рассела Дэвиса.

exec 5>&1
FF=$(ls /taco/ 2>&1 |tee /dev/fd/5; exit ${PIPESTATUS[0]})
exit_code=$?
echo "$FF"
echo "Exit Code: $exit_code"

если папке /taco/ существует, это будет захватить его содержимое. Если папка не существует, она будет захватить сообщение об ошибке и код выхода будет 2.

если вы опустите 2>&1затем только stdout будут захвачены.

вы можете использовать более трех дескрипторов файлов. Попробуйте здесь:

http://tldp.org/LDP/abs/html/io-redirection.html

" каждому открытому файлу присваивается дескриптор файла. [2] файловые дескрипторы для stdin, stdout и stderr равны 0, 1 и 2 соответственно. Для открытия дополнительных файлов остаются дескрипторы от 3 до 9. Иногда полезно назначить один из этих дополнительных файловых дескрипторов stdin, stdout или stderr в качестве временного дубликата ссылка на сайт."

дело в том, стоит ли усложнять скрипт только для достижения этого результата. На самом деле это не совсем так, как вы делаете это.

Comments

    Ничего не найдено.