LINUX.ORG.RU

Как потокобезопасно скопировать файл (bash)?

 ,


0

3

У меня есть файл, мне необходимо проделать над ним некоторую длительную операцию будучи уверенным в том, что во время работы с ним никто другой его не изменит. Логично, что проще всего скопировать файл во временный, и проделывать операции с ним. Дает ли нам стандартный cp умеренность в том, что во время копирования никто ничего с ним не сделает? Если да, и это гарантирует нам ядро, то каким образом это организованно там? Где почитать?


Не гарантирует, операция не атомарная

anonymous
()
Ответ на: комментарий от ymn

Хорошо, а каким образом тогда организовать атомарность? Как-то ведь это делается, в том же самом git'е например.

actics
() автор топика
Ответ на: комментарий от ymn

rename атомарный тоже не всегда. Атомарность гарантируется только если ты вызываешь его из одной и той же директории

actics
() автор топика
Ответ на: комментарий от x905

Тут закономерный вопрос возникает: гарантирует ли md5sum, что хеш будет посчитан именно для того файла, который мы указали при запуске. А если во время работы файл изменили?

actics
() автор топика
Ответ на: комментарий от actics

а неважно т.к. считаем 2 раза
1. md5_1
2. наша работа с файлом
3. md5_2
если md5_1 и md5_2 неравны, то работа наша скорее всего неверна

x905 ★★★★★
()
Ответ на: комментарий от x905

Окей. Другая задача. Мне нужно md5 именно от того самого файла, который был на момент вызова md5sum. Как это решить.

actics
() автор топика

Можно скопировать файл во временный, потом сравнить командой cmp с исходным, если отличий нет - работать со временным, если есть - всё повторить.

x-signal ★★
()
Ответ на: комментарий от actics

Давай начнем с начала: что за файл, кто кроме тебя его может изменить и почему?

1. проверить (fuser) что файл никто не открыл
2. переименовать его в «случайное» имя (можно сделать скрытый файл)
3. копировать

или

1. проверить (fuser) что файл никто не открыл
2. начать копировать в фоне ( & ) и сразу удалить исходный файл, чтобы никто другой до него не дотянулся.

anonymous
()

вангую что задача сформулирована некорректно

zolden ★★★★★
()
Ответ на: комментарий от actics

Мне нужно md5 именно от того самого файла, который был на момент вызова md5sum. Как это решить.

1. md5_1
2. `md5 именно от того самого файла`
3. md5_2

)

x905 ★★★★★
()
Ответ на: комментарий от anonymous

Тебе же говорят, что в процессе первого подсчета md5sum файл может поменяться.

а я и отвечаю - для этого и есть второй подсчет

x905 ★★★★★
()
Ответ на: комментарий от x905

Ты не понял.

Условно:

0. Исходная (неизвестная нам) md5 — 12345
1. Начали считать первую md5 (файл в процессе изменился) и получили md5 — 23456
2. Второй подсчет тоже дал 23456, но файл то изменен

anonymous
()
Ответ на: комментарий от actics

Тут закономерный вопрос возникает: гарантирует ли md5sum, что хеш будет посчитан именно для того файла, который мы указали при запуске. А если во время работы файл изменили?

1) Получить время последнего изменения. 2) Посчитать md5sum. 3) Проверить совпадает ли время последнего изменения с тем что получили в п.1 Если нет то кто-то что-то сделал с файлом.

anonymous
()

В случае, если файловая система zfs или btrfs, можно создать легковесную копию файла командой

cp --reflink исх_файл рабочая_копия

поработать с копией, потом копию удалить.

netam
()
Ответ на: комментарий от anonymous

Ты не понял.

ок, наверно

если можно принять, что «длительная операция над файлом» это именно шаг №2 (после первого подсчета md5), то все вполне работает

возможно ТС сможет уточнить задачу

еще думаю можно Inotify прикрутить

x905 ★★★★★
()
Ответ на: комментарий от x905

сама md5sum длительная операция, примерно равная по времени копированию (между разными дисками)

anonymous
()

Пишешь во временный файл в директории где должен быть целевой файл и переименовываешь его. man 2 rename и man 2 mkstemp.

omnomnomnus
()

Сам не пробовал, но судя по этому можно попробовать через SELinux. Вроде бы можно указать конкретный процесс с контекстом для доступа к конкретному файлу.

ronkajitsu
()
Ответ на: комментарий от anonymous

Вот, я ожидал нечто подобное. Не понимаю почему не догадался сам.
Вопрос собственно о лучших практиках. Наверняка в различных приложениях возникает такая задача.

actics
() автор топика
Ответ на: комментарий от anonymous

В каких случаях оно может не поменяться? Ну если исключить вариант с тем, что ядро само перезаписало кусок файла и не проставило метки.

actics
() автор топика
Ответ на: комментарий от x905

Вопрос скорее абстрактный, а не для конкретной реализации. В общем: мне интересно как избегают рейс-кондишнс в случаях работы с файлами. Например. У нас есть 2 процесса, они полностью независимые, написаны разными людьми и ничего друг про друга не знают. Процесс 1 достаточно часто перезаписывает куски файла. Процесс 2 фиксирует время t1 и хочет получить копию файла с гарантией того, что это копия будет побайтно совпадать с файлом, который существовал в момент времени t1. Как это реализуют?

actics
() автор топика

google://acid+filesystem
result: need more mushroom to parse it

system-root ★★★★★
()
Ответ на: комментарий от actics

На обычных как бы inotify, вроде. Только вот кто скажет всегда ли оно работает?

А вот про acid+filesystem не знаю, разве это не просто библиотеки для конкретного приложения? В смысле, есть ли такие, с которыми как с любой другой можно работать, а не только из кода?

ronkajitsu
()
Ответ на: комментарий от actics

У нас есть 2 процесса, они полностью независимые, написаны разными людьми и ничего друг про друга не знают. Процесс 1 достаточно часто перезаписывает куски файла. Процесс 2 фиксирует время t1 и хочет получить копию файла с гарантией того, что это копия будет побайтно совпадать с файлом, который существовал в момент времени t1. Как это реализуют?

Тут либо поискать уже готовый софт либо написать самому перехват вызовов к файла и добавить возможность второму процессу дочитать блокируя изменения для первого процесса.
Гугли по словам «exclusive file lock».

V1KT0P ★★
()
Ответ на: комментарий от actics

Если с одним файлом нужно работать из двух процессов то как-то вырабатывают механизм взаимной блокировки (хоть через создание lock-файла, хоть через системный вызовы). Изменения в файл обычно вносятся не одним вызовом write(), поэтому в произвольный момент времени информация в файле может быть не целостной, поэтому и делают блокировки.

А ваша задача какое-то извращение и для этого есть разные костыли, типа fcntl( F_SETLEASE ), BTRFS_IOC_CLONE (если он рабочий), снапшот файловой системы.

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