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 ★★★★★
()
Вы не можете добавлять комментарии в эту тему: топик перемещен в архив.