Захват 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.
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