Получить имя устройства для пути или идентификатора тома

Итак, мне приходится работать в рамках пользовательских квот в системе Linux, и мне нужно узнать имя устройства (например, - /dev/md2) для заданного пути, чтобы я мог найти правильную квоту для этого пути.

Теперь я могу достаточно легко получить точку монтирования, используя:

df -k "/volume1/foo/bar" | tail -1 | awk '{ print $6 }'

Однако я не уверен, как лучше всего взять эту точку монтирования и преобразовать ее в имя устройства?

Чтобы еще больше усложнить ситуацию, точка монтирования, которую я получаю от приведенной выше команды, на самом деле может быть зашифрованной папкой, и в этом случае у меня может быть что-то вроде:

/dev/md2 -> /volume1
/volume1/@Foo@ -> /volume1/Foo

Это означает, что приведенная выше команда df идентифицирует точку монтирования /volume1/Foo. Однако мне нужен надежный, независимый от платформы способ работать с точками монтирования и находить фактическое имя устройства, которое мне нужно для использования с quota.

Конкретно; Я не могу просто полагаться на то, что первая часть пути является точкой монтирования устройства, поскольку я могу работать со средами, которые монтируют тома в более конкретных местах, например, OS X, которая помещает монтирование в /Volumes/ например.


person Haravikk    schedule 02.05.2013    source источник
comment
На самом деле вам не нужно искать точку монтирования. Вам просто нужен номер устройства, на котором находится целевой файл, который вы можете получить непосредственно с помощью stat -c%d /volume1/foo/bar. Затем вам нужно найти специальный узел в /dev с этим номером устройства. Я не могу найти хороших универсальных инструментов для сценариев, которые сделают эту последнюю часть за вас, но если у вас установлен grub, вы всегда можете использовать grub-probe для решения всего вопроса с помощью одной командной строки, поэтому: /usr/sbin/grub-probe --target=device /volume1/foo/bar   -  person Celada    schedule 02.05.2013
comment
Вы также можете попробовать программу 'di': gentoo.com/di . Он будет искать информацию о квоте и использовать ее для отображения доступного пространства.   -  person Brad Lanam    schedule 03.05.2013
comment
К сожалению, у меня нет ни grub, ни di; Мне нужно, чтобы сценарий был как можно более общего назначения, что является огромной головной болью, поскольку df и quota на самом деле не гарантируют одинаковое форматирование на разных платформах, ба! Я даже не уверен, что могу полагаться на параметр -c для статистики, одно устройство, которое я использую, не поддерживает его, что означает grep и awk, я полагаю. Я не уверен, что делать с идентификатором устройства из stat, но у меня есть один из eh/14d, который я нигде не узнаю.   -  person Haravikk    schedule 03.05.2013
comment
Сначала вы написали Linux-систему, а теперь говорите о разных платформах. Если вам нужно, чтобы он был переносимым, вы абсолютно не можете полагаться на stat- не на всех платформах он есть OOTB (например, Solaris), а BSD (OSX) stat использует -f вместо -c.   -  person Adrian Frühwirth    schedule 04.05.2013


Ответы (1)


Итак, я попробовал и нашел следующее решение: это не очень красиво, но mount и df должны быть доступны в большинстве разновидностей Unix, и это должно возвращать правильный идентификатор устройства, работая с томами, пока он не сможет двигаться дальше. В большинстве случаев требуется только одна или две итерации.

function get_device() {
    fs=$(df -k "$1" | tail -1)

    # Determine the device for the file-system
    device=
    mnt=$(echo "$fs" | awk '{ print $6 }')
    if [ "$cached_mnt" != "$mnt" ] 
        then
            cached_mnt="$mnt"

            mnts=$(mount)
            newmnt="$mnt"

            # Try to get a root mount point (for encrypted folders etc.)
            while [ -n "$newmnt" ] 
            do
                newmnt=$(echo "$mnts" | grep " on $mnt " | awk '{ print $1 }')
                [ "$newmnt" = "$mnt" ] && break

                if [ -n "$newmnt" ] 
                    then
                        device="$newmnt"
                        mnt=$(df "$newmnt" 2> /dev/null | tail -1 | awk '{print $6 }')

                        [ "$mnt" = "$device" -o "$mnt" = "$last" ] && break
                        last="$mnt"
                fi
            done

            cached_device="$device"
        else
            device="$cached_device"
    fi

    echo "$device"
}

Простите любые опечатки, так как это из большого сценария. Он использует очень простое кэширование в случае, если несколько запросов устройств разрешаются на один и тот же диск/раздел.

person Haravikk    schedule 04.05.2013