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

    В ситуации, когда имеется общий каталог на сервере с несколькими пользователями (к примеру на файлопомойке в локальной сети), перед вами может встать проблема, когда необходимо давать права на чтение-запись всем зарегистрированным пользователям. Ситуация уже обсуждалась на Хабре, поэтому позволю себе буквально процитировать статью пользователя 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а, зато вернее по сути.

    Similar posts

    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 17

      +4
      хорошее решение.
      но я думаю проще было бы работать через шары.
        0
        Через шары самбы? Велосипед NFS я предпочел велосипеду CIFS.
        +4
        А чем bindfs не угодил?
          0
          Биндить директории нескольким десяткам пользователей разной степени удалённости — не очень удобное решение. К тому же оно не решает проблем с правами.
            0
            Решает полностью.
            bindfs для группы пользователей + nfs поверх. Работает исправно.
              0
              Да, почитал про ваш метод и соглашусь. Век живи — век учись!
                0
                Хотя, есть отличие. То, что я читал, упирается в следующий момент, при

                bindfs -o perms=0770,mirror=@family,group=family /media/Data/ /media/Data/

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

                (не спорю, маны я не читал, может там есть прямое указание на нормальный метод, без таких дыр?).
              0
              Присоединюсь — bindfs — самое простое решение.
              +3
              а ещё мне интересно, чем не угодила NFS-шара с домашнего медиабокса :)
                0
                На самом деле пользователи и подключаются через NIS+NFS.
                –1
                Юзаю Dropbox, там есть галочка работать по лану :)
                  0
                  Десятками дропбоксов будет управляться еще сложнее чем так. Да и не «энтерпрайзно» пользоваться сервисами с сомнительной политикой безопасности.
                  +1
                  спасибо, у нас как раз похожая проблема. Сервак служит ещё и рабочей станцией и юзер упорно не хочет лезть на шару через smb (в которой можно указать фиксированную группу для всех заливаемых файлов)), ему удобнее через файловую систему. Описанный костыль вполне разрулит ситуацию :-)
                    0
                    В принципе, у нас похожая ситуация, только пользователей, которые ходят через CIFS — 3 человека.
                    0
                    Зачем так сложно? Есть же NFS с all_squash.
                      0
                      При all_squash я не управляю правами. Некошерно.

                      Only users with full accounts can post comments. Log in, please.