Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > *NIX системы: Общие вопросы > Bash - вернуть значение переменной из дочернего


Автор: savigm 29.3.2009, 00:48
Всем добрый день.

На форуме нет отдельной темы по Linux оболочке Bash, предлагаю все вопросы, касающиеся Bash обсуждать в этой теме.

Я изложу суть своего вопроса:
Есть первый скрипт, вызывающий второй. Второй является дочерним процессом первого. Вопрос: как можно вернуть значение переменной из второго скрипта (дочернего процесса) в первый (родительский процесс)? У меня пока только идея сохранить его в файл во втором скрипте и прочитать его в первом, но по-моему это кривое решение.

Автор: powerfox 29.3.2009, 00:57
Этой теме место в http://forum.vingrad.ru/forum/Linux-Unix-common-questions.html

savigm, скрипт всё равно, что программа: по завершении остаётся лишь вывод (если быть точным, то 2) + статус завершения.
Обычно скрипты взаимодейтсвуют, через конвеер: script1 | script2, таким образом стандартный вывод script1 является стандартным вводом для script2.
Если же нужно, чтобы возвращалось значение, то нужна функция (и то, возвращает то же, что может вернуть скрипт).

Автор: savigm 29.3.2009, 01:36
powerfox, второй скрипт может передать первому значение и без функций - exit <код возврата>, но так как идеологически код возврата 0 - норм. звершение программы(скрипта), не 0 - код ошибки мне бы хотелось передавать значение из второго скрипта(вызванного из первого) через переменную.

А насчет переноса темы по-моему это спорный вопрос: с одной стороны Bash - оболочка в Linux, с другой - коммандный язык программирования. Я думаю для Bash нужно две темы - одна по программированию в Bash(Bash-scripting), вторая по использованию и настройке.

Автор: Cr@$h 29.3.2009, 12:00
Модератор: Пожалуйста, один топик - один вопрос.
Правила форума: http://forum.vingrad.ru/index.php?act=boardrules
Модератор: bash - командный процессор. Тему по всем вопросам создавать нельзя. Поднимать вопрос о создании подфорума для оболочки POSIX нужно в разделах *nix

Автор: powerfox 29.3.2009, 12:50
Цитата(savigm @  29.3.2009,  02:36 Найти цитируемый пост)
powerfox, второй скрипт может передать первому значение и без функций - exit <код возврата>, но так как идеологически код возврата 0 - норм. звершение программы(скрипта), не 0 - код ошибки мне бы хотелось передавать значение из второго скрипта(вызванного из первого) через переменную.

Я об этом написал. Просто не всегда нужно передавать число.

Автор: savigm 29.3.2009, 14:43
Т.е. скрипт может возвращать не только число? Как? С помощью exit можно вернуть только числа [0..255]. Мне необходимо, чтобы второй скрипт возвращал 0 или не 0 информируя о нормальном завершении, либо о номере ошибки, собственно как это и должно быть, но нужно еще передать и строковую переменную. Здесь уже видимо без создания временного файла не обойтись.

Автор: xaran4o 29.3.2009, 19:33
Цитата

мне бы хотелось передавать значение из второго скрипта(вызванного из первого) через переменную.


Переменная определенная в "родительском" скрипте с префиксом export, видна в "дочернем". smile  smile 

Автор: powerfox 29.3.2009, 21:40
Цитата(savigm @  29.3.2009,  15:43 Найти цитируемый пост)
Т.е. скрипт может возвращать не только число? Как? С помощью exit можно вернуть только числа [0..255]. Мне необходимо, чтобы второй скрипт возвращал 0 или не 0 информируя о нормальном завершении, либо о номере ошибки, собственно как это и должно быть, но нужно еще передать и строковую переменную. Здесь уже видимо без создания временного файла не обойтись. 

Всё зависит от того, что у вас за скрипт2.

Цитата(xaran4o @  29.3.2009,  20:33 Найти цитируемый пост)
Переменная определенная в "родительском" скрипте с префиксом export, видна в "дочернем". smile  smile  

Видна не значит, что если её изменить в дочерней оболочке (именно в ней запустится скрипт), изменения затронут переменную в родительском. Механизма «обратного» экспорта не существует.

Есть команда '.', которая позволяет выполнить команды скрипты, за запуская дочернюю оболочку, но это не самый элегантый способ. Эта команда было специально создана для обновления .profile, а не для выполнения скриптов.


savigm, а чем не устраивает вывод второго скрипта?
Код

fox@linux-ltde:/> qwe=$(date)
fox@linux-ltde:/> echo $qwe
Вск Мар 29 22:32:30 MSD 2009


Если у скрипта есть дополнительный вывод, то можно использовать регулярные выражения (или sed/awk), чтобы получить значение из строки "MY_SUPER_SCRIPT_RESULT=qweqweqweqw".


Автор: gcc 29.3.2009, 22:02
Код

echo $QUERY_STRING;


если я правильно понял

Автор: savigm 29.3.2009, 22:10
Цитата(powerfox @  29.3.2009,  21:40 Найти цитируемый пост)
savigm, а чем не устраивает вывод второго скрипта?
Выделить всёБез подсветки
1:
2:
3:
    
fox@linux-ltde:/> qwe=$(date)
fox@linux-ltde:/> echo $qwe
Вск Мар 29 22:32:30 MSD 2009


Если у скрипта есть дополнительный вывод, то можно использовать регулярные выражения (или sed/awk), чтобы получить значение из строки "MY_SUPER_SCRIPT_RESULT=qweqweqweqw".

Обьясню: в первом скрипте читаются статусные файлы, читаются директории и т.п., на основании этой информации идет часть выдачи, потом выполняется программа, на основании результата(результат пишется в файл) выполненной программы идет остальная выдача. По предложенному варианту эта выдача будет идти сразу, а не частями, а хотелось бы чтобы было как в первом скрипте: сначала первая часть выдачи, потом результат программы. Дублировать часть кода для первой части выдачи во втором скрипте неохота, тем более это будет двойная работа.

Автор: powerfox 30.3.2009, 01:19
Цитата(savigm @  29.3.2009,  23:10 Найти цитируемый пост)
Обьясню: в первом скрипте читаются статусные файлы, читаются директории и т.п., на основании этой информации идет часть выдачи, потом выполняется программа, на основании результата(результат пишется в файл) выполненной программы идет остальная выдача. По предложенному варианту эта выдача будет идти сразу, а не частями, а хотелось бы чтобы было как в первом скрипте: сначала первая часть выдачи, потом результат программы. Дублировать часть кода для первой части выдачи во втором скрипте неохота, тем более это будет двойная работа. 

Я не понял, что вы хотите. Во всяком случае это не соответствует тому, что вы спросили в начале темы.

Автор: Vaulter 30.3.2009, 01:35
Код

# Инициализация
# Препарация
. status_files
for file in .; do
#....
done


## НИКОГДА ТАК НЕ ПИШИ :) 

echo -n " ==> Exit with $?: "

if ( ERRSTR=$(my_very_needed_bin 2>>outerr.log) ); then echo "failed"; else echo "OK"; 

echo $ERRSTR


Добавлено через 1 минуту и 4 секунды
my_very_needed_bin может выводить в обычный и поток ошибок... если нужно, и еще вовращать статус выхода!

Этого достаточно? smile

Добавлено через 1 минуту и 45 секунд
$? - это.... артефакт smile  smile 

Автор: xaran4o 30.3.2009, 09:30
Цитата

powerfox.    Есть команда '.', которая позволяет выполнить команды скрипты, за запуская дочернюю оболочку, но это не самый элегантый способ. Эта команда было специально создана для обновления .profile, а не для выполнения скриптов.


поясните новичку, чем плоха комманда "."    Чревата коллизиями, это понятно, если используешь "чужой" скрипт. А еще? Если я пишу "родительский" и "дочерний" скрипты сам??

Автор: powerfox 30.3.2009, 14:23
Цитата(xaran4o @  30.3.2009,  10:30 Найти цитируемый пост)
поясните новичку, чем плоха комманда "."    Чревата коллизиями, это понятно, если используешь "чужой" скрипт. А еще? Если я пишу "родительский" и "дочерний" скрипты сам?? 


Тем, что нужно следить за именами функций и переменных. А если потом захочется один из скриптов использовать отдельно, то можно попасть в просак. Эта команда, как Goto в С/C++: мощная штука, но нужно применять с умом.

Автор: MAKCim 30.3.2009, 15:03
Цитата(savigm @  29.3.2009,  14:43 Найти цитируемый пост)
Т.е. скрипт может возвращать не только число? Как?

Код

#!/bin/bash

# parent script `parent'

var=$(child 2>/dev/null)

echo $var

Код

#!/bin/bash

# child script `child'

echo "1234656789"

Автор: savigm 30.3.2009, 15:07
Вобщем скрипты немного поменялись, переменную из дочернего скрипта передаю по подстановке команд: $var=`script1.sh`

Поясню на упрощенном примере, что мне нужно:

Первый скрипт - script1.sh:
Код

if [ ! -x program.bin ]; then
    exit 1
fi
echo -n "Run <$file> ......... "
./program.bin file1 > ${file}.log
if grep -q "OK" ${file}.log; then
    echo "[OK]"
elif grep -q "ERROR"; then
    echo "[ERROR]"
else
    echo "[ABEND]"
fi

Единственный параметр script1.sh - имя файла file, program bin при удачном завершении выдает "[OK]", при неудачном завершении "[ERROR]". Если программа завершилась ненормально(например по [Ctrl]+[C]) - выдается "[ABEND]". Код возврата script1.sh - 0 нормальное завершение, не 0 - ненормальное завершение(например отсутсвие файла program.bin).

Второй скрипт - script2.sh:
Код

all_files=`cat status.txt`
for file in $all_files; do
    echo -n "Run <$file> ......... "
    result=`./script1.sh $file`
    echo $result
done

Статусный файл соодержит имена файлов file для первого скрипта script1.sh.

Остается одна проблема: как анализировать код возврата первого скрипта, в случае ненулевого сразу завершить script2.sh.
Если сразу после
Код

result=`./script1.sh $file`

анализировать $? это и будет код возврата скрипта script1.sh, или это будет код возврата присвоения переменной result?

Автор: Vaulter 30.3.2009, 22:09
по первому script1.sh
зачем лишний файл лога? можно сразу
Код

if [ ! -x program.bin ]; then
    exit 1
fi

echo -n "Run <$file> ......... "
$ret=$(./program.bin $file 2> ${file}.err.log)

if [ "[OK]" = "$ret" ]; then
    echo "Ok";  //
    exit 0;
elif [ "[ERROR]" = "$ret]; then
    echo "Failed";
    exit 1;
else
    echo "Aborted"
    exit 2;
fi


Код

all_files=`cat status.txt`
for file in "$all_files"; do
    echo -n "Run <$file> ......... "
    out=`./script1.sh $file 2>&1`
    retval=$?
    echo "( $retval ) $out"

    if (( $? )); then echo "ERROR on $file"; fi

done


Автор: savigm 31.3.2009, 02:06
Vaulter, В первом скрипте нужен лог  выдачи program.bin для отдельных целей. Я так понимаю в $? будет именно код возврата скрипта script1.sh (./script1.sh $file), а не код возврата операции присвоения (result=`./script1.sh $file`)?

Автор: Vaulter 31.3.2009, 02:47
$? код возврата последнего завершившегося процесса.
присвоение, насколько я знаю - это не процесс.

Автор: savigm 5.4.2009, 00:48
powerfox
Vaulter, спасибо, тема по-моему вполне освещена, вывод следующий:
из дочернего скрипта, как правильно заметил powerfox, можно получить два результата - выдача и код возврата.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)