Сценарии SHELL

Linux

splinter

Hello world

По аналогии с практически любым курсом по программированию, мы начнем работу с разработки сценария hello_world. Следующий сценарий будет выводить строку Hello World.

echo Hello World

После создания этого простого сценария в редакторе vi или с помощью команды echo вам придется выполнить команду chmod +x hello_world для того, чтобы сделать файл сценария исполняемым. В том случае, если вы не будете добавлять путь к директории с вашими сценариями в список директорий из переменной окружения PATH, вам придется вводить полный путь к сценарию для того, чтобы командная оболочка смогла найти его.

[paul@RHEL4a ~]$ echo echo Hello World > hello_world [paul@RHEL4a ~]$ chmod +x hello_world [paul@RHEL4a ~]$ ./hello_world Hello World [paul@RHEL4a ~]$

She-bang

Давайте немного доработаем наш пример, разместив строку #!/bin/bash в начале сценария. Последовательность символов #! называется she-bang (или иногда sha-bang), причем слово she-bang составлено из названий двух первых символов сценария.

#!/bin/bash echo Hello World

Вы ни при каких обстоятельствах не можете быть уверены в том, какая командная оболочка используется в системе пользователя. Сценарий, превосходно работающий в командной оболочке bash, может не работать в командных оболочках kshcsh или dash. Для того, чтобы проинструктировать командную оболочку о необходимости запуска вашего сценария в определенной командной оболочке, вы должны начинать ваш сценарий с последовательности символов she-bang, после которой должен располагаться путь к бинарному файлу командной оболочки, в которой сценарий должен исполняться. Приведенный ниже сценарий будет исполняться в командной оболочке bash.

#!/bin/bash echo -n hello echo Дочерняя командная оболочка bash `echo -n hello`

А этот сценарий будет исполняться в командной оболочке Korn shell (за исключением тех случаев, когда по пути /bin/ksh расположена жесткая ссылка на бинарный файл /bin/bash). Файл /etc/shells содержит список путей к командным оболочкам, установленным в вашей системе.

#!/bin/ksh echo -n hello echo Дочерняя командная оболочка Korn shell `echo -n hello`

Комментарий

Давайте еще немного усовершенствуем наш пример, добавив строки комментариев.

#!/bin/bash # # Сценарий Hello World # echo Hello World

Переменные

Ниже приведен простой пример объявления переменной в сценарии.

#!/bin/bash # # простая переменная в сценарии # var1=4 echo var1 = $var1

Сценарии могут содержать переменные, но ввиду того, что сценарии исполняются в своих собственных экземплярах командных оболочек, переменные не смогут пережить момент завершения исполнения сценария.

[paul@RHEL4a ~]$ echo $var1 [paul@RHEL4a ~]$ ./vars var1 = 4 [paul@RHEL4a ~]$ echo $var1 [paul@RHEL4a ~]$

Использование рабочей командной оболочки

К счастью, у вас имеется возможность исполнения сценария в той же рабочей командной оболочке; данная техника называется использованием рабочей командной оболочки (sourcing a script).

[paul@RHEL4a ~]$ source ./vars var1 = 4 [paul@RHEL4a ~]$ echo $var1 4 [paul@RHEL4a ~]$

Представленная выше команда аналогична следующей команде.

[paul@RHEL4a ~]$ . ./vars var1 = 4 [paul@RHEL4a ~]$ echo $var1 4 [paul@RHEL4a ~]$ 

Отладка сценария

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

paul@debian6~/test$ bash runme 42

Дополнение данной команды до формы bash -x позволит вам ознакомиться со всеми командами, исполняемыми командной оболочкой (после раскрытия команд).

paul@debian6~/test$ bash -x runme + var4=42 + echo 42 42 paul@debian6~/test$ cat runme # сценарий runme var4=42 echo $var4 paul@debian6~/test$

Обратите внимание на отсутствие строки комментария (первым символом которой является символ #), а также замену значения переменной перед исполнением команды для вывода данных echo.

Предотвращение подмены имен файлов сценариев с целью повышения привилегий в системе

Какой-либо пользователь может попытаться выполнить сценарий с установленным битом setuid с целью повышения привилегий в системе, подменив имя файла этого сценария путем создания ссылки на него (root spoofing). Это довольно редкая, но возможная атака. Для повышения безопасности функционирования вашего сценария, а также для предотвращения подмены имен файлов сценариев, вам необходимо добавить после строки #!/bin/bash параметр --, который позволит деактивировать механизм обработки параметров, благодаря чему командная оболочка не примет дополнительных параметров.

#!/bin/bash -

или

#!/bin/bash --

Любые аргументы, расположенные после последовательности символов -- будут рассматриваться как имена файлов и аргументы. Аргумент - эквивалентен аргументу --.

 

Команда eval

Команда eval позволяет интерпретировать переданные аргументы как директивы сценария командной оболочки (результирующие команды исполняются). Данное обстоятельство позволяет использовать значение переменной в качестве переменной.

paul@deb503:~/test42$ answer=42 paul@deb503:~/test42$ word=answer paul@deb503:~/test42$ eval x=\$$word ; echo $x 42

Как в командной оболочке bash, так и командной оболочке Korn shell аргументы могут экранироваться с помощью двойных кавычек.

kahlan@solexp11$ answer=42 kahlan@solexp11$ word=answer kahlan@solexp11$ eval "y=\$$word" ; echo $y 42

Иногда команде eval необходимо передавать аргументы таким образом, чтобы командной оболочкой осуществлялся их корректный разбор. Рассмотрите приведенный ниже пример, в котором команда date принимает один параметр, являющийся строкой "1 week ago".

paul@debian6~$ date --date="1 week ago" Чт мар 8 21:36:25 CET 2012

В том случае, если мы сохраняем данную команду в переменную, исполнение команды из этой переменной будет заканчиваться неудачей до того момента, когда мы начнем использовать команду eval.

paul@debian6~$ lastweek='date --date="1 week ago"' paul@debian6~$ $lastweek date: лишний операнд `ago"' По команде `date --help' можно получить дополнительную информацию. paul@debian6~$ eval $lastweek Чт мар 8 21:36:39 CET 2012

Оператор (( ))

Оператор (( )) позволяет сравнивать числовые значения.

paul@deb503:~/test42$ (( 42 > 33 )) && echo true || echo false true paul@deb503:~/test42$ (( 42 > 1201 )) && echo true || echo false false paul@deb503:~/test42$ var42=42 paul@deb503:~/test42$ (( 42 == var42 )) && echo true || echo false true paul@deb503:~/test42$ (( 42 == $var42 )) && echo true || echo false true paul@deb503:~/test42$ var42=33 paul@deb503:~/test42$ (( 42 == var42 )) && echo true || echo false false

Команда let

Встроенная команда командной оболочки let инструктирует командную оболочку о необходимости вычисления значений арифметических выражений. Она будет возвращать значение 0, если результат последней арифметической операции не равен 0.

[paul@RHEL4b ~]$ let x="3 + 4" ; echo $x 7 [paul@RHEL4b ~]$ let x="10 + 100/10" ; echo $x 20 [paul@RHEL4b ~]$ let x="10-2+100/10" ; echo $x 18 [paul@RHEL4b ~]$ let x="10*2+100/10" ; echo $x 30

Команда let также может использоваться для перевода значений в различные системы счисления.

[paul@RHEL4b ~]$ let x="0xFF" ; echo $x 255 [paul@RHEL4b ~]$ let x="0xC0" ; echo $x 192 [paul@RHEL4b ~]$ let x="0xA8" ; echo $x 168 [paul@RHEL4b ~]$ let x="8#70" ; echo $x 56 [paul@RHEL4b ~]$ let x="8#77" ; echo $x 63 [paul@RHEL4b ~]$ let x="16#c0" ; echo $x 192

Существует различие между непосредственным присваиванием значения переменной и использованием команды let для расчета значений арифметических выражений (даже в том случае, если с помощью данной команды осуществляется исключительно присваивание значения переменной).

kahlan@solexp11$ dec=15 ; oct=017 ; hex=0x0f kahlan@solexp11$ echo $dec $oct $hex 15 017 0x0f kahlan@solexp11$ let dec=15 ; let oct=017 ; let hex=0x0f kahlan@solexp11$ echo $dec $oct $hex 15 15 15

Оператор case

В некоторых случаях вы можете упростить конструкции из вложенных условных переходов if, воспользовавшись конструкцией case.

[paul@RHEL4b ~]$ ./help Какое животное вы видите ? лев Лучше всего быстро убегать! [paul@RHEL4b ~]$ ./help Какое животное вы видите ? собака Не беспокойтесь, угостите ее печеньем. [paul@RHEL4b ~]$ cat help #!/bin/bash # # Советы по обращению с дикими животными # echo -n "Какое животное вы видите ? " read animal case $animal in "лев" | "тигр") echo "Лучше всего быстро убегать!" ;; "кот") echo "Выпустите мышь..." ;; "собака") echo "Не беспокойтесь, угостите ее печеньем." ;; "курица" | "гусь" | "утка" ) echo "Яйца на завтрак!" ;; "лигр") echo "Подойдите и скажите: 'Ах ты, большой пушистый котенок...'." ;; "вавилонская рыбка") echo "Она выпала из вашего уха ?" ;; *) echo "Вы обнаружили неизвестное животное, дайте ему имя!" ;; esac [paul@RHEL4b ~]$

Функции сценариев командной оболочки

Функции сценариев командной оболочки могут использоваться для логической группировки команд.

kahlan@solexp11$ cat funcs.ksh #!/bin/ksh  function greetings { echo Hello World! echo а также приветствуем пользователя $USER! } echo Сейчас мы вызовем функцию greetings echo Конец

А это пример вывода данного сценария командной оболочки с функцией.

kahlan@solexp11$ ./funcs.ksh Сейчас мы вызовем функцию Hello World! а также приветствуем пользователя kahlan! Конец

Функция сценария командной оболочки также может принимать параметры.

kahlan@solexp11$ cat addfunc.ksh #!/bin/ksh  function plus { let result="$1 + $2" echo $1 + $2 = $result } plus 3 10 plus 20 13 plus 20 22

Данный сценарий генерирует следующий вывод:

kahlan@solexp11$ ./addfunc.ksh 3 + 10 = 13 20 + 13 = 33 20 + 22 = 42