Как стать автором
Обновить

Общий каталог на Linux-машине, v2

Время на прочтение3 мин
Количество просмотров6K
В ситуации, когда имеется общий каталог на сервере с несколькими пользователями (к примеру на файлопомойке в локальной сети), перед вами может встать проблема, когда необходимо давать права на чтение-запись всем зарегистрированным пользователям. Ситуация уже обсуждалась на Хабре, поэтому позволю себе буквально процитировать статью пользователя karapuz:

Что тут можно сделать? В голову сразу приходят несколько решений:

1. Установить для общего каталога соответствующий umask;
2. Установить соответствующий default acl;
3. Установить бит SGID.

Хорошо, применили одно из решений, или все сразу. Вроде все работает. Оба пользователя имеют полный доступ ко всему содержимому общего каталога, новый файлы в этом каталоге наследуют его права, но вот Вы скинули в этот каталог фотографии с фотоаппарата. В систему под своим пользователем заходит Ваша жена и решает немного изменить эти фотографии, только вот при сохранении появляется сообщение о недостаточных правах. Оказывается скопированные Вами файлы не наследовали права общего каталога. Почему? Да потому, что утилите cp пофигу на Ваши umask'и и acl'ы. Она копирует файлы с сохранением исходных прав, либо права уменьшаются, все зависит от прав на каталог, куда копируем.


В качестве решения проблемы karapuz предложил использовать один из двух имеющихся демонов мониторинга файловой системы fam или gamin и утилиту fileschanged.

Но, как показала практика, оба этих демона значительно нагружают сервер, особенно, когда пользователи активно работают с файлами в контролируемом каталоге. В сети можно найти жалобы пользователей на то, что gamin отъедает до 30% процессорного времени. Могу сказать, что такие же неутешительные результаты получил и я. Чтобы облегчить нагрузку на железку, я решил вместо названных утилит использовать утилиту inotifywait из пакета inotify-tools:

sudo apt-get install inotify-tools

inotifywait ловко отслеживает изменения каталогов и файлов используя интерфейс inotify.

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

Вот примерное решение у меня на сервере. Допустим, нужно следить за правами в каталоге /home/sharez/

Создаем пускалку /usr/local/bin/inotifywait.sh

sudo nano /usr/local/bin/inotifywait.sh

#!/bin/sh
# Передаю директорию в качестве аргумента
inotifywait -mrq -e close_write -e moved_to -e create --format "%w%f" "$1" | while read "FILE"
do
if [ -d "$FILE" ]; then
chown -R nobody:nogroup "$FILE"
chmod -R a+rwX "$FILE"
elif [ -f "$FILE" ]; then
chown nobody:nogroup "$FILE"
chmod a+rw-x "$FILE"
fi
done
:


Внимательный взгляд заметит то, что права и владение директориями устанавливаются рекурсивно. Для чего это сделано, ведь любые рекурсивные действия — это дополнительные значительные накладные расходы? Дело в том, что inotifywait следит лишь за инодой файла или директории. И если при копировании директории ивент create затрагивает все файлы и подкаталоги, то при перемещении в пределах одного физического раздела ивент moved_to затрагивает только лишь перемещаемый каталог(знает о операции с инодой каталога, но ведь иноды внутри него остаются нетронутыми), и не действует на подкаталоги и файлы в нем. В результате, совершая операцию перемещения, мы можем потерять самое главное, из-за чего мы затеяли все это — наследование прав. Поэтому, я решил пожертвовать производительностью, тем более, что операция перемещения большого количества файлов одновременно производится редко.
Теперь необходимо создать скрипт для init.d

Мне не понравились варианты запуска из rc.local, поэтому пускающий скрипт inotifywait.sh в init.d у нас будет выглядеть примерно так:

sudo nano /etc/init.d/inotifywait.sh

#! /bin/sh
case "$1" in
start|"")
rm -f /tmp/inotifywait.log
/usr/local/bin/inotifywait.sh /home/sharez/ >/tmp/inotifywait.log 2>&1 &
;;
restart|reload|force-reload)
echo "Error: argument '$1' not supported" >&2
exit 3
;;
stop)
# Надо сделать так, чтобы я убивал только свои inotifywait
;;
*)
echo "Usage: inotifywait.sh [start|stop]" >&2
exit 3
;;
esac
:


Делаем наши скрипты исполняемыми:
sudo chmod a+x /usr/local/bin/
sudo chmod a+x /etc/init.d/inotifywait.sh


Добавляем загрузочный скрипт в ранлевелы и запускаем:
sudo update-rc.d inotifywait.sh defaults
sudo service inotifywait.sh start


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

При этом заодно я решил одну побочную задачу: как вы видите, кроме прав доступа в скрипте я еще назначаю владельца и группу. В реальности, несколько таких скриптов управляют документооборотом в офисе на одних бинарных правах, не прибегая к acl. Документ проходит определённый путь отдел за отделом, и в каждый момент времени только один отдел имеет право на редактирование (или даже чтение).

UPD: немного изменил название, теперь оно меньше соответствует оригинальной статье karapuzа, зато вернее по сути.
Теги:
Хабы:
Всего голосов 24: ↑21 и ↓3+18
Комментарии17

Публикации

Истории

Ближайшие события

19 августа – 20 октября
RuCode.Финал. Чемпионат по алгоритмическому программированию и ИИ
МоскваНижний НовгородЕкатеринбургСтавропольНовосибрискКалининградПермьВладивостокЧитаКраснорскТомскИжевскПетрозаводскКазаньКурскТюменьВолгоградУфаМурманскБишкекСочиУльяновскСаратовИркутскДолгопрудныйОнлайн
3 – 18 октября
Kokoc Hackathon 2024
Онлайн
24 – 25 октября
One Day Offer для AQA Engineer и Developers
Онлайн
25 октября
Конференция по росту продуктов EGC’24
МоскваОнлайн
26 октября
ProIT Network Fest
Санкт-Петербург
7 – 8 ноября
Конференция byteoilgas_conf 2024
МоскваОнлайн
7 – 8 ноября
Конференция «Матемаркетинг»
МоскваОнлайн
15 – 16 ноября
IT-конференция Merge Skolkovo
Москва
25 – 26 апреля
IT-конференция Merge Tatarstan 2025
Казань