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

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 59 60 61 62 63 64 65 66 67 ... 96

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 и так далее.

1 ... 59 60 61 62 63 64 65 66 67 ... 96
На этой странице вы можете бесплатно читать книгу Искусство программирования на языке сценариев командной оболочки - Мендель Купер бесплатно.
Похожие на Искусство программирования на языке сценариев командной оболочки - Мендель Купер книги

Оставить комментарий