Как скопировать файл транзакционно?

С GNUdate:

$ date +%FT%T.%3N%:z
2017-06-30T13:00:54.566+01:00

С bashвстроенными функциями самое близкое, что вы можете получить, это:

$ printf -v date '%(%FT%T%z)T' -1
$ printf '%s\n' "${date%??}:${date: -2}"
2017-06-30T13:00:54+01:00

как bashне поддерживает точность до доли секунды.

С последними версиямиzsh:

$ zmodload zsh/datetime
$ strftime -s date '%FT%T.%3.%z'
$ printf '%s\n' $date[1,-3]:$date[-2,-1]
2017-06-30T13:00:54.566+01:00
9
26.07.2019, 12:54
5 ответов

rsyncвыполняет эту работу. Временный файл O_EXCLсоздается по умолчанию (отключен только в том случае, если вы используете --inplace), а затем renamedповерх целевого файла. Используйте --ignore-existing, чтобы не перезаписывать B, если он существует.

На практике у меня никогда не возникало проблем с этим при монтировании ext4, zfs или даже NFS.

12
27.01.2020, 20:05

Вы можете написать для этого программу.

Используйте open(O_CREAT|O_RDWD), чтобы открыть целевой файл, прочитать все байты и метаданные, чтобы проверить, является ли целевой файл полным, если нет, есть две возможности,

  1. Неполная запись

  2. Другой процесс выполняет ту же программу.

Попытка установить блокировку описания открытого файла для целевого файла.

Сбой означает наличие параллельного процесса, текущий процесс должен существовать.

Успех означает, что последняя запись завершилась со сбоем, вы должны начать сначала или попытаться исправить это, записав в файл.

Также обратите внимание, что вам лучше fsync()после записи в целевой файл, прежде чем закрыть файл и снять блокировку, иначе другой процесс может прочитать не -, а -данные на диске -.

https://www.gnu.org/software/libc/manual/html_node/Open-File-Description-Locks.html

Это важно, чтобы помочь вам отличить параллельно работающую программу от последней аварийно завершенной операции.

2
27.01.2020, 20:05
4
27.01.2020, 20:05

Вы получите правильный результат, выполнив cpвместе с mv. Это либо заменит «B» новой копией «A», либо оставит «B» таким, каким он был раньше.

cp A B.tmp && mv B.tmp B

обновление для соответствия существующимB:

cp A B.tmp && if [ ! -e B ]; then mv B.tmp B; else rm B.tmp; fi

Это не 100% атомарность, но близко к этому. Существует состояние гонки, когда две из этих вещей работают, обе одновременно входят в тест if, обе видят, что Bне существует, затем обе выполняют mv.

0
27.01.2020, 20:05

Я думаю, Rsync — подходящий инструмент.

Вы должны использовать rsync -Pahn --контрольная сумма /path/from/source/destination/path

Однако будьте осторожны, файлы у вас очень большие...

-1
08.04.2021, 18:43

Теги

Похожие вопросы