есть скрипт run.sh:
#!/bin/sh
clear
echo "$# parametrs"
my_inc=$@; #### пробовал my_inc='$@'
echo $my_inc;
include '$my_inc';
. $my_inc
clear
echo "$# parametrs"
my_inc=$@; #### пробовал my_inc='$@'
echo $my_inc;
include '$my_inc';
. $my_inc
$./run.sh my.sh
я хочу чтобы скрипт run.sh запускал файл, название которого передается как параметр
(последние две строки моего скрипта не делают этого)
вопросы :
1)почему это не проиходит?
2)можно ли как то запустить в консоли два скрипта в одной строке, так чтобы когда запустится второй скрипт, переменные с первого скрипта не уничтожились в памяти
пробовал :
$./script1.sh && ./script2.sh
$./script1.sh; ./script2.sh
не пашет, когда запускаетя второй скрипт, то уже первого скрипта переменные он не знает
-----------------
Думал, отвечу сейчас минут за пять, да и хорошо. А получилось как-то чуть по больше
Вопрос первый
В первом случае вместо апострофов, стоит использовать кавычки. Стринг в апострофах не вычисляется, а представляется просто набором символов:
[ant@CentOS 2]$ cat c;./c
#!/bin/bash
a="slon"
b='$a'
c=$a
d="$a"
echo a=$a
echo b=$b
echo c=$c
echo d=$d
#-EOF-
a=slon
b=$a
c=slon
d=slon
[ant@CentOS 2]$
#!/bin/bash
a="slon"
b='$a'
c=$a
d="$a"
echo a=$a
echo b=$b
echo c=$c
echo d=$d
#-EOF-
a=slon
b=$a
c=slon
d=slon
[ant@CentOS 2]$
var="what's this? it's a $cat ;)"
altvar=what\'s\ this?\ it\'s\ a\ $cat\ \;\)
altvar=what\'s\ this?\ it\'s\ a\ $cat\ \;\)
Вопрос второй
Вообще тут надо помнить, что каждый процесс имеет своё окружение. Так вот переменные этого окружения наследуются в порожденный процесс. Шелл использует понятие переменной как некий внутренний механизм, который с этим окружением никак не связан. Это всего лишь конструкция языка. В bash для того чтобы создать переменную окружения с таким же названием как и шелловская используется export. Т.о.
если
[ant@CentOS 2]$ a=foo
[ant@CentOS 2]$ b=bar
[ant@CentOS 2]$ export b
[ant@CentOS 2]$ cat >abc;chmod 755 abc
!#/bin/sh
echo a=$a
echo b=$b
^D
[ant@CentOS 2]$ b=bar
[ant@CentOS 2]$ export b
[ant@CentOS 2]$ cat >abc;chmod 755 abc
!#/bin/sh
echo a=$a
echo b=$b
^D
[ant@CentOS 2]$ ./abc
a=
b=bar
[ant@CentOS 2]$
a=
b=bar
[ant@CentOS 2]$
Обратное действие, т.е создание из переменной окружения, внутренней переменной, по умолчанию шелл выполняет автоматически при старте. Чем-то напоминает поведение php при magic_vars=1 и получении внешних параметров ;)
В примере из второго вопроса из текущего шелла сначала порождается один процесс со скриптом, а потом другой. Нет никакой возможности из порожденного процесса поменять окружение родительского (для обмена данными между двумя "живыми" процессами используются механизмы межпроцессного взаимодействия: каналы, сокеты, сообщения и т.д, но это уже выходит за рамки обычного скриптования).
Вообще говоря, поведение export требует более внимательного рассмотрения, а лучше всего почитать man :) Дело в том, что эта команда не просто создает переменную окружения. Она помечает внутреннюю переменную, для автоматического её дублирования в окружении. И как только переменная помечается, она тут же автоматически дублируется в окружение. При изменении помеченной переменной, изменится и соответствующая переменная окружения. Иначе пришлось бы каждый раз после изменения, выполнять
export var
Т.о. создается иллюзия что переменная "приобрела статус" переменной окружения. Более того!!! Если в текущем шелле есть такая переменная, то само собой она будет наследоваться в порожденный шелл(да и в любой другой порожденный процесс), но стоит обратить внимание, что в порожденном шелле она УЖЕ будет помечена, поскольку это довольно логично, помечать все что было созданно из перемнных окружения при запуске. Можно провести такой трюк. Например, есть скрипт который вызывает другой скрипт. Известно, что первый скрипт использует переменную slon, а второй скрипт делает, просто, echo $slon и ничего больше. Можно в ведущем шелле проинициализировать экспортируемую переменную slon. Вот что из этого получится.
[ant@CentOS 2]$ cat >script1&&cat >script2&&chmod 755 script[12]
#!/bin/sh
slon="some value"
./script2
#--EOF script1--
^D
#!/bin/sh
echo script2: slon=$slon
#--EOF script2--
^D
[ant@CentOS 2]$ export slon=
[ant@CentOS 2]$ ./script1
script2: slon=some value
[ant@CentOS 2]$
#!/bin/sh
slon="some value"
./script2
#--EOF script1--
^D
#!/bin/sh
echo script2: slon=$slon
#--EOF script2--
^D
[ant@CentOS 2]$ export slon=
[ant@CentOS 2]$ ./script1
script2: slon=some value
[ant@CentOS 2]$
[ant@CentOS 2]$ export -n slon
[ant@CentOS 2]$ ./script1
script2: slon=
[ant@CentOS 2]$
[ant@CentOS 2]$ ./script1
script2: slon=
[ant@CentOS 2]$
На заметку. Условие передачи окружения в порождаемый процесс не абсолютное - можно порождать процессы с окружением без переменных. Bash здесь не исключение, у него есть параметры с помощью которых можно изменить это условие. Так же с помощью специальных параметров команды set можно изменить это условие у текущего (выполняющего данный скрипт или ожидающего ввода команд) интерпретатора.
Итак, здесь возможны варианты:
1. В первом скрипте с помощью export вынести нужные переменные в его окружение, и породить второй процесс (из первого)
--script1--
#!/bin/sh
a=foo; b=bar; export a b
path=<path>
$path/script2
--script2--
#!/bin/sh
echo -e a=$a \\nb=$b
#!/bin/sh
a=foo; b=bar; export a b
path=<path>
$path/script2
--script2--
#!/bin/sh
echo -e a=$a \\nb=$b
--script1--
#!/bin/sh
a=foo; b=bar;
path=<path>
. $path/script2
#!/bin/sh
a=foo; b=bar;
path=<path>
. $path/script2
--script1--
#!/bin/sh
tmp=/tmp/sometemp
>$tmp
var1="Fee fie foe fum"
var2="I smell the blood of an english man"
var3="Be he live or be he dead"
var4="I'll grind his bones to make my bread"
dumpvars="var1 var2 var3 var4"
for vname in $dumpvars;do
echo $vname=\"${!vname}\" >>$tmp
done
--script2--
#!/bin/sh
tmp=/tmp/sometemp
. $tmp
echo var1=$var1
echo var2=$var2
echo var3=$var3
echo var4=$var4
rm -f $tmp
[ant@CentOS 2]$ ./script1 && ./script2
или
[ant@CentOS 2]$ ./script1; ./script2
#!/bin/sh
tmp=/tmp/sometemp
>$tmp
var1="Fee fie foe fum"
var2="I smell the blood of an english man"
var3="Be he live or be he dead"
var4="I'll grind his bones to make my bread"
dumpvars="var1 var2 var3 var4"
for vname in $dumpvars;do
echo $vname=\"${!vname}\" >>$tmp
done
--script2--
#!/bin/sh
tmp=/tmp/sometemp
. $tmp
echo var1=$var1
echo var2=$var2
echo var3=$var3
echo var4=$var4
rm -f $tmp
[ant@CentOS 2]$ ./script1 && ./script2
или
[ant@CentOS 2]$ ./script1; ./script2
name="value"
по сути это выражение как бы реализация $$val но в шеле это не может сработать потому как он воспринимает его как $$ и 'val', а $$ возвращает id текущего процесса. В более ранних реализация шелла (<V.2.xx) пришлось бы завести дополнительную переменную и записать как-то так:
eval var=\$$vname
Конечно возможны варианты передачи данных из одного процесса в другой по конвейеру, типа script1|script2 предварительно сжав их через gzip и прогнав base64 %))), либо вместо временного файла использовать unix socket, хотя я не пробовал работать с сокетами из скриптов, либо еще чего-нибудь эдакое замыслить интересное.
спасибо , получилось !!!!
ОтветитьУдалитьПоздравляю с первым сообщением в своем блоге! Подписался в Google Reader, буду ждать новостей с блога!!
еще вариант:
ОтветитьУдалить---run.sh----
#!/bin/bash
var=1
. $1
---my.sh---
#!/bin/bash
echo $var
$./run.sh my.sh
1
Простейший случай существенной разницы между этими вариантами -- использование команды exit в моем скрипте. В случае если скрипт вызывается bash script2 после неё произойдёт возврат в первый скрипт, если .script2 -- выход из первого скрипта.
ОтветитьУдалитьПо поводу первого комента. Дык я и описал этот случай у себя в варианте N2
ОтветитьУдалить--script1--
#!/bin/sh
a=foo; b=bar;
path=
. $path/script2
да и ты с него как раз и начинал - твой первый вопрос там где апострофы вместо кавык были. Но просто использовать $* или $@ более удобно, это позволит прокинуть параметры в последний вызываемый скрипт. Просто в своем описании я делал упор именно на механизм передачи данных от скрипта к скрипту, не вдаваясь в частности.
насчет второго комента не совсем понял, что ты хотел сказать. Если ты из скрипта вызываешь другой скрипт, то первый скрипт порождает процесс bash script2 и переходит в режим ожидания завершения этого потомка. Когда потомок завершается, первый скрипт просыпается и продолжает свое выполнение. А чего уж он там достигает, exit'а или конца файла, какая разница? В случае точки (source) порождения нового процесса не происходит, проосто содержимое второго скрипта добавляется в то место где эта точка стоит, и выполняется, все в рамках того же процесса
Кстати думаю тут будет втему
ОтветитьУдалитьhttp://ftp.sumylug.osdn.org.ua/pub/docs/mirrors/gazette.linux.ru.net/rus/articles/abs-guide/c3242.html#APPREF