Никакая сложная операционная система, будь то Windows, OS X или Unix, не может функционировать бесконечно долго без вмешательства человека. Если вы работаете в многопользовательской системе Linux, значит, кто-то выполняет задачи системного администрирования. Вы можете игнорировать пресловутого «человека за ширмой», управляющего всем и вся, или сами быть великим и могучим волшебником из страны Оз — тем, кто двигает рычаги и нажимает кнопки, чтобы обеспечить нормальную работу системы. Если вы единственный пользователь системы, вам придется регулярно решать задачи системного администрирования самостоятельно.
К счастью, сценарии командной оболочки не в последнюю очередь существуют для того, чтобы упростить жизнь администраторам систем Linux (о чем и пойдет речь в этой главе). Довольно многие команды Linux в действительности являются сценариями, и многие из самых основных задач, такие как добавление пользователей, анализ использования дискового пространства и управление файлами гостевой учетной записи, можно достаточно эффективно решать с помощью коротких сценариев.
Что интересно, многие сценарии, предназначенные для системного администрирования, включают не более 20–30 строк. С помощью команд Linux можно выявить, какие команды являются сценариями, а добавив конвейер — узнать, сколько строк содержит каждый из них. Ниже перечисляется 15 самых коротких сценариев в /usr/bin/:
$ file /usr/bin/* | grep "shell script" | cut -d: -f1 | xargs wc -l \
| sort -n | head -15
3 zcmp
3 zegrep
3 zfgrep
4 mkfontdir
5 pydoc
7 sgmlwhich
8 batch
8 ps2pdf12
8 ps2pdf13
8 ps2pdf14
8 timed-read
9 timed-run
10 c89
10 c99
10 neqn
Ни один из 15 самых коротких сценариев в каталоге /usr/bin/ не содержит больше 10 строк. И десятистрочный сценарий форматирования формул neqn наглядно демонстрирует, как короткий сценарий командной оболочки может упрощать жизнь пользователям:
#!/bin/bash
# Присутствие этого сценария не должно расцениваться как наличие поддержки
# GNU eqn и groff -Tascii|-Tlatin1|-Tutf8|-Tcp1047.
: ${GROFF_BIN_PATH=/usr/bin}
PATH=$GROFF_BIN_PATH:$PATH
export PATH
exec eqn -Tascii ${1+"$@"}
# eof
Сценарии, которые будут представлены в этой главе, такие же короткие и полезные, как neqn, и помогают решить множество административных задач, включая резервное копирование системы, добавление и удаление учетных записей и пользовательских данных, управление учетными записями. Также вы получите простой и удобный интерфейс к команде date, изменяющий текущие дату и время, и инструмент для проверки файлов crontab.
Даже с появлением очень емких жестких дисков и постоянным уменьшением цен на них системным администраторам постоянно приходится следить за использованием дискового пространства, чтобы общедоступные диски не переполнились.
Наиболее типичным приемом мониторинга является исследование каталога /usr или /home с использованием команды du, чтобы определить объем всех подкаталогов, с последующим выводом списка 5 или 10 пользователей, занявших больше всего дискового пространства. Однако этот подход не позволяет контролировать потребление дискового пространства в других местах на жестких дисках. Если у отдельных пользователей есть дополнительное архивное пространство на втором диске или у вас завелись хитрецы, которые хранят огромные видеофайлы в каталоге с именем, начинающимся с точки и находящемся в каталоге /tmp или в неиспользуемом каталоге в области ftp, такие факты расходования дискового пространства не будут обнаружены. Кроме того, если домашние каталоги пользователей разбросаны по нескольким дискам, поиск каждого каталога /home может оказаться неоптимальным.
Лучшее решение — получить имена всех учетных записей непосредственно из файла /etc/passwd и затем отыскать в файловой системе все файлы, принадлежащие каждой учетной записи, как показано в листинге 5.1.
Листинг 5.1. Сценарий fquota
#!/bin/bash
# fquota -- инструмент анализа расходования дискового пространства для Unix;
# предполагается, что все учетные записи рядовых пользователей
# имеют числовые идентификаторы UID >= 100
MAXDISKUSAGE=20000 # В мегабайтах
for name in $(cut -d: -f1,3 /etc/passwd | awk -F: '$2 > 99 {print $1}')
do
/bin/echo -n "User $name exceeds disk quota. Disk usage is: "
# Вам может потребоваться изменить следующий список каталогов, чтобы
# он лучше соответствовал структуре каталогов на вашем диске.
# Наиболее вероятно, что вам придется заменить имя /Users на /home.
find / /usr /var /Users -xdev -user $name -type f -ls | \
awk '{ sum += $7 } END { print sum / (1024*1024) " Mbytes" }'
done | awk "\$9 > $MAXDISKUSAGE { print \$0 }"
exit 0
В соответствии с соглашениями, идентификаторы пользователей (User ID, UID) от 1 до 99 отводятся для системных демонов и административных задач, а идентификаторы со значениями 100 и выше можно выбирать для учетных записей обычных пользователей. Поскольку администраторы Linux обычно весьма организованные люди, этот сценарий пропускает все учетные записи со значениями UID меньше 100.
Аргумент -xdev в вызове команды find гарантирует, что find не будет выполнять поиск во всех файловых системах. Иными словами, этот аргумент предотвращает обход командой системных областей, каталогов, доступных только для чтения, извлекаемых устройств, каталога /proc действующих процессов (в Linux) и других подобных областей. Вот почему в список явно включены такие каталоги, как /usr, /var и /home. Эти каталоги часто размещаются в отдельных файловых системах для упрощения их резервного копирования и организации. Добавление их в список, когда они действительно находятся в корневой файловой системе, не означает, что они будут просмотрены дважды.
На первый взгляд кажется, что сценарий выведет сообщение exceeds disk quota (превысил дисковую квоту) для любой учетной записи, но это не так: команда awk, следующая за концом цикла , позволит вывести такое сообщение только для учетных записей, файлы которых занимают больше чем MAXDISKUSAGE.
Сценарий не имеет аргументов и должен запускаться с привилегиями root, чтобы гарантировать доступность всех каталогов и файловых систем. Запускать сценарии с такими привилегиями предпочтительнее с помощью команды sudo (выполните команду man sudo в окне терминала, чтобы получить дополнительную информацию). Почему именно с помощью sudo? Потому что такой прием позволяет выполнить с привилегиями root только одну команду, после чего привилегии командной оболочки будут вновь понижены до уровня обычного пользователя. Каждый раз, когда вам потребуется выполнить административную команду, используйте для этого sudo. Использование команды su - root, напротив, позволит выполнить все последующие команды с привилегиями root, пока подоболочка не будет закрыта явно, а отвлекшись на что-то срочное, легко забыть, что вы получили привилегии root, и есть риск по ошибке сделать что-то, что приведет к разрушительным последствиям.
ПРИМЕЧАНИЕ
Измените список каталогов в команде find , чтобы он точно соответствовал структуре каталогов на вашем диске.
Сценарий выполняет поиск по целым файловым системам, поэтому не надо удивляться, что ему для работы требуется немало времени. В больших файловых системах процесс легко может занять промежуток между утренней чашкой чая и обедом. В листинге 5.2 приводится пример результатов работы сценария.
Листинг 5.2. Тестирование сценария fquota
$ sudo fquota
User taylor exceeds disk quota. Disk usage is: 21799.4 Mbytes
Как видите, пользователь taylor вышел из-под контроля! Объем его файлов составил 21 Гбайт, что намного больше квоты в 20 Гбайт, выделяемой каждому пользователю.
Полноценный сценарий такого рода должен иметь возможность автоматически по электронной почте извещать нарушителей о том, что они заняли слишком много дискового пространства. Это усовершенствование демонстрируется в следующем сценарии.
Большинство системных администраторов стремятся найти самый простой способ решения проблемы, а самый простой способ организовать управление дисковыми квотами — добавить в сценарий fquota (сценарий № 35) рассылку предупреждений по электронной почте пользователям, занявшим слишком большой объем дискового пространства, как показано в листинге 5.3.
Листинг 5.3. Сценарий diskhogs
#!/bin/bash
# diskhogs -- инструмент анализа расходования дискового пространства для Unix;
# предполагается, что все учетные записи рядовых пользователей
# имеют числовые идентификаторы UID >= 100.
# Рассылает электронные письма с предупреждением всем нарушителям
# и выводит на экран общий отчет.
MAXDISKUSAGE=500
violators="/tmp/diskhogs0.$$"
trap "$(which rm) -f $violators" 0
for name in $(cut -d: -f1,3 /etc/passwd | awk -F: '$2 > 99 { print $1 }')
do
/bin/echo -n "$name "
# Вам может потребоваться изменить следующий список каталогов, чтобы
# он лучше соответствовал структуре каталогов на вашем диске.
# Наиболее вероятно, что вам придется заменить имя /Users на /home.
find / /usr /var /Users -xdev -user $name -type f -ls | \
awk '{ sum += $7 } END { print sum / (1024*1024) }'
done | awk "\$2 > $MAXDISKUSAGE { print \$0 }" > $violators
if [ ! -s $violators ] ; then
echo "No users exceed the disk quota of ${MAXDISKUSAGE}MB"
cat $violators
exit 0
fi
while read account usage ; do
cat << EOF | fmt | mail -s "Warning: $account Exceeds Quota" $account
Your disk usage is ${usage}MB, but you have been allocated only
${MAXDISKUSAGE}MB. This means that you need to delete some of your
files, compress your files (see 'gzip' or 'bzip2' for powerful and
easy-to-use compression programs), or talk with us about increasing
your disk allocation.
Thanks for your cooperation in this matter.
Your friendly neighborhood sysadmin
EOF
echo "Account $account has $usage MB of disk space. User notified."
done < $violators
exit 0
При создании этого сценария за основу был взят сценарий № 35. Изменения отмечены номерами , , , и . Обратите внимание на дополнительную команду fmt в конвейере, передающем текст программе отправки электронной почты .
Этот трюк помогает улучшить вид автоматически сгенерированного электронного письма, когда в тексте имеются поля неизвестной длины, такие как $account. Логика работы цикла for несколько отличается от логики работы цикла for в сценарии № 35: так как вывод этого цикла предназначен исключительно для использования во второй части сценария, в каждой итерации он просто выводит имя учетной записи и объем занятого дискового пространства, а не сообщение об ошибке exceeds disk quota (превысил дисковую квоту).
Сценарий не имеет аргументов и должен запускаться с привилегиями root, чтобы гарантировать точность результатов. Для большей безопасности желательно запускать сценарий командой sudo, как показано в листинге 5.4.
Листинг 5.4. Тестирование сценария diskhogs
$ sudo diskhogs
Account ashley has 539.7MB of disk space. User notified.
Account taylor has 91799.4MB of disk space. User notified.
Если теперь заглянуть в почтовый ящик пользователя ashley, мы увидим сообщение, отправленное сценарием (листинг 5.5).
Листинг 5.5. Электронное письмо, отправленное пользователю ashley после превышения дисковой квоты
Subject: Warning: ashley Exceeds Quota
Your disk usage is 539.7MB, but you have been allocated only 500MB. This means
that you need to delete some of your files, compress your files (see 'gzip' or
'bzip2' for powerful and easy-to-use compression programs), or talk with us
about increasing your disk allocation.
Thanks for your cooperation in this matter.
Your friendly neighborhood sysadmin
Удобным усовершенствованием этого сценария могла бы стать поддержка разных квот для разных пользователей. Ее легко реализовать, создав отдельный файл, определяющий дисковые квоты для всех пользователей, и настроив в сценарии квоту по умолчанию для тех, кто отсутствует в файле. Файл с именами пользователей и квотами можно было бы анализировать командой grep, извлекать из найденной записи второе поле командой cut -f2.
Вывод утилиты df порой выглядит очень непонятным, но мы можем увеличить его удобочитаемость. Сценарий в листинге 5.6 преобразует счетчики байтов в выводе df в более понятные единицы измерения.
Листинг 5.6. Сценарий newdf, обертка для df, помогающая получить более удобочитаемый вывод
#!/bin/bash
# newdf -- более дружественная версия df
awkscript="/tmp/newdf.$$"
trap "rm -f $awkscript" EXIT
cat << 'EOF' > $awkscript
function showunit(size)
{ mb = size / 1024; prettymb=(int(mb * 100)) / 100;
gb = mb / 1024; prettygb=(int(gb * 100)) / 100;
if ( substr(size,1,1) !~ "[0-9]" ||
substr(size,2,1) !~ "[0-9]" ) { return size }
else if ( mb < 1) { return size "K" }
else if ( gb < 1) { return prettymb "M" }
else { return prettygb "G" }
}
BEGIN {
printf "%-37s %10s %7s %7s %8s %-s\n",
"Filesystem", "Size", "Used", "Avail", "Capacity", "Mounted"
}
!/Filesystem/ {
size=showunit($2);
used=showunit($3);
avail=showunit($4);
printf "%-37s %10s %7s %7s %8s %-s\n",
$1, size, used, avail, $5, $6
}
EOF
df -k | awk -f $awkscript
exit 0
Основная работа выполняется awk-сценарием, и не составило бы большого труда написать весь сценарий на awk, а не на языке командной оболочки, применив в нем функцию system() для вызова команды df. (Вообще, этот пример — идеальный кандидат, чтобы переписать его на языке Perl, но наша книга совсем не о том.)
В этом сценарии используется старый трюк, в строках и , пришедший из языка BASIC.
Быстро ограничить количество знаков после десятичной точки при работе с числами произвольной точности можно, умножив число на степень 10, преобразовав произведение в целое число (отбросив дробную часть) и разделив результат на ту же степень 10: prettymb=(int(mb * 100)) / 100;. Этот код, например, превратит значение 7,085344324 в более привлекательное 7,08.
ПРИМЕЧАНИЕ
Некоторые версии df поддерживают флаг -h, позволяющий получить похожий вывод. Однако этот сценарий, как и многие другие в данной книге, обеспечивает более дружественный и понятный вывод в любой системе, Unix или Linux, независимо от используемой версии df.
Сценарий не имеет аргументов и может запускаться с любыми привилегиями, в том числе с привилегиями root. Чтобы исключить строки с информацией об устройствах, которые вам не интересны, используйте команду grep -v после вызова df.
Обычная команда df выводит результаты в виде, трудном для понимания, как показано в листинге 5.7.
Листинг 5.7. В выводе по умолчанию команды df сложно разобраться
$ df
Filesystem 512-blocks Used Available Capacity Mounted on
/dev/disk0s2 935761728 628835600 306414128 68% /
devfs 375 375 0 100% /dev
map -hosts 0 0 0 100% /net
map auto_home 0 0 0 100% /home
localhost:/mNhtYYw9t5GR1SlUmkgN1E 935761728 935761728 0 100% /Volumes/ Mobile- Backups
Новый сценарий использует awk для увеличения удобочитаемости и преобразует 512-байтные блоки в более понятный формат, как можно видеть в листинге 5.8.
Листинг 5.8. Простой и понятный вывод сценария newdf
$ newdf
Filesystem Size Used Avail Capacity Mounted
/dev/disk0s2 446.2G 299.86G 146.09G 68% /
devfs 187K 187K 0 100% /dev
map -hosts 0 0 0 100%
map auto_home 0 0 0 100%
localhost:/mNhtYYw9t5GR1SlUmkgN1E 446.2G 446.2G 0 100% /Volumes/ Mobile- Backups
В этом сценарии много недостатков, и один из самых значительных — наличие версий df, включающих информацию об использовании индексных узлов (inode) и даже внутреннюю информацию о процессоре, хотя она не представляет никакого интереса (как две записи map в примере выше). Сценарий был бы намного полезнее, если бы мы удалили вывод подобной ненужной информации, поэтому в первую очередь стоить применить флаг -P в вызове df, ближе к концу сценария , чтобы удалить из вывода информацию об использовании индексных узлов. (Ее можно было бы вывести в отдельном столбце, но тогда вывод станет еще шире и форматировать его станет труднее.) Чтобы удалить записи map, достаточно воспользоваться командой grep. Просто добавьте в конец команды |grep -v "^map" , и вы навсегда избавитесь от них.
Коль скоро сценарий № 37 способен упростить вывод команды df, чтобы его было легче читать и понимать, тогда на более простой вопрос об объеме доступного дискового пространства в системе тем более можно ответить с помощью сценария командной оболочки. Команда df действительно сообщает информацию для каждого диска, но для ее осмысления требуется приложить некоторые усилия:
$ df
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/hdb2 25695892 1871048 22519564 8% /
/dev/hdb1 101089 6218 89652 7% /boot
none 127744 0 127744 0% /dev/shm
Более полезная версия df могла бы суммировать числа в колонке «Available» (Доступно) и выводить ее в удобочитаемом виде. Эта задача легко решается с помощью команды awk, как показано в листинге 5.9.
Листинг 5.9. Сценарий diskspace, удобная обертка для df, сообщающая информацию в дружественном формате
#!/bin/bash
# diskspace -- суммирует доступное дисковое пространство и выводит сумму
# в логичном и удобочитаемом виде
tempfile="/tmp/available.$$"
trap "rm -f $tempfile" EXIT
cat << 'EOF' > $tempfile
{ sum += $4 }
END { mb = sum / 1024
gb = mb / 1024
printf "%.0f MB (%.2fGB) of available disk space\n", mb, gb
}
EOF
df -k | awk -f $tempfile
exit 0
Сценарий diskspace опирается на временный awk-сценарий, который сохраняется в каталоге /tmp. Этот awk-сценарий вычисляет общий объем доступного дискового пространства на основе переданных ему данных и затем выводит результат в удобочитаемом формате. Результаты вызова команды df по конвейеру передаются команде awk , которая в свою очередь выполняет операции, определяемые awk-сценарием. Когда работа сценария завершается, временный awk-сценарий удаляется из каталога /tmp благодаря обработчику сигнала выхода, установленному командой trap в начале сценария.
Этот сценарий, который может запустить любой пользователь, выводит короткую строку с информацией о суммарном объеме доступного дискового пространства.
В той же системе, где был получен вывод команды df, показанный выше, этот сценарий выведет строку, представленную в листинге 5.10.
Листинг 5.10. Тестирование сценария diskspace
$ diskspace
96199 MB (93.94GB) of available disk space
Если в вашей системе несколько многотерабайтных дисков, вы могли научить сценарий автоматически выводить значение в терабайтах. В случае исчерпания дискового пространства будет особенно неприятно увидеть, что доступно всего 0,03 Гб — но это отличный повод запустить сценарий № 36, чтобы подтолкнуть пользователей удалить ненужные файлы, разве не так?
Обратите внимание еще на одну проблему: имеет ли смысл учитывать доступное дисковое пространство на всех устройствах, включая разделы, которые точно не будут заполняться, такие как /boot, или достаточно сообщать информацию только о пользовательских разделах? В последнем случае этот сценарий можно было бы усовершенствовать, добавив вызов grep сразу после вызова df . Используйте grep с именами нужных устройств, чтобы включить в расчеты только определенные устройства, или grep -v с именами ненужных устройств, чтобы исключить из расчетов информацию о них.
Сценарий locate, представленный в сценарии № 19 (глава 2), очень полезен, но создает угрозу безопасности: если процесс сбора данных запустить с привилегиями root, он составит полный список файлов и каталогов во всей системе, независимо от их владельца, что даст возможность обычным пользователям увидеть имена файлов каталогов, к которым у них нет доступа. Процесс сбора информации можно запустить с привилегиями обобщенного пользователя (как это делается в OS X, где mklocatedb запускается с привилегиями пользователя nobody), но и это не самое правильное решение, потому что вам может понадобиться найти файл где-нибудь в дереве вашего домашнего каталога, независимо от наличия прав доступа к этим файлам и каталогам у пользователя nobody.
Одно из решений этой дилеммы состоит в том, чтобы расширить записи, хранящиеся в базе данных locate, дополнив их сведениями о владельце, группе и привилегиях доступа. Но сама база данных mklocatedb все равно останется незащищенной, если только не запускать сценарий locate с привилегией setuid или setgid, чего желательно всячески избегать в интересах безопасности всей системы.
Компромиссное решение — создавать файл .locatedb отдельно для каждого пользователя. Это не самый худший вариант, потому что личные базы данных нужны только пользователям, которые действительно пользуются командой locate. После вызова система создаст файл .locatedb в домашнем каталоге пользователя, а его своевременное обновление можно переложить на задание cron, выполняющееся по ночам. Когда пользователь запустит защищенный сценарий slocate в самый первый раз, он увидит сообщение, предупреждающее о том, что он может выполнять поиск только среди общедоступных файлов. Запустив сценарий на следующий день (в зависимости от того, на какое время запланирован запуск задания cron), пользователи будут получать свои, персонализированные результаты.
Защищенная версия locate состоит из двух сценариев: конструктора базы данных mkslocatedb (представленного в листинге 5.11), и утилиты поиска slocate (представленной в листинге 5.12).
Листинг 5.11. Сценарий mkslocatedb
#!/bin/bash
# mkslocatedb -- создает центральную базу данных общедоступных файлов,
# выполняясь с привилегиями пользователя nobody, и одновременно обходит
# домашние каталоги всех пользователей в поисках файла .slocatedb.
# Если файл найден, для пользователя создается дополнительная, личная
# версия базы данных поиска файлов.
locatedb="/var/locate.db"
slocatedb=".slocatedb"
if [ "$(id -nu)" != "root" ] ; then
echo "$0: Error: You must be root to run this command." >&2
exit 1
fi
if [ "$(grep '^nobody:' /etc/passwd)" = "" ] ; then
echo "$0: Error: you must have an account for user 'nobody'" >&2
echo "to create the default slocate database." >&2
exit 1
fi
cd / # Предотвратить проблемы нехватки прав доступа после команды su
# Сначала создать или обновить общедоступную базу данных.
su -fm nobody -c "find / -print" > $locatedb 2>/dev/null
echo "building default slocate database (user = nobody)"
echo ... result is $(wc -l < $locatedb) lines long.
# Теперь обойти учетные записи пользователей и посмотреть,
# у кого в домашнем каталоге имеется файл .slocatedb.
for account in $(cut -d: -f1 /etc/passwd)
do
homedir="$(grep "^${account}:" /etc/passwd | cut -d: -f6)"
if [ "$homedir" = "/" ] ; then
continue # Не создавать в корневом каталоге.
elif [ -e $homedir/$slocatedb ] ; then
echo "building slocate database for user $account"
su -m $account -c "find / -print" > $homedir/$slocatedb \
2>/dev/null
chmod 600 $homedir/$slocatedb
chown $account $homedir/$slocatedb
echo ... result is $(wc -l < $homedir/$slocatedb) lines long.
fi
done
exit 0
Сам сценарий slocate (в листинге 5.12) — это пользовательский интерфейс к базе данных slocate.
Листинг 5.12. Сценарий slocate, сопутствующий сценарий для mkslocatedb
#!/bin/bash
# slocate -- выполняет поиск собственной, защищенной базы данных locatedb
# пользователя по указанному шаблону. Если база данных не найдена, это
# означает, что она отсутствует, тогда выводится предупреждающее сообщение
# и создается новая база данных. Если личная база данных .slocatedbis пустая,
# вместо нее используется системная.
locatedb="/var/locate.db"
slocatedb="$HOME/.slocatedb"
if [ ! -e $slocatedb -o "$1" = "--explain" ] ; then
cat << "EOF" >&2
Warning: Secure locate keeps a private database for each user, and your
database hasn't yet been created. Until it is (probably late tonight),
I'll just use the public locate database, which will show you all
publicly accessible matches rather than those explicitly available to
account ${USER:-$LOGNAME}.
EOF
if [ "$1" = "--explain" ] ; then
exit 0
fi
# Перед продолжением создать файл .slocatedb, чтобы задание cron заполнило
# его, когда в следующий раз сценарий mkslocatedb будет запущен.
touch $slocatedb # mkslocatedb заполнит этот файл при следующем запуске
chmod 600 $slocatedb # Установить безопасные привилегии
elif [ -s $slocatedb ] ; then
locatedb=$slocatedb
else
echo "Warning: using public database. Use \"$0 --explain\" for details." >&2
fi
if [ -z "$1" ] ; then
echo "Usage: $0 pattern" >&2
exit 1
fi
exec grep -i "$1" $locatedb
Сценарий mkslocatedb основан на идее, что процесс, запущенный с привилегиями root, может временно приобретать привилегии разных пользователей, используя команду su -fm user . После этого он может выполнить команду find с привилегиями каждого пользователя для создания персонализированных баз данных с именами файлов. Однако, работая с командой su внутри сценария, необходимо соблюдать некоторые меры предосторожности, потому что по умолчанию su не только изменяет действующий идентификатор пользователя, но также импортирует окружение для выбранной учетной записи. Это может приводить к странным и запутывающим сообщениям об ошибках, если только не использовать в команде флаг -m, запрещающий импорт пользовательского окружения. Флаг -f — это дополнительная мера предосторожности, помогающая предотвратить загрузку файла .cshrc для учетных записей, использующих командную оболочку csh или tcsh.
Еще одна необычная конструкция в строке , 2>/dev/null, которая отправляет все сообщения об ошибках в пресловутый битоприемник: все, что посылается в /dev/null, исчезает без следа. Это самый простой способ избавиться от неизбежных сообщений о недостаточности привилегий, которые выводит команда find в каждом вызове.
mkslocatedb — сценарий, необычный не только тем, что должен запускаться с привилегиями root, но и тем, что использования команды sudo для его запуска будет недостаточно. Вы должны войти в систему как пользователь root или использовать более мощную команду su, чтобы приобрести привилегии root перед запуском сценария. Это объясняется тем, что su фактически превращает вас в суперпользователя root, тогда как sudo просто дает текущему пользователю привилегии root на время. Команда sudo устанавливает другие права доступа к файлам, чем команда su. Сценарий slocate, конечно, не предъявляет таких требований.
В результате попытки создать базы данных для пользователей nobody (общедоступная база данных) и taylor в системе Linux на экран будут выведены строки, как показано в листинге 5.13.
Листинг 5.13. Запуск сценария mkslocatedb с привилегиями root
# mkslocatedb
building default slocate database (user = nobody)
... result is 99809 lines long.
building slocate database for user taylor
... result is 99808 lines long.
Теперь давайте сначала попробуем найти конкретный файл или группу файлов, соответствующих заданному шаблону, зарегистрировавшись в системе как пользователь tintin (в домашнем каталоге которого нет файла .slocatedb):
tintin $ slocate Taylor-Self-Assess.doc
Warning: using public database. Use "slocate --explain" for details.
$
Теперь введем ту же команду от имени пользователя taylor, которому принадлежит разыскиваемый файл:
taylor $ slocate Taylor-Self-Assess.doc
/Users/taylor/Documents/Merrick/Taylor-Self-Assess.doc
Если ваша файловая система имеет огромный объем, такой подход может привести к потреблению значительного пространства на диске. Одно из решений проблемы — не включать в персональные базы данных .slocatedb записи, имеющиеся в центральной базе данных. Это потребует выполнения дополнительных операций (сортировать оба файла командой sort и затем отыскивать различия командой diff или просто пропускать каталоги /usr и /bin, когда выполняется поиск индивидуальных файлов пользователей), но поможет сэкономить место на диске. Другой способ экономии — добавлять в индивидуальные файлы .slocatedb только ссылки на файлы, к которым выполнялось обращение с момента последнего обновления. Этот прием будет работать лучше, если сценарий mkslocatedb запускать не каждый день, а раз в неделю; иначе все пользователи встретят понедельник с пустыми базами данных, потому что едва ли кто-то из них будет запускать команду slocate в выходные.
Наконец, еще один простой способ сэкономить место на диске — хранить файлы .slocatedb в сжатом виде и разжимать их «на лету», во время поиска командой slocate. Идею можно подсмотреть в реализации команды zgrep, в сценарии № 33 (глава 4).
Если вы отвечаете за поддержку сетей в системах Unix или Linux, вас наверняка расстраивают мелкие несовместимости между разными операционными системами, имеющимися в вашем распоряжении. Некоторые самые простые задачи администрирования оказываются несовместимы с разными разновидностями Unix, и главная из них — управление учетными записями пользователей. Вместо одной команды, на 100% совместимой со всеми разновидностями Linux, каждый производитель норовит создать собственную программу с графическим интерфейсом для работы с настройками своей системы.
Казалось бы, простой протокол управления сетью (Simple Network Management Protocol, SNMP) должен помогать в нормализации подобных отклонений, тем не менее управление учетными записями пользователей остается таким же сложным делом, как лет десять тому назад, особенно в гетерогенных окружениях. Как результат, полезные наборы сценариев для системных администраторов включают версии adduser, suspenduser и deleteuser, которые можно настроить под конкретные потребности и затем легко перенести на все системы Unix. Далее мы рассмотрим сценарий adduser, а в следующих двух разделах — сценарии suspenduser и deleteuser.
ПРИМЕЧАНИЕ
Операционная система OS X со своей отдельной базой данных для хранения учетных записей пользователей является исключением из правил. Чтобы сохранить душевное здоровье, просто пользуйтесь версиями приведенных команд для Mac, не стараясь вникнуть в тонкости администрирования этой базы данных из командной строки.
В Linux учетная запись создается добавлением в файл /etc/passwd уникальной записи, включающей имя учетной записи длиной от одного до восьми символов, уникальный числовой идентификатор пользователя, числовой идентификатор группы, путь к домашнему каталогу и командную оболочку входа для этого пользователя. Современные системы хранят шифрованные пароли в /etc/shadow, так что для каждого нового пользователя в этом файле также должна быть создана запись. Наконец, учетная запись должна быть указана в файле /etc/group, в собственной группе (эта стратегия реализована в данном сценарии) или в составе существующей группы. Реализация всех перечисленных шагов приводится в листинге 5.14.
Листинг 5.14. Сценарий adduser
#!/bin/bash
# adduser -- добавляет нового пользователя в систему, включая создание
# домашнего каталога, копирование конфигурационных данных по умолчанию
# и так далее.
# Для стандартных систем Unix/Linux, не для OS X.
pwfile="/etc/passwd"
shadowfile="/etc/shadow"
gfile="/etc/group"
hdir="/home"
if [ "$(id -un)" != "root" ] ; then
echo "Error: You must be root to run this command." >&2
exit 1
fi
echo "Add new user account to $(hostname)"
/bin/echo -n "login: " ; read login
# Следующая строка ограничивает максимальный числовой идентификатор
# пользователя значением 5000, скорректируйте это значение,
# чтобы оно соответствовало верхней границе вашего диапазона
# числовых идентификаторов пользователей.
uid="$(awk -F: '{ if (big < $3 && $3 < 5000) big=$3 } END { print big + 1 }'\
$pwfile)"
homedir=$hdir/$login
# Для каждого пользователя создается собственная группа.
gid=$uid
/bin/echo -n "full name: " ; read fullname
/bin/echo -n "shell: " ; read shell
echo "Setting up account $login for $fullname..."
echo ${login}:x:${uid}:${gid}:${fullname}:${homedir}:$shell >> $pwfile
echo ${login}:*:11647:0:99999:7::: >> $shadowfile
echo "${login}:x:${gid}:$login" >> $gfile
mkdir $homedir
cp -R /etc/skel/.[a-zA-Z]* $homedir
chmod 755 $homedir
chown -R ${login}:${login} $homedir
# Установка начального пароля
exec passwd $login
Самая замысловатая команда в этом сценарии находится в строке . Она перебирает записи в файле /etc/passwd, отыскивает наибольший числовой идентификатор, который меньше наибольшего допустимого значения для учетных записей пользователей (в этом сценарии используется число 5000, но вы должны скорректировать его для своей конфигурации), и затем прибавляет 1, чтобы получить числовой идентификатор для новой учетной записи. Это избавляет администратора от необходимости запоминать следующий доступный числовой идентификатор, а также гарантирует высокую степень согласованности информации об учетных записях в процессе развития и изменения коллектива пользователей.
Сценарий добавляет учетную запись с новым числовым идентификатором. Затем создает домашний каталог для нового пользователя и копирует в него содержимое каталога /etc/skel. В соответствии с соглашениями, каталог /etc/skel должен хранить шаблоны файлов .cshrc, .login, .bashrc и .profile. На сайтах, где имеется веб-сервер, поддерживающий службу ~account, в новый домашний каталог необходимо также скопировать каталог, такой как /etc/skel/public_html. Это особенно удобно, если в вашей организации предусматривается настройка рабочих станций с Linux для инженеров или разработчиков специальными конфигурациями bash.
Этот сценарий не имеет аргументов и должен запускаться с привилегиями root.
В нашей системе уже есть учетная запись для tintin, поэтому мы решили создать отдельную учетную запись для snowy (как показано в листинге 5.15).
Листинг 5.15. Тестирование сценария adduser
$ sudo adduser
Add new user account to aurora
login: snowy
full name: Snowy the Dog
shell: /bin/bash
Setting up account snowy for Snowy the Dog...
Changing password for user snowy.
New password:
Retype new password:
passwd: all authentication tokens updated successfully.
Одним из значительных преимуществ использования собственного сценария adduser является возможность расширять его и изменять логику отдельных операций, не заботясь об обновлении системы под эти изменения. В числе вероятных расширений автоматическая отправка приветственного электронного письма, в общих чертах обрисовывающего порядок работы и способы получения справочной информации, автоматическая печать на бумаге сводной информации об учетной записи для передачи пользователю, добавление псевдонима firstname_lastname или firstname.lastname в файл aliases сервера электронной почты и даже копирование комплекта файлов в домашний каталог учетной записи, чтобы пользователь мог немедленно включиться в коллективную работу над проектом.
Есть много случаев, когда желательно заблокировать учетную запись, не удаляя ее из системы, например, когда пользователь уличен в краже промышленных секретов и идет разбирательство, студент отправился отдыхать на летние каникулы или подрядчик ушел в отпуск.
Можно просто изменить пароль пользователя и не сообщить ему, но, если пользователь в это время находится в системе, также важно было бы принудительно вывести его из системы и закрыть доступ к его домашнему каталогу из других учетных записей в системе. Когда действие учетной записи приостанавливается, почти всегда требуется вывести пользователя из системы немедленно, а не когда он сам пожелает сделать это.
Большая часть сценария в листинге 5.16 связана с определением присутствия пользователя в системе, его уведомлением о завершении сеанса и принудительным выводом из системы.
Листинг 5.16. Сценарий suspenduser
#!/bin/bash
# suspenduser -- приостанавливает действие учетной записи до неопределенного
# момента в будущем
homedir="/home" # Местонахождение домашних каталогов пользователей
secs=10 # Пауза в секундах перед выводом пользователя из системы
if [ -z $1 ] ; then
echo "Usage: $0 account" >&2
exit 1
elif [ "$(id -un)" != "root" ] ; then
echo "Error. You must be 'root' to run this command." >&2
exit 1
fi
echo "Please change the password for account $1 to something new."
passwd $1
# Теперь посмотрим, если пользователь зарегистрирован в системе.
# выведем его принудительно.
if who|grep "$1" > /dev/null ; then
for tty in $(who | grep $1 | awk '{print $2}'); do
cat << "EOF" > /dev/$tty
******************************************************************************
URGENT NOTICE FROM THE ADMINISTRATOR:
This account is being suspended, and you are going to be logged out
in $secs seconds. Please immediately shut down any processes you
have running and log out.
If you have any questions, please contact your supervisor or
John Doe, Director of Information Technology.
******************************************************************************
EOF
done
echo "(Warned $1, now sleeping $secs seconds)"
sleep $secs
jobs=$(ps -u $1 | cut -d\ -f1)
kill -s HUP $jobs # Послать сигнал остановки процессам пользователя.
sleep 1 # Дать одну секунду...
kill -s KILL $jobs > /dev/null 2>1 # и остановить те, что еще остались.
echo "$1 was logged in. Just logged them out."
fi
# В заключение закрыть домашний каталог от любопытных глаз.
chmod 000 $homedir/$1
echo "Account $1 has been suspended."
exit 0
Сценарий меняет пароль пользователя на неизвестную ему комбинацию символов и затем закрывает его домашний каталог. Если в это время пользователь находится в системе, сценарий посылает ему текст предупреждения, ждет несколько секунд и останавливает все запущенные им процессы.
Обратите внимание, что сценарий посылает сигнал остановки SIGHUP (HUP) всем процессам, запущенным пользователем , ждет одну секунду и затем посылает более жесткий сигнал SIGKILL (KILL) . Сигнал SIGHUP завершает работу запущенного приложения, но не всегда, и оболочка входа не реагирует на него. Однако сигнал SIGKILL не может быть проигнорирован или заблокирован, поэтому он действует со стопроцентной гарантией. Однако такой способ остановки приложений нельзя назвать предпочтительным, потому что этот сигнал не дает приложению возможности удалить временные файлы, вытолкнуть буферы, чтобы гарантировать запись изменений на диск, и выполнить другие заключительные операции.
Разблокирование пользователя выполняется в два шага: открыть его домашний каталог (командой chmod 700) и установить известный пользователю пароль (командой passwd).
Этот сценарий должен запускаться с привилегиями root и принимает один аргумент: имя учетной записи, действие которой требуется приостановить.
Выяснилось, что пользователь snowy нарушил правила пользования учетной записи. Давайте приостановим ее действие, как показано в листинге 5.17.
Листинг 5.17. Тестирование сценария suspenduser на пользователе snowy
$ sudo suspenduser snowy
Please change the password for account snowy to something new.
Changing password for user snowy.
New password:
Retype new password:
passwd: all authentication tokens updated successfully.
(Warned snowy, now sleeping 10 seconds)
snowy was logged in. Just logged them out.
Account snowy has been suspended.
Так как snowy в этот момент был зарегистрирован в системе, он получил сообщение, показанное в листинге 5.18, за несколько секунд до того, как его принудительно вывели из системы.
Листинг 5.18. Текст предупреждения, появившийся на терминале пользователя перед его отключением
******************************************************************************
URGENT NOTICE FROM THE ADMINISTRATOR:
This account is being suspended, and you are going to be logged out
in 10 seconds. Please immediately shut down any processes you
have running and log out.
If you have any questions, please contact your supervisor or
John Doe, Director of Information Technology.
******************************************************************************
Удаление учетной записи немного сложнее в реализации, чем приостановка ее действия, потому что сценарий должен прочесать всю файловую систему в поисках файлов, принадлежащих удаляемой учетной записи, прежде чем информация о ней будет стерта из файлов /etc/passwd и /etc/shadow. Сценарий в листинге 5.19 гарантирует полное удаление из системы учетной записи и всех ее данных. Предполагается, что предыдущий сценарий suspenduser находится в одном из каталогов, перечисленных в текущем значении переменной PATH.
Листинг 5.19. Сценарий deleteuser
#!/bin/bash
# deleteuser -- удаляет учетную запись без следа.
# Не предназначен для использования в OS X.
homedir="/home"
pwfile="/etc/passwd"
shadow="/etc/shadow"
newpwfile="/etc/passwd.new"
newshadow="/etc/shadow.new"
suspend="$(which suspenduser)"
locker="/etc/passwd.lock"
if [ -z $1 ] ; then
echo "Usage: $0 account" >&2
exit 1
elif [ "$(whoami)" != "root" ] ; then
echo "Error: you must be 'root' to run this command.">&2
exit 1
fi
$suspend $1 # Заблокировать учетную запись на время выполнения работы.
uid="$(grep -E "^${1}:" $pwfile | cut -d: -f3)"
if [ -z $uid ] ; then
echo "Error: no account $1 found in $pwfile" >&2
exit 1
fi
# Удалить пользователя из файлов password и shadow.
grep -vE "^${1}:" $pwfile > $newpwfile
grep -vE "^${1}:" $shadow > $newshadow
lockcmd="$(which lockfile)" # Найти приложение lockfile.
if [ ! -z $lockcmd ] ; then # Использовать системную команду lockfile.
eval $lockcmd -r 15 $locker
else # Не вышло, используем свой механизм.
while [ -e $locker ] ; do
echo "waiting for the password file" ; sleep 1
done
touch $locker # Создать блокировку на основе файла.
fi
mv $newpwfile $pwfile
mv $newshadow $shadow
rm -f $locker # Щелк! Снять блокировку.
chmod 644 $pwfile
chmod 400 $shadow
# Теперь удалить домашний каталог и перечислить все, что осталось.
rm -rf $homedir/$1
echo "Files still left to remove (if any):"
find / -uid $uid -print 2>/dev/null | sed 's/^/ /'
echo ""
echo "Account $1 (uid $uid) has been deleted, and their home directory "
echo "($homedir/$1) has been removed."
exit 0
Чтобы избежать любых изменений в учетной записи в то время, пока работает сценарий deleteuser, сразу после запуска он приостанавливает ее действие, вызывая suspenduser.
Перед изменением файла с паролями этот сценарий блокирует доступ к нему с помощью программы lockfile, если она доступна . Как вариант, для создания файла-блокировки в Linux можно также использовать утилиту flock. Если этой программы нет, сценарий использует относительно примитивный механизм блокировки, основанный на создании файла /etc/passwd.lock. Если файл-блокировка уже существует , сценарий ждет его удаления другой программой, после чего создает свой файл, выполняет необходимые операции и удаляет его по завершении .
Этот сценарий должен запускаться с привилегиями root (с помощью sudo) и в качестве аргумента ожидает получить имя учетной записи для удаления. В листинге 5.20 показан запуск сценария для удаления учетной записи пользователя snowy.
ВНИМАНИЕ
Действия, выполняемые сценарием, необратимы, и в ходе своей работы он удаляет много файлов, поэтому будьте осторожны во время экспериментов с ним!
Листинг 5.20. Тестирование сценария deleteuser на учетной записи пользователя snowy
$ sudo deleteuser snowy
Please change the password for account snowy to something new.
Changing password for user snowy.
New password:
Retype new password:
passwd: all authentication tokens updated successfully.
Account snowy has been suspended.
Files still left to remove (if any):
/var/log/dogbone.avi
Account snowy (uid 502) has been deleted, and their home directory
(/home/snowy) has been removed.
Пользователь snowy попытался спрятать AVI-файл (dogbone.avi) в каталоге /var/log. Но мы благополучно нашли его — кто знает, что там может быть?
Сценарий deleteuser преднамеренно был создан неполным. Вы должны решить, что делать с файлами, принадлежащими удаляемой учетной записи: сжать их и поместить в архив, записать на ленту, скопировать в облачное хранилище, сохранить на DVD или даже послать их по почте прямо в ФБР (в последнем случае мы просто пошутили). Кроме всего прочего упоминание об учетной записи необходимо удалить из файла /etc/group. Если за пределами домашнего каталога имеются файлы, принадлежащие учетной записи, команда find найдет их, но администратор должен сам просмотреть их и решить, что с ними делать, удалить или оставить.
Другим полезным усовершенствованием стала бы реализация пробного режима, чтобы иметь возможность посмотреть, что будет удалено из системы перед тем, как действительно удалить учетную запись.
Переходя из системы в систему, люди обычно переносят свои файлы с настройками окружения, из-за чего эти настройки нередко оказываются недействительными; в конечном итоге в переменной PATH могут оказаться каталоги, фактически отсутствующие в системе, переменная PAGER может ссылаться на несуществующую программу, и так далее.
Сложное решение — сначала проверить переменную PATH, чтобы гарантировать присутствие в ней только допустимых каталогов, а затем проверить все настройки важнейших вспомогательных программ и убедиться, что полные пути указывают на существующие файлы или что эти файлы находятся в каталогах, перечисленных в PATH. Задачу решает сценарий в листинге 5.21.
Листинг 5.21. Сценарий validator
#!/bin/bash
# validator -- проверяет допустимость каталогов в переменной PATH
# и затем проверяет допустимость всех остальных переменных окружения.
# Проверяются переменные SHELL, HOME, PATH, EDITOR, MAIL и PAGER.
errors=0
source library.sh # Содержит сценарий #1 с функцией in_path().
validate()
{
varname=$1
varvalue=$2
if [ ! -z $varvalue ] ; then
if [ "${varvalue%${varvalue#?}}" = "/" ] ; then
if [ ! -x $varvalue ] ; then
echo "** $varname set to $varvalue, but I cannot find executable."
(( errors++ ))
fi
else
if in_path $varvalue $PATH ; then
echo "** $varname set to $varvalue, but I cannot find it in PATH."
errors=$(( $errors + 1 ))
fi
fi
fi
}
# НАЧАЛО ОСНОВНОГО СЦЕНАРИЯ
# =================
if [ ! -x ${SHELL:?"Cannot proceed without SHELL being defined."} ] ; then
echo "** SHELL set to $SHELL, but I cannot find that executable."
errors=$(( $errors + 1 ))
fi
if [ ! -d ${HOME:?"You need to have your HOME set to your home directory"} ]
then
echo "** HOME set to $HOME, but it's not a directory."
errors=$(( $errors + 1 ))
fi
# Первая интересная проверка: все каталоги в PATH допустимы?
oldIFS=$IFS; IFS=":" # IFS -- разделитель полей. Записать в него ':'.
for directory in $PATH
do
if [ ! -d $directory ] ; then
echo "** PATH contains invalid directory $directory."
errors=$(( $errors + 1 ))
fi
done
IFS=$oldIFS # Восстановить прежнее значение разделителя полей.
# Следующие переменные должны содержать полные пути к файлам программ,
# но могут быть не определены или содержать только имена программ.
# Добавьте дополнительные переменные в комплект, если это
# необходимо для вашего сайта и ваших пользователей.
validate "EDITOR" $EDITOR
validate "MAILER" $MAILER
validate "PAGER" $PAGER
# И в заключение вывод разных сообщений, в зависимости от значения errors
if [ $errors -gt 0 ] ; then
echo "Errors encountered. Please notify sysadmin for help."
else
echo "Your environment checks out fine."
fi
exit 0
Проверки, выполняемые сценарием, не отличаются большой сложностью. Чтобы проверить допустимость всех каталогов, перечисленных в переменной PATH, сценарий перебирает их и проверяет, существуют ли они . Обратите внимание, что перед этим изменяется внутренний разделитель полей (IFS): в строке ему присваивается двоеточие, благодаря чему сценарий может благополучно выполнить обход всех каталогов, перечисленных в переменной PATH. В соответствии с соглашениями, каталоги в переменной PATH отделяются друг от друга двоеточием:
$ echo $PATH
/bin/:/sbin:/usr/bin:/sw/bin:/usr/X11R6/bin:/usr/local/mybin
Допустимость переменных окружения оценивает функция validate() , которая прежде всего проверяет, начинается ли значение каждой переменной с символа слеша (/). Если это условие выполняется, функция проверяет наличие указанного выполняемого файла. Если значение переменной не начинается с символа слеша (/), сценарий вызывает функцию in_path(), импортированную из библиотеки, написанную нами в сценарии № 1 (глава 1) , которая проверяет присутствие программы в одном из каталогов, перечисленных в переменной PATH.
Самый необычный аспект сценария — использование значений по умолчанию в некоторых условных выражениях и в операции извлечения подстроки из переменной. Использование значений по умолчанию в условных выражениях вы видите в блоке, начинающемся со строки . Синтаксис ${varname:?"errorMessage"} можно интерпретировать так: «Если переменная varname существует, вернуть ее значение; иначе завершить сценарий и вывести сообщение errorMessage».
Синтаксис извлечения подстроки из переменной ${varvalue%${varvalue#?}}, используемый в строке , — это функция извлечения подстроки, определяемая стандартом POSIX, которая возвращает только первый символ из значения переменной varvalue. Таким образом сценарий определяет, является ли значение переменной полным путем к файлу (начинается с символа слеша / и определяет полный путь к программе).
Если ваша версия Unix/Linux не поддерживает этот синтаксис, его можно заменить более прямолинейными проверками. Например, использовать вместо ${SHELL:?No Shell} следующие строки:
if [ -z "$SHELL" ] ; then
echo "No Shell" >&2; exit 1
fi
А вместо {varvalue%${varvalue#?}} — следующую строку, дающую тот же результат:
$(echo $varvalue | cut -c1)
Этот сценарий пользователи могут запускать для проверки своего окружения. Он не принимает аргументов командной строки и запускается, как показано в листинге 5.22.
Листинг 5.22: Тестирование сценария validator
$ validator
** PATH contains invalid directory /usr/local/mybin.
** MAILER set to /usr/local/bin/elm, but I cannot find executable.
Errors encountered. Please notify sysadmin for help.
Несмотря на то что по соображениям безопасности на многих сайтах запрещен вход с именем пользователя guest, кое-где такая гостевая учетная запись все еще используется (часто с легко угадываемым паролем), чтобы дать клиентам или сотрудникам из других отделов доступ к сети. Это бывает удобно, но есть одна большая проблема: когда одной учетной записью пользуется множество людей, существует опасность, что кто-то из них по неосторожности испортит ее настройки, затруднив работу тех, кто последует за ним. Такое может произойти, например, во время экспериментов с командами, при редактировании файлов .rc или добавлении подкаталогов, и так далее.
Сценарий в листинге 5.23 решает эту проблему, очищая окружение после выхода пользователя из гостевой учетной записи. Он удаляет все новые файлы и подкаталоги, имена которых начинаются с точки и восстанавливает официальные файлы учетной записи, копируя их из архива, доступного только для чтения и спрятанного в каталоге ..template гостевой учетной записи.
Листинг 5.23. Сценарий fixguest
#!/bin/bash
# fixguest -- очищает гостевую учетную запись в процессе выхода.
# Не доверяйте переменным окружения: ссылайтесь на источники,
# доступные только для чтения.
iam=$(id -un)
myhome="$(grep "^${iam}:" /etc/passwd | cut -d: -f6)"
# *** НЕ запускайте этот сценарий в обычной учетной записи!
if [ "$iam" != "guest" ] ; then
echo "Error: you really don't want to run fixguest on this account." >&2
exit 1
fi
if [ ! -d $myhome/..template ] ; then
echo "$0: no template directory found for rebuilding." >&2
exit 1
fi
# Удалить все файлы и каталоги в домашнем каталоге учетной записи.
cd $myhome
rm -rf * $(find . -name ".[a-zA-Z0-9]*" -print)
# Теперь должен остаться только каталог ..template.
cp -Rp ..template/* .
exit 0
Чтобы сценарий работал правильно, создайте комплект шаблонных файлов и каталогов и поместите их в подкаталог ..template, внутри домашнего каталога гостевой учетной записи. Измените права доступа к каталогу ..template, чтобы он был доступен только для чтения, и затем установите права и принадлежность файлов каталогов внутри ..template, чтобы они соответствовали пользователю guest.
Самый подходящий момент для запуска сценария fixguest — выход пользователя из системы. Для этого можно вставить запуск в файл .logout (прием работает почти во всех командных оболочках за редким исключением). Кроме того, вы убережете себя от многих жалоб пользователей, если сценарий login будет выводить, например, такое сообщение:
Внимание: Все файлы будут автоматически удалены из домашнего каталога
гостевой учетной записи сразу после выхода, поэтому, пожалуйста,
не сохраняйте здесь ничего важного. Если вам потребуется что-то сохранить,
отправьте это по электронной почте на свой почтовый ящик.
Вы предупреждены!
Однако отдельные знающие пользователи могут скорректировать содержимое файла .logout, поэтому имеет смысл организовать вызов сценария fixguest также из задания cron. Просто в начале сценария нужно убедиться, что в системе нет ни одного пользователя, зарегистрировавшегося с гостевой учетной записью!
Сценарий ничего не выводит во время работы, он только восстанавливает состояние домашнего каталога в соответствии с содержимым каталога ..template.
Тема: Внимание: ashley превысил квоту
Вы используете 539.7 Мбайт дискового пространства, тогда как вам выделено 500 Мбайт.
Это означает, что вам следует удалить некоторые ваши файлы, сжать файлы (с помощью
простых и мощных программ сжатия ‘gzip’ или ‘bzip2’) или подать заявку на увеличение
дисковой квоты для вас.
Спасибо за сотрудничество в этом вопросе.
Ваш непосредственный системный администратор.
Вам непонятно, о чем это мы? Это персонажи из замечательной серии иллюстрированных комиксов «Adventures of Tintin» (Приключения Тинтина), созданной бельгийским художником Эрже (Hergé) и вышедшей в середине XX века. Подробности смотрите на сайте: http://www.tintin.com/ (https://ru.wikipedia.org/wiki/Приключения_Тинтина – Примеч. пер.).
Перевод:
СРОЧНОЕ СООБЩЕНИЕ ОТ АДМИНИСТРАТОРА:
Эта учетная запись блокируется, и вы будете выведены из системы
через 10 секунд. Пожалуйста, завершите все свои процессы и
выйдите из системы.
По всем вопросам обращайтесь к своему руководителю или
Джону Доу, начальнику отдела информационных технологий.