KnigaRead.com/
KnigaRead.com » Компьютеры и Интернет » Программирование » Мендель Купер - Искусство программирования на языке сценариев командной оболочки

Мендель Купер - Искусство программирования на языке сценариев командной оболочки

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн Мендель Купер, "Искусство программирования на языке сценариев командной оболочки" бесплатно, без регистрации.
Перейти на страницу:

wait # Ожидание завершения работы подоболочек.


diff list123 list456

Перенаправление ввода/вывода в/из подоболочки производится оператором построения конвейера "|", например, ls -al | (command).

Блок команд, заключенный в фигурные скобки не приводит к запуску дочерней подоболочки.

{ command1; command2; command3; ... }


Глава 20. Ограниченный режим командной оболочки

Команды, запрещенные в ограниченном режиме командной оболочки

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

В ограниченном режиме запрещена команда cd -- смена текщего каталога.

Запрещено изменять переменные окружения $PATH, $SHELL, $BASH_ENV и $ENV.

Заперщен доступ к переменной $SHELLOPTS.

Запрещено перенаправление вывода.

Запрещен вызов утилит, в названии которых присутствует хотя бы один символ "слэш" (/).

Запрещен вызов команды exec для запуска другого процесса.

Запрещен ряд других команд, которые могут использовать сценарий для выполнения непредусмотренных действий.

Запрещен выход из ограниченного режима.

Пример 20-1. Запуск сценария в ограниченном режиме

#!/bin/bash

# Если sha-bang задать в таком виде: "#!/bin/bash -r"

# то это приведет к включению ограниченного режима с момента запуска скрипта.


echo


echo "Смена каталога."

cd /usr/local

echo "Текущий каталог: `pwd`"

echo "Переход в домашний каталог."

cd

echo "Текущий каталог: `pwd`"

echo


# До сих пор сценарий исполнялся в обычном, неограниченном режиме.


set -r

# set --restricted имеет тот же эффект.

echo "==> Переход в ограниченный режим. <=="


echo

echo


echo "Попытка сменить текущий каталог в ограниченном режиме."

cd ..

echo "Текущий каталог остался прежним: `pwd`"


echo

echo


echo "$SHELL = $SHELL"

echo "Попытка смены командного интерпретатора в ограниченном режиме."

SHELL="/bin/ash"

echo

echo "$SHELL= $SHELL"


echo

echo


echo "Попытка перенаправления вывода в ограниченном режиме."

ls -l /usr/bin > bin.files

ls -l bin.files # Попробуем найти файл, который пытались создать.


echo


exit 0


Глава 21. Подстановка процессов

Подстановка процессов -- это аналог подстановки команд. Операция подстановки команд записывает в переменную результат выполнения некоторой команды, например, dir_contents=`ls -al` или xref=$(grep word datafile). Операция подстановки процессов передает вывод одного процесса на ввод другого (другими словами, передает результат выполнения одной команды -- другой).

Шаблон подстановки команды

Внутри круглых скобок

>(command)

<(command)

Таким образом инициируется подстановка процессов. Здесь, для передачи результата работы процесса в круглых скобках, используются файлы /dev/fd/<n>.[ 49 ]

Между круглой скобкой и символом "<" или ">", не должно быть пробелов, в противном случае это вызовет сообщение об ошибке.

bash$ echo >(true)

/dev/fd/63


bash$ echo <(true)

/dev/fd/63

Bash создает канал с двумя файловыми дескрипторами, --fIn и fOut--. stdin команды true присоединяется к fOut (dup2(fOut, 0)), затем Bash передает /dev/fd/fIn в качестве аргумента команде echo. В системах, где отсутствуют файлы /dev/fd/<n>, Bash может использовать временные файлы. (Спасибо S.C.)

cat <(ls -l)

# То же самое, что и ls -l | cat


sort -k 9 <(ls -l /bin) <(ls -l /usr/bin) <(ls -l /usr/X11R6/bin)

# Список файлов в трех основных каталогах 'bin', отсортированный по именам файлов.

# Обратите внимание: на вход 'sort' поданы три самостоятельные команды.


diff <(command1) <(command2) # Выдаст различия в выводе команд.


tar cf >(bzip2 -c > file.tar.bz2) $directory_name

# Вызовет "tar cf /dev/fd/?? $directory_name" и затем "bzip2 -c > file.tar.bz2".

#

# Из-за особенностей, присущих некоторым системам, связанным с /dev/fd/<n>,

# канал между командами не обязательно должен быть именованным.

#

# Это можно сделать и так.

#

bzip2 -c < pipe > file.tar.bz2&

tar cf pipe $directory_name

rm pipe

# или

exec 3>&1

tar cf /dev/fd/4 $directory_name 4>&1 >&3 3>&- | bzip2 -c > file.tar.bz2 3>&-

exec 3>&-


# Спасибо S.C.


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

# Фрагмент сценария из дистрибутива SuSE:


while read des what mask iface; do

# Некоторые команды ...

done < <(route -n)


# Чтобы проверить это, попробуем вставить команду, выполняющую какие либо действия.

while read des what mask iface; do

echo $des $what $mask $iface

done < <(route -n)


# Вывод на экран:

# Kernel IP routing table

# Destination Gateway Genmask Flags Metric Ref Use Iface

# 127.0.0.0 0.0.0.0 255.0.0.0 U 0 0 0 lo


# Как указывает S.C. -- более простой для понимания эквивалент:

route -n |

while read des what mask iface; do # Переменные берут значения с устройства вывода конвейера (канала).

echo $des $what $mask $iface

done # На экран выводится то же самое, что и выше.

# Однако, Ulrich Gayer отметил, что ...

#+ этот вариант запускает цикл while в подоболочке,

#+ и поэтому переменные не видны за пределами цикла, после закрытия канала.


Глава 22. Функции

Подобно "настоящим" языкам программирования, Bash тоже имеет функции, хотя и в несколько ограниченном варианте. Функция -- это подпрограмма, блок кода который реализует набор операций, своего рода "черный ящик", предназначенный для выполнения конкретной задачи. Функции могут использоваться везде, где имеются участки повторяющегося кода.

function function_name { command... }

или

function_name () { command... }


Вторая форма записи ближе к сердцу C-программистам (она же более переносимая).

Как и в языке C, скобка, открывающая тело функции, может помещаться на следующей строке.

function_name () { command... }


Вызов функции осуществляется простым указанием ее имени в тексте сценария.

Пример 22-1. Простая функция

#!/bin/bash


funky ()

{

echo "Это обычная функция."

} # Функция должна быть объявлена раньше, чем ее можно будет использовать.


# Вызов функции.


funky


exit 0

Функция должна быть объявлена раньше, чем ее можно будет использовать. К сожалению, в Bash нет возможности "опережающего объявления" функции, как например в C.

f1

# Эта строка вызовет сообщение об ошибке, поскольку функция "f1" еще не определена.


declare -f f1 # Это не поможет.

f1 # По прежнему -- сообщение об ошибке.


# Однако...


f1 ()

{

echo "Вызов функции "f2" из функции "f1"."

f2

}


f2 ()

{

echo "Функция "f2"."

}


f1 # Функция "f2", фактически, не вызывается выше этой строки,

#+ хотя ссылка на нее встречается выше, до ее объявления.

# Это допускается.


# Спасибо S.C.


Допускается даже создание вложенных функций, хотя пользы от этого немного.

f1 ()

{


f2 () # вложенная

{

echo "Функция "f2", вложенная в "f1"."

}


}


f2 # Вызывает сообщение об ошибке.

# Даже "declare -f f2" не поможет.


echo


f1 # Ничего не происходит, простой вызов "f1", не означает автоматический вызов "f2".

f2 # Теперь все нормально, вызов "f2" не приводит к появлению ошибки,

#+ поскольку функция "f2" была определена в процессе вызова "f1".


# Спасибо S.C.


Объявление функции может размещаться в самых неожиданных местах.

ls -l | foo() { echo "foo"; } # Допустимо, но бесполезно.


if [ "$USER" = bozo ]

then

bozo_greet () # Объявление функции размещено в условном операторе.

{

echo "Привет, Bozo!"

}

fi


bozo_greet # Работает только у пользователя bozo, другие получат сообщение об ошибке.


# Нечто подобное можно использовать с определеной пользой для себя.

NO_EXIT=1 # Will enable function definition below.


[[ $NO_EXIT -eq 1 ]] && exit() { true; } # Определение функции в последовательности "И-список".

# Если $NO_EXIT равна 1, то объявляется "exit ()".

# Тем самым, функция "exit" подменяет встроенную команду "exit".


exit # Вызывается функция "exit ()", а не встроенная команда "exit".


# Спасибо S.C.


22.1. Сложные функции и сложности с функциями

Функции могут принимать входные аргументы и возвращать код завершения.

function_name $arg1 $arg2

Доступ к входным аргументам, в функциях, производится посредством позиционных параметров, т.е. $1, $2 и так далее.

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*