В ситуации, когда имеется общий каталог на сервере с несколькими пользователями (к примеру на файлопомойке в локальной сети), перед вами может встать проблема, когда необходимо давать права на чтение-запись всем зарегистрированным пользователям. Ситуация уже обсуждалась на Хабре, поэтому позволю себе буквально процитировать статью пользователя karapuz:
В качестве решения проблемы karapuz предложил использовать один из двух имеющихся демонов мониторинга файловой системы fam или gamin и утилиту fileschanged.
Но, как показала практика, оба этих демона значительно нагружают сервер, особенно, когда пользователи активно работают с файлами в контролируемом каталоге. В сети можно найти жалобы пользователей на то, что gamin отъедает до 30% процессорного времени. Могу сказать, что такие же неутешительные результаты получил и я. Чтобы облегчить нагрузку на железку, я решил вместо названных утилит использовать утилиту inotifywait из пакета inotify-tools:
inotifywait ловко отслеживает изменения каталогов и файлов используя интерфейс inotify.
И так, программа для слежения за изменениями состояния у нас имеется, теперь нужно скормить ей необходимый каталог и заставить это делать после перезагрузки.
Вот примерное решение у меня на сервере. Допустим, нужно следить за правами в каталоге /home/sharez/
Создаем пускалку /usr/local/bin/inotifywait.sh
Внимательный взгляд заметит то, что права и владение директориями устанавливаются рекурсивно. Для чего это сделано, ведь любые рекурсивные действия — это дополнительные значительные накладные расходы? Дело в том, что inotifywait следит лишь за инодой файла или директории. И если при копировании директории ивент create затрагивает все файлы и подкаталоги, то при перемещении в пределах одного физического раздела ивент moved_to затрагивает только лишь перемещаемый каталог(знает о операции с инодой каталога, но ведь иноды внутри него остаются нетронутыми), и не действует на подкаталоги и файлы в нем. В результате, совершая операцию перемещения, мы можем потерять самое главное, из-за чего мы затеяли все это — наследование прав. Поэтому, я решил пожертвовать производительностью, тем более, что операция перемещения большого количества файлов одновременно производится редко.
Теперь необходимо создать скрипт для init.d
Мне не понравились варианты запуска из rc.local, поэтому пускающий скрипт inotifywait.sh в init.d у нас будет выглядеть примерно так:
Делаем наши скрипты исполняемыми:
Добавляем загрузочный скрипт в ранлевелы и запускаем:
Вроде и все, дикие провисания производительности, которые я периодически я ловил, когда куча народу работала со своими файлами на сервере, исчезли.
При этом заодно я решил одну побочную задачу: как вы видите, кроме прав доступа в скрипте я еще назначаю владельца и группу. В реальности, несколько таких скриптов управляют документооборотом в офисе на одних бинарных правах, не прибегая к acl. Документ проходит определённый путь отдел за отделом, и в каждый момент времени только один отдел имеет право на редактирование (или даже чтение).
UPD: немного изменил название, теперь оно меньше соответствует оригинальной статье 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а, зато вернее по сути.