Выбрать главу

Многие реализации Unix, включая GNU/Linux и OS X, устанавливают утилиту lockfile по умолчанию. Ее присутствие в системе можно проверить простой командой man 1 lockfile. Если в результате откроется страница справочного руководства, значит, удача сопутствует вам! Сценарий в листинге 1.22 предполагает наличие команды lockfile, и все последующие сценарии требуют работоспособности механизма надежной блокировки, реализованного в сценарии № 10, поэтому перед их использованием также проверьте наличие команды lockfile в вашей системе.

Код

Листинг 1.22. Сценарий filelock

··#!/bin/bash

··# filelock — Гибкий механизм блокировки файлов

··retries="10"·········· # Число попыток по умолчанию

··action="lock"··········# Действие по умолчанию

··nullcmd="’which true’" # Пустая команда для lockfile

··while getopts "lur: " opt; do

····case $opt in

······l) action="lock";;

······u) action="unlock";;

······r) retries="$OPTARG";;

····esac

··done

··shift $(($OPTIND — 1))

··if [$# −eq 0]; then # Вывести в stdout многострочное сообщение об ошибке.

····cat << EOF >&2

······Usage: $0 [-l|-u] [-r retries] LOCKFILE

······Where −l requests a lock (the default), −u requests an unlock, −r X

······specifies a max number of retries before it fails (default = $retries).

··EOF[2]

····exit 1

··fi

··# Проверка наличия команды lockfile.

··if [-z "$(which lockfile | grep −v '^no ')"]; then

····echo "$0 failed: 'lockfile' utility not found in PATH." >&2

····exit 1

··fi

··if ["$action" = "lock"]; then

····if! lockfile -1 −r $retries "$1" 2> /dev/null; then

······echo "$0: Failed: Couldn't create lockfile in time." >&2

······exit 1

····fi

··else # Действие = разблокировка

····if [! -f "$1"]; then

······echo "$0: Warning: lockfile $1 doesn't exist to unlock." >&2

······exit 1

····fi

····rm −f "$1"

··fi

··exit 0

Как это работает

Как это часто бывает с хорошо написанными сценариями командной оболочки, половину листинга 1.22 занимает анализ входных данных и проверка на наличие ошибок. Затем выполняется инструкция if и осуществляется фактическая попытка использовать системную команду lockfile. Она вызывается с заданным числом попыток и генерирует собственное сообщение об ошибке, если ей так и не удалось заблокировать файл. А что произойдет, если предложить сценарию снять блокировку (например, удалить файл-блокировку), которой в действительности нет? В результате будет сгенерировано другое сообщение об ошибке. В противном случае lockfile просто удалит блокировку.

Если говорить более конкретно, первый блок использует мощную функцию getopts для анализа всех поддерживаемых флагов (-l, −u, — r) в цикле while. Это наиболее типичный способ использования getopts, который снова и снова будет встречаться в книге. Обратите внимание на команду shift $(($OPTIND — 1)) в строке : переменная OPTIND устанавливается функцией getopts, благодаря чему сценарий получает возможность сдвинуть входные параметры вниз (то есть значение параметра $2 сместится в параметр $1, например), вытолкнув тем самым обработанные параметры, начинающиеся с дефиса.

Поскольку этот сценарий использует системную утилиту lockfile, он сначала проверяет ее доступность в списке путей пользователя и завершается с сообщением об ошибке, если утилита недоступна. Далее следует простая условная инструкция , выясняющая, какая операция запрошена — блокировка или разблокировка, — и производится соответствующий вызов утилиты lockfile.

Запуск сценария

Сценарий filelock относится к категории сценариев, которые редко используются сами по себе, и для его проверки потребуется открыть два окна терминала. Чтобы установить блокировку, просто укажите имя файла, который будет играть роль блокировки, в аргументе сценария filelock. Чтобы снять блокировку, запустите сценарий еще раз с флагом −u.

Результаты

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

Листинг 1.23. Создание файла-блокировки командой filelock

$ filelock /tmp/exclusive.lck

$ ls −l /tmp/exclusive.lck

-r-r-r-··1 taylor··wheel··1 Mar 21 15:35 /tmp/exclusive.lck

Когда в следующий раз вы попытаетесь установить ту же блокировку, filelock выполнит указанное количество попыток (10 по умолчанию) и завершится с ошибкой (как показано в листинге 1.24):

вернуться

2

Символы «EOF» должны находиться в начале строки, т. е. перед ними не должно быть пробелов. Это требование синтаксиса встроенных документов. В оригинале это правило нарушено. В данном листинге перед всеми строками добавлены 2 пробела, чтобы не нарушить отступы. Они к делу не относятся, и в данном случае считается, что метка EOF находится в начале строки, без отступа. — Примеч. пер.