Сценарии SHELL
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, может не работать в командных оболочках ksh, csh или 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