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

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 69 70 71 72 73 74 75 76 77 ... 96

var1 = 23 # Правильный вариант: 'var1=23'.

# В вышеприведенной строке Bash будет трактовать "var1" как имя команды

# с аргументами "=" и "23".

let c = $a - $b # Правильный вариант: 'let c=$a-$b' или 'let "c = $a - $b"'

if [ $a -le 5] # Правильный вариант: if [ $a -le 5 ]

# if [ "$a" -le 5 ] еще лучше.

# [[ $a -le 5 ]] тоже верно.

Ошибочным является предположение о том, что неинициализированные переменные содержат "ноль". Неинициализированные переменные содержат "пустое" (null) значение, а не ноль.

#!/bin/bash

echo "uninitialized_var = $uninitialized_var"

# uninitialized_var =

Часто программисты путают операторы сравнения = и -eq. Запомните, оператор = используется для сравнения строковых переменных, а -eq -- для сравнения целых чисел.

if [ "$a" = 273 ] # Как вы полагаете? $a -- это целое число или строка?

if [ "$a" -eq 273 ] # Если $a -- целое число.

# Иногда, такого рода ошибка никак себя не проявляет.

# Однако...

a=273.0 # Не целое число.

if [ "$a" = 273 ]

then

echo "Равны."

else

echo "Не равны."

fi # Не равны.

# тоже самое и для a=" 273" и a="0273".

# Подобные проблемы возникают при использовании "-eq" со строковыми значениями.

if [ "$a" -eq 273.0 ]

then

echo "a = $a'

fi # Исполнение сценария прерывается по ошибке.

# test.sh: [: 273.0: integer expression expected

Ошибки при сравнении целых чисел и строковых значений.

#!/bin/bash

# bad-op.sh

number=1

while [ "$number" < 5 ] # Неверно! должно быть while [ "number" -lt 5 ]

do

echo -n "$number "

let "number += 1"

done

# Этот сценарий генерирует сообщение об ошибке:

# bad-op.sh: 5: No such file or directory

Иногда, в операциях проверки, с использованием квадратных скобок ([ ]), переменные необходимо брать в двойные кавычки. См. Пример 7-6, Пример 16-4 и Пример 9-6.

Иногда сценарий не в состоянии выполнить команду из-за нехватки прав доступа. Если пользователь не сможет запустить команду из командной строки, то эта команда не сможет быть запущена и из сценария. Попробуйте изменить атрибуты команды, возможно вам придется установить бит suid.

Использование символа - в качестве оператора перенаправления (каковым он не является) может приводить к неожиданным результатам.

command1 2> - | command2 # Попытка передать сообщения об ошибках команде command1 через конвейер...

# ...не будет работать.

command1 2>& - | command2 # Так же бессмысленно.

Спасибо S.C.

Использование функциональных особенностей Bash версии 2 или выше, может привести к аварийному завершению сценария, работающему под управлением Bash версии 1.XX.

#!/bin/bash

minimum_version=2

# Поскольку Chet Ramey постоянно развивает Bash,

# вам может потребоваться указать другую минимально допустимую версию $minimum_version=2.XX.

E_BAD_VERSION=80

if [ "$BASH_VERSION" < "$minimum_version" ]

then

echo "Этот сценарий должен исполняться под управлением Bash, версии $minimum или выше."

echo "Настоятельно рекомендуется обновиться."

exit $E_BAD_VERSION

fi

...

Использование специфических особенностей Bash может приводить к аварийному завершению сценария в Bourne shell (#!/bin/sh). Как правило, в Linux дистрибутивах, sh является псевдонимом bash, но это не всегда верно для UNIX-систем вообще.

Сценарий, в котором строки отделяются друг от друга в стиле MS-DOS (rn), будет завершаться аварийно, поскольку комбинация #!/bin/bashrn считается недопустимой. Исправить эту ошибку можно простым удалением символа 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

# Попытка записать значения в переменные 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 ].

Использование сценариев в качестве 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. Стиль программирования

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

Ниже приводится несколько рекомендаций по оформлению сценариев, однако их не следует рассматривать как Официальное Руководство.

32.1. Неофициальные рекомендации по оформлению сценариев

 Комментируйте свой код. Это сделает ваши сценарии понятнее для других, и более простыми, в обслуживании, для вас.

 PASS="$PASS${MATRIX:$(($RANDOM%${#MATRIX})):1}"

 # Эта строка имела некоторый смысл в момент написания,

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

 # (Из сценария "pw.sh", автор: Antek Sawicki)

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

1 ... 69 70 71 72 73 74 75 76 77 ... 96
На этом сайте Вы можете читать книги онлайн бесплатно русская версия Искусство программирования на языке сценариев командной оболочки - Мендель Купер.
Книги, аналогичгные Искусство программирования на языке сценариев командной оболочки - Мендель Купер

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