Сценарий оболочки, который пишет сценарий оболочки - PullRequest
0 голосов
/ 05 сентября 2010

Два вопроса: как я могу записать переменную оболочки из этого скрипта в дочерний скрипт?

Есть ли более простые способы сделать это?

Если вы не можете следовать тому, что яя делаю, я:

1) начиная со списка каталогов, имена которых будут сохранены как значения, взятые $ i

2) cd'ing к каждому значению $ iи ls'ing его содержимое

3) отображение его содержимого в новом скрипте с именем каталога через cat

4) использование echo и cat для написания нового скрипта, содержащего lsd $ i и отправляет их на электронный адрес блога, который называется $i@tumblr.com

#/bin/sh
read -d '' commands <<EOF

#list of directories goes here
dir1
dir2
dir3
etc...    

EOF

for i in $commands
do

cd $SPECIALPATH/$i
echo ("#/bin/sh \n read -d '' directives <<EOF \n") | cat >> $i.sh
ls | cat >> $i.sh
echo ("EOF \n for q in $directives \n do \n uuencode $q $q | sendmail $i \n done \n") | cat >> $i.sh
# NB -- I am asking the script to write the shell variable $i into the new
# script, called $i.sh, as the email address specified, in the middle of an
# echo statement... I am well aware that it doesn't work as is
chmod +x $i.sh
./$i.sh    

done

Ответы [ 3 ]

5 голосов
/ 05 сентября 2010

Вы часто злоупотребляете кошачьими - вам нужно просто перенаправить, а не пайп к cat, который добавляется.

Вы можете избежать промежуточного файла $i.sh, связав весь вывод, который идет в файлс одним перенаправлением ввода / вывода, которое направляет канал непосредственно в оболочку - нет необходимости в очистке промежуточного файла (вы не показали, что это происходит) или операции chmod.

Я бы сделал этоиспользуя фигурные скобки:

{
echo "..."
ls
echo "..."
} | sh

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

#/bin/sh
read -d '' commands <<EOF

#list of directories goes here
dir1
dir2
dir3
etc...    

EOF

for i in $commands
do
    (
    cd $SPECIALPATH/$i
    ls |
    while read q
    do uuencode $q $q | sendmail $i
    done
    )
done

Я предполагаю, что команда sendmail работает - это не так, как япопробуйте отправить письмо.Я бы, вероятно, использовал mailx или что-то подобное, и я бы тоже не стал использовать uuencode (я бы использовал кодировку base-64, оставленную для моих собственных устройств):

    do uuencode $q $q | mailx -s "File $q" $i@tumblr.com

Скрипт также использует круглые скобки вокруг команды cd.Это означает, что команда cd и последующие выполняются в под-оболочке, поэтому родительский скрипт не меняет каталог.В этом случае с абсолютным путем к $ SPECIALDIR это не будет иметь большого значения.Но, как правило, это часто облегчает жизнь, если вы изолируете такие изменения в каталогах.

Я бы, вероятно, еще больше упростил его для общего повторного использования (хотя мне нужно было бы добавить что-то, чтобы убедиться, что SPECIALPATHустановить соответствующим образом):

#/bin/sh

for i in "$@"
do
    (
    cd $SPECIALPATH/$i
    ls |
    while read q
    do uuencode $q $q | sendmail $i
    done
    )
done

Затем я могу вызвать его с помощью:

script-name $(<list-of-dirs)

Это означает, что без редактирования сценария его можно повторно использовать для любого списка каталогов.


Промежуточный шаг 1:

for i in $commands
do
    (
    cd $SPECIALPATH/$i
    {
    echo "read -d '' directives <<EOF"
    ls 
    echo "EOF"
    echo "for q in $directives"
    echo "do"
    echo "    uuencode $q $q | sendmail $i"
    echo "done"
    } |
    sh
    )
done

Лично мне легче читать сгенерированный скрипт, если генерирующий код делает сгенерированный скрипт понятным - используя несколько команд echo.Это включает в себя отступ кода.

Промежуточный шаг 2:

for i in $commands
do
    (
    cd $SPECIALPATH/$i
    {
    ls |
    echo "while read q"
    echo "do"
    echo "    uuencode $q $q | sendmail $i"
    echo "done"
    } |
    sh
    )
done

Мне не нужно считывать данные в переменную, чтобы пройти по каждому элементу списка один раз - просточитать каждую строку по очереди.Механизм while read часто также полезен для разбиения строки на несколько переменных: while read var1 var2 var3 junk будет читать первое поле в $var1, второе в $var2, третье в $var3, и если что-то осталосьболее, это входит в $junk.Если вы сгенерировали данные точно, мусора не будет;но иногда приходится иметь дело с данными других людей.

1 голос
/ 05 сентября 2010

Если вы экспортируете переменную

export VAR1=FOO

, она будет присутствовать во всех дочерних процессах.

Если вы посмотрите на сценарии инициализации, /etc/init..d/ * вы заметите, что многие исходники представляют другой файл, полный «внешних» определений.Вы можете настроить такой файл и получить от этих файлов ваш дочерний скрипт.

1 голос
/ 05 сентября 2010

Если сгенерированный скрипт предназначен для временного использования, я не буду использовать файлы. Кроме того, chmoding их исполняемым звучит небезопасно. Когда мне нужно было выполнить параллельное выполнение сценариев, я использовал сценарий bash, чтобы сформировать набор команд (в массиве, разделить массив на две части, затем развернуть массив) в одну строку, разделенную \n, и затем передать ее новый экземпляр bash.

В основном, в bash:

for orig in "$@"
do
    commands="$commands echo \"echoeing stuff here for arguments $orig\" \n"
done 

echo -e $commands |bash 

И небольшой совет: если сценарий не нуждается в надзоре, добавьте & после переданного по каналу bash, чтобы заставить ваш первый сценарий завершить работу, а остальная часть работы разветвляется.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...