При вызове Shell в командной строке можно указать пять флагов. Эти флаги нельзя включить командой set.
-i Если указан этот флаг, или ввод и вывод Shell оба подключены к терминалу, то Shell является интерактивным. В таком Shell'е INTERRUPT (сигнал 2) перехватывается и игнорируется, а TERMINATE (сигнал 15) и QUIT (сигнал 3) игнорируются.
-s Если указан этот флаг или нет никаких аргументов переадресации ввода-вывода, то Shell считывает команды из стандартного ввода. Вывод Shell записывается в файл с дескриптором 2. Все остальные аргументы обозначают позиционные параметры.
-c Когда указан этот флаг, Shell считывает команды из первой строки, следующей после флага. Все остальные аргументы игнорируются.
-t Когда указан этот флаг, то считывается и выполняется только одна команда и затем происходит выход из Shell. Этот флаг рекомендуется использовать с Си-программами.
-r Если указан этот флаг, то Shell является усеченной версией Shell (см. rsh(C)).
В этом разделе приводятся стратегии написания эффективных процедур Shell, которые не тратят лишние ресурсы при выполнении поставленных задач. Основной задачей является достижение желаемого результата с минимальными затратами. Акцент всегда должен ставиться на простоту, ясность и удобочитаемость, но эффективность может быть достигнута при использовании определенных стратегий программирования. Во многих случаях переорганизация процедуры повышает ее эффективность за счет уменьшения размера, и часто облегчает ее понимание. В любом случае, вы можете не оптимизировать процедуры Shell, пока они вас устраивают по быстродействию и ресурсов системы хватает для ее выполнения.
Создание процедуры Shell состоит из таких же шагов, как и написание обычных программ: написания текста, определения его размера и оптимизации только отдельных важных частей. Пользователь должен уметь свободно пользоваться командой time, которую можно использовать для определения времени выполнения как всей процедуры, так и ее частей. Мы настоятельно рекомендуем пользоваться ей, т.к. человеческая интуиция непригодна для оценки времени выполнения программ. Каждый тест должен быть выполнен несколько раз, т.к. его результаты могут зависеть от загруженности системы в данный момент.
Когда выполняется большое число коротких команд, то действительное время выполнения может быть значительно увеличено за счет создания вспомогательных процессов. Процедурами, для которых требуются значительные количества таких процессов, как правило являются процедуры, в которых выполняется много циклов и которые генерируют командные последовательности, которые должны интерпретироваться другим Shell.
Если вас беспокоит эффективность выполнения, вам надо знать, какие команды являются встроенными в Shell, а какие нет. Ниже приводится список всех встроенных команд:
break case cd continue echo
eval exec exit export for
if read readonly return set
shift test times trap umask
until wait while . :
{}
Обычные скобки () также являются встроенной командой, но команда, заключенная в них, выполняется как дочерний процесс, т.е. Shell разветвляется. Все остальные команды, не указанные в списке, являются внешними (требуют fork и exec).
Пользователь должен всегда хотя бы приблизительно знать число процессов, генерируемых процедурой. Для всех приведенных ранее процедур число генерируемых (не обязательно одновременно) процессов может быть оценено по формуле:
число процессов = (k*n) + c
где k и с - это константы, а n может быть количеством аргументов процедуры, количеством строк во входном файле, количеством файлов в каталоге и т.п. Повышение эффективности обычно достигается за счет уменьшения константы k.
В качестве примера проанализируем процедуру с именем split, чей текст проведен ниже:
:
# split
trap 'rm temp$$; trap 0; exit' 0 1 2 3 15
start1=0 start2=0
b='[A-Za-z]'
cat > temp$$
# read stdin into temp file
# save original lengths of $1,$2
if test -s "$1"
then start1=`wc -l < $1`
fi
if test -s "$2"
then start2=`wc -l < $2`
fi
grep "$b" temp$$ >> $1
# lines with letters onto $1
grep -v "$b" temp$$ | grep '[0-9]' >> $2
# lines without letters onto $2
total=" `wc -l< temp$$` "
end1=" `wc -l< $1` "
end2=" `wc -l< $2` "
lost=" `expr $total - \($end1 - $start1\)\
- \($end2 - $start2\)` "
echo "$total read, $lost thrown away"
Для каждой итерации в цикле имеется одна команда expr и либо команда echo или другая команда expr. Еще одна дополнительная команда echo выполняется в конце процедуры. Если n - число строк на вводе, то количество процессов равно 2*n+1.
Некоторые разновидности процедур не следует писать на Shell'е. Так, например, если с каждым символом файла связан один или несколько процессов, хорошим решением будет перенос процедуры на язык Си. Shell-процедуры не следует использовать для посимвольного сканирования или посимвольного формирования файлов.