LINUX.ORG.RU

Блокировка добавлении файла на сервер

 , ,


0

1

Есть сервер с файлами.
Есть bash-скрипт, который заливает файлы на сервер через ssh-соединение (scp). Имена файлам он придумывает с помощью sha256sum, проверяет, что такого файла на сервере нет, заливает. Если файл уже есть - добавляет к получившейся сумме текущую дату, и берет сумму от получившегося текста.

Скрипт будет выполняться с разных машин, т.е. чисто теоретически может возникнуть ситуация, когда 2 скрипта сгенерировали одинаковые суммы, проверили, что таких файлов еще нет и по очереди залили данные в один и тот же файл. В итоге один из файлов потеряется.

Собственно вопрос. Какой самый модный способ не допустить такого поведения, если на сервере нельзя запускать дополнительный софт (т.к. это файлопомойка и там рулит админ).

P.S. Разговоры о том, что вероятность получения двух одинаковых сумм ничтожно мала предлагаю оставить на пятничный вечер. Этим двум скриптам очень даже могут достаться одинаковые файлы, да и количество файлов со временем будет очень велико.

★★★★★

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

dd if=/dev/urandom count=1 bs=256 2>/dev/null | sha256sum

Slavaz ★★★★★
()

добавлять файлы в каталоги, называемые по текущей дате времени в юникс-ипок-времени, сцепленной r fingerprint'у клиента

anonymous
()

Можно секцию выбора имени файла защитить с помощью flock.

anonymous
()

А если надо «железобетонный» способ по избежанию коллизий безо всяких теорий вероятности, то хеш-алгоритмы не помогут. Я бы игрался в сторону эксклюзивного открытия некоего файла-семафора, в котором ведём некий счётчик уникальных значений. Тогда будут всегда уникальные имена файлов на основе этого счётчика. Но тут становится bottle neck сам файл-семафор - пока один сервак не отработает семафор и не возьмёт счёётчик с приростом, второй(третий, десятый) сервак будет ждать...

Ну или каждый сервак ведёт свой счётчик, но при этом добавляет свой уникальный префикс/суффикс к имени файла.

Slavaz ★★★★★
()
Последнее исправление: Slavaz (всего исправлений: 1)

Ну можно хеш (хотя лучше epoch) передавать в качестве шаблона для mktemp, хотя (чисто) теоретически коллизии тоже возможны.

anonymous
()
cd uploads; file=`date +%s-$RANDOM-$(ls -l | wc -l)`.file

Железнобетонный способ

derlafff ★★★★★
()
Последнее исправление: derlafff (всего исправлений: 1)

А что, mktemp на сервере нет?

ABW ★★★★★
()

Создание каталога - гарантированно атомарная операция. Можно вместо файлов хеш-имена давать каталогам.

Kuzz ★★★
()

если на сервере нельзя запускать дополнительный софт

Там что, scponly для ваших ssh-соединений? Если нет, то заливайте через «ssh 'cat - > ...'», а не через scp. Тогда выполняемый ssh на сервере команды могут сами определить имя файла, или добавить к имени-хешу что-нибудь уникальное на момент передачи файла, допустим PID.

mky ★★★★★
()

Добавлять еще нечто вроде соли, завязанной на IP/hostname машины, с которой заливают файл? Если хотим исключить ситуацию «в один и тот же момент 2 машины сгенерировали одинаковый хэш».

strangeman ★★★★
()

Есть единственный мне известный надёжный метод, который даже теоретически не допускает коллизий (за исключением NFS).

Это не пользоваться кодом типа

if ( ! open(file, O_RDONLY) ) {
    close(file)
    open(file, O_WRONLY)
}
потому что неатомарно! Но только так:
if ( open(file, O_WRONLY, O_CREAT | O_EXCL ))
    // write to file

gag ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.