Искусство программирования на языке сценариев командной оболочки
Шрифт:
Сценарий, в котором строки отделяются друг от друга в стиле MS-DOS (\r\n), будет завершаться аварийно, поскольку комбинация #!/bin/bash\r\n считается недопустимой. Исправить эту ошибку можно простым удалением символа \r из сценария.
#!/bin/bash
echo "Начало"
unix2dos $0 # Сценарий переводит символы перевода строки в формат DOS.
chmod 755 $0 # Восстановление прав на запуск.
# Команда 'unix2dos' удалит право на запуск из атрибутов файла.
./$0 #
# Но это не сработает из-за того, что теперь строки отделяются
# друг от друга в стиле DOS.
echo "Конец"
exit 0
Сценарий, начинающийся с #!/bin/sh, не может работать в режиме полной совместимости с Bash. Некоторые из специфических функций, присущих Bash, могут оказаться запрещенными к использованию. Сценарий, который требует полного доступа ко всем расширениям, имеющимся в Bash, должен начинаться строкой #!/bin/bash.
Сценарий не может экспортировать переменные родительскому процессу - оболочке. Здесь как в природе, потомок может унаследовать черты родителя, но не наооборот.
WHATEVER=/home/bozo
export WHATEVER
exit 0
bash$ echo $WHATEVER
bash$
Будьте уверены -- при выходе в командную строку переменная $WHATEVER останется неинициализированной.
Использование в подоболочке переменных с теми же именами, что и в родительской оболочке может не давать ожидаемого результата.
Пример 31-1. Западня в подоболочке
#!/bin/bash
# Западня в подоболочке.
outer_variable=внешняя_переменная
echo
echo "outer_variable = $outer_variable"
echo
(
# Запуск в подоболочке
echo "внутри подоболочки outer_variable = $outer_variable"
inner_variable=внутренняя_переменная # Инициализировать
echo "внутри подоболочки inner_variable = $inner_variable"
outer_variable=внутренняя_переменная # Как думаете? Изменит внешнюю переменную?
echo "внутри подоболочки outer_variable = $outer_variable"
# Выход из подоболочки
)
echo
echo "за пределами подоболочки inner_variable = $inner_variable" # Ничего не выводится.
echo "за пределами подоболочки outer_variable = $outer_variable" # внешняя_переменная.
echo
exit 0
Передача вывода от echo по конвейеру команде read может давать неожиданные результаты. В этом сценарии, команда read действует так, как будто бы она была запущена в подоболочке. Вместо нее лучше использовать команду set (см. Пример 11-14).
Пример 31-2. Передача вывода от команды echo команде read, по конвейеру
#!/bin/bash
# badread.sh:
# Попытка использования 'echo' и 'read'
#+ для записи значений в переменные.
a=aaa
b=bbb
c=ccc
echo "один два три" | read a b c
# Попытка записать значения
echo
echo "a = $a" # a = aaa
echo "b = $b" # b = bbb
echo "c = $c" # c = ccc
# Присваивания не произошло.
# ------------------------------
# Альтернативный вариант.
var=`echo "один два три"`
set -- $var
a=$1; b=$2; c=$3
echo "-------"
echo "a = $a" # a = один
echo "b = $b" # b = два
echo "c = $c" # c = три
# На этот раз все в порядке.
# ------------------------------
# Обратите внимание: в подоболочке 'read', для первого варианта, переменные присваиваются нормально.
# Но только в подоболочке.
a=aaa # Все сначала.
b=bbb
c=ccc
echo; echo
echo "один два три" | ( read a b c;
echo "Внутри подоболочки: "; echo "a = $a"; echo "b = $b"; echo "c = $c" )
# a = один
# b = два
# c = три
echo "-------"
echo "Снаружи: "
echo "a = $a" # a = aaa
echo "b = $b" # b = bbb
echo "c = $c" # c = ccc
echo
exit 0
Огромный риск, для безопасности системы, представляет использование в скриптах команд, с установленным битом "suid" [ 61 ] .
61
Установка этого бита на файлы сценариев не имеет никакого эффекта.
Использование сценариев в качестве CGI-приложений может приводить к серьезным проблемам из-за отсутствия контроля типов переменных. Более того, они легко могут быть заменены взломщиком на его собственные сценарии.
Bash не совсем корректно обрабатывает строки, содержащие двойной слэш (//).
Сценарии на языке Bash, созданные для Linux или BSD систем, могут потребовать доработки, перед тем как они смогут быть запущены в коммерческой версии UNIX. Такие сценарии, как правило, используют GNU-версии команд и утилит, которые имеют лучшую функциональность, нежели их аналоги в UNIX. Это особенно справедливо для таких утилит обработки текста, как tr.
Danger is near thee --
Beware, beware, beware, beware.
Many brave hearts are asleep in the deep.
So beware --
Beware.
A.J. Lamb and H.W. Petrie
Глава 32. Стиль программирования
Возьмите в привычку структурный и систематический подход к программированию на языке командной оболочки. Даже для сценариев "выходного дня" и "писаных на коленке", не поленитесь, найдите время для того, чтобы разложить свои мысли по полочкам и продумать структуру будущего скрипта прежде чем приниматься за кодирование.