2015-07-21 11 views
1

Я застрял с bash scipt, который должен писать как в stdout, так и в файл. Я использую функции и некоторые переменные внутри них. Всякий раз, когда я пытаюсь перенаправить функцию в файл и печатать на экране с помощью tee, я не могу использовать переменные, которые я использовал в функции, поэтому они как-то становятся локальными. Вот простой пример:В bash tee делает переменные функции локальными, как я могу избежать этого?

#!/bin/bash 
LOGV=/root/log 

function var() 
{ 
echo -e "Please, insert VAR value:\n" 
read -re VAR 
} 
var 2>&1 | tee $LOGV 
echo "This is VAR:$VAR" 

Выход:

[[email protected] ~]# ./var.sh 
Please, insert VAR value: 

foo 
This is VAR: 
[[email protected] ~]# 

Заранее спасибо!

EDIT: В ответ на @Etan Рейснер предложение использовать var 2>&1 > >(tee $LOGV)

Единственная проблема этой конструкции является то, что файл журнала dosn't получить все ...

[[email protected]~]# ./var.sh 
Please, insert VAR value: 

foo 
This is VAR:foo 
[[email protected] ~]# cat log 
Please, insert VAR value: 
+2

Я тонкий k Ваша проблема в том, что, поскольку вы используете канал (в 'tee'), начальный вызов' var' происходит в подоболочке. Таким образом, вы устанавливаете переменную среды в этом подпроцессе, но не влияете на среду основного (родительского) процесса. –

+0

Вы хотите, чтобы запрос «Пожалуйста, вставьте ...» в выходной файл? –

+0

Спасибо, да, я думаю, это проблема с подоболочкой, но пока не могу ее исправить. Уильям Пурселл, да, я знаю! – LinenG

ответ

3

Это вариант BashFAQ #24.

var 2>&1 | tee $LOGV 

... как любой трубопровод оболочки, имеет возможность запускать функцию var внутри подпроцесса - и, на практике, ведет себя таким образом в Баш. (Спецификация POSIX sh оставляет информацию о том, какие компоненты конвейера, если таковые имеются, выполняются внутри родительской оболочки undefined).


Избегайте этого так же просто, как не использовать трубопровод.

var > >(tee "$LOGV") 2>&1 

... использует процесс замены (расширение КШ, принятое Баш, не присутствующую в POSIX ш) представлять tee подпроцесс через имя файла (в виде /dev/fd/## на современном Linux), который выход может быть перенаправлен без перемещения функции в конвейер.


Если вы хотите, чтобы убедиться, что tee выходов перед другими командами запуска, используйте блокировку:

#!/bin/bash 
logv=/tmp/log 

collect_var() { 
     echo "value for var:" 
     read -re var 
} 
collect_var > >(logv="$logv" flock "$logv" -c 'exec tee "$logv"') 2>&1 
flock "$logv" -c true # wait for tee to exit 

echo "This is var: $var" 

Кстати, если вы хотите запустить несколько команд с их выходом которого поступает в этом Вы должны вызывать tee только один раз и подавать в него по необходимости:

#!/bin/bash 
logv=/tmp/log 
collect_var() { echo "value for var:"; read -re var; } 

exec 3> >(logv="$logv" flock "$logv" -c 'exec tee "$logv"') # open output to log 
collect_var >&3 2>&3   # run function, sending stdout/stderr to log 
echo "This is var: $var" >&3 # ...and optionally run other commands the same way 
exec 3>&-     # close output 
flock "$logv" -c true  # ...and wait for tee to finish flushing and exit. 
+0

Благодарим вас за ответ, но при использовании рекомендованных методов есть некоторые препятствия: 1) Во время первого варианта файл журнала не получает окончательную часть эха +, она не добавляется (легко управляется 'tee -a ', хотя); 2) Здесь происходит какое-то неожиданное поведение: 1) вставленное значение foo печатается с эхо-строкой, например: 'fooThis - VAR: foo'; 2) Echo не перенаправляется в файл; 3) Сценарий не выходит после повторения «fooThis является VAR: foo', однако он запрашивает ввод: ' [root @ testbox ~] # ' – LinenG

+0

Не думаю, что я следую тому, что вы пытаетесь чтобы достичь достаточно хорошо, чтобы высказанные выше возражения имели смысл. Не могли бы вы расширить свой вопрос, чтобы точно описать, какое содержимое вы ожидаете в файле журнала после запуска команды, и точно указать, какое поведение или результат приводит к тому, что сценарий не выходит, когда он должен? (Что касается (1), ваш исходный код на основе труб не добавлялся к logv, поэтому я не понимаю, почему это проблема, которая этого не делает). –

+0

Charles Duffy, конечная цель состоит в том, чтобы иметь функцию с определенными глобальными переменными внутри, которые могут использоваться вне функции при перенаправлении stdout/stderr выполнения сценария в файл и экран. P.S. Вы правы, мой плохой, я не упоминал о добавлении, извините. – LinenG

 Смежные вопросы

  • Нет связанных вопросов^_^