Как переместить и воссоздать папку одновременно?

9

У меня есть папка statisticsна сервере Ubuntu, в которой регулярно хранятся файлы данных. Как я могу переименовать statisticsпапку backup-xxпри повторном создании statisticsпапки, чтобы быть доступным для хранения новых файлов?

Файлы в statisticsпапке созданы PHP file_put_contents.

Я предпочитаю переименовывать папку, так как в ней много файлов statistics.

Googlebot
источник
Сначала я подумал, что вы имели в виду «одновременно», что операция должна быть «атомарной» (насколько это возможно).
phk
@phk Да, именно это я и имел в виду.
Googlebot
Между прочим, правильной терминологией будет «каталог», а не «папка».
Berk Özbalcı

Ответы:

7
mv statistics backup-xx && mkdir statistics

Это приведет к переименованию существующего statisticsкаталога backup-xx, а в случае успеха он продолжит создание нового statisticsкаталога.

Для более элементарной операции рассмотрите возможность создания каталога statistics-001(или аналогичного, возможно, путем замены 001текущей даты в подходящем формате) и символической ссылки на него, называемой statistics:

mkdir statistics-001
ln -s statistics-001 statistics

Если вы хотите «повернуть» это так, чтобы новые данные попадали в чистый каталог, сначала создайте каталог, а затем заново создайте statisticsссылку на него:

mkdir statistics-002
ln -sf statistics-002 statistics

mv statistics-001 backup-001

Таким образом, любая программа для написания в statisticsкаталоге (то есть каталог , в котором эта символическая ссылка указывает) никогда 1 не найти.

Если вам нужны особые права доступа или права доступа к каталогу, на который он statisticsуказывает, установите их перед (повторным) созданием ссылки.

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

Кусалананда
источник
1
Вы также chown --reference=backup-xx statistics ; chmod --reference=backup-xx statisticsможете установить владельца и разрешения. В идеале вы должны сделать это перед переименованием, так что mkdir new ; chown ; chmod ; mv stats backup ; mv new statsпроцесс типа.
Стивен Харрис
@StephenHarris Да, в системах с такими флагами.
Кусалананда
Это не атомно, хотя. Это близко к атомному, но не совсем.
CVn
@ MichaelKjörling Исправлено.
Кусалананда
ln -sfне атомно. Указано, что нужно отсоединить старую символическую ссылку, а затем создать новую, которая обязательно не является атомарной. Вместо этого вы должны создать дополнительную временную символическую ссылку и использовать renameфункцию (например, через mvкоманду), чтобы атомарно заменить старую. Смотрите мой подход к этому здесь: git.musl-libc.org/cgit/musl/tree/tools/…
R .. GitHub ОСТАНОВИТЬ ПОМОЩЬ ICE
12

Нет никакого способа атомарно заменить каталог другим каталогом. Вы можете переместить старый каталог, а затем создать новый каталог:

mv statistics backup-xx
mkdir statistics

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

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

mkdir "statistics-$(date +%Y%m%d)"

(или, тем не менее, вы хотите выбрать соглашение об именах каталогов). Создайте символическую ссылку с фиксированным именем на текущее местоположение:

ln -s  statistics

Чтобы заменить каталог, сначала создайте новый каталог и новую символическую ссылку, а затем переместите ее, чтобы перезаписать старую символическую ссылку. Обратите внимание, что ни простая mvсимволическая ссылка, ни простая не ln -sбудут этого делать: они создадут запись в целевом каталоге. GNU coreutils также ln -snfне подходит, потому что он удаляет существующую символическую ссылку перед созданием новой, что оставляет небольшое временное окно, в течение которого путь не существует. Вы можете использовать GNU coreutils mv -Tпо новой символической ссылке.

new_dir="statistics-$(date +%Y%m%d)"
mkdir "$new_dir"
ln -s statistics.new
mv -Tf statistics.new statistics
Жиль "ТАК - прекрати быть злым"
источник
busybox' ln -sfТакже не является атомарной, я не знаю ни одной реализации , что есть.
phk
1
Кроме того, символические ссылки комментариев phk также не на 100% безопасны, потому что запущенный процесс может все еще иметь дескриптор файла открытого каталога (цель символической ссылки), и он может создавать больше новых файлов в переименованном каталоге (например, openat()CWD). Я бы только переместил содержимое каталога на новый. Это все еще небезопасно в отношении открытых файлов, но немного лучше. В случае сомнений используйте, logrotateкоторые должны уважать такие вопросы наилучшим образом
rudimeier
1
@phk symlinkСистемный вызов не перезаписывает существующий файл, поэтому, к сожалению, невозможно напрямую переключать символическую ссылку. renameСистемный вызов будет перезаписывать существующий файл, но раздражающе нет переносимого способа сделать это в оболочке; это возможно с GNU coreutils благодаря -Tопции.
Жиль "ТАК - перестань быть злым"
3

Не переименовывайте каталог вообще. Вы сказали, что предпочитаете переименовывать каталог, потому что в нем много файлов. Единственная причина, по которой я могу подумать, что вы захотите, это потому, что копирование файлов займет слишком много времени. Однако перемещение (т. Е. Переименование) файлов происходит мгновенно, если они перемещены в местоположение в одной и той же файловой системе. Я предполагаю, что это то, что вам нужно сделать, так как, если вы меняете файловые системы, mvэто займет столько времени, сколько cpбы он ни перемещал: каталог или его содержимое.

Итак, просто сделайте:

mkdir backup-xx && mv statistics/* backup-xx

Если вам нужно также получить скрытые файлы, вы можете сделать:

mkdir backup-xx && mv statistics/* statistics/.* backup-xx

Или, если используете bash:

shopt -s dotglob; mkdir backup-xx && mv statistics/* statistics/.* backup-xx

Таким образом, каталог всегда есть, но вы все равно перемещаете его содержимое в простой и быстрой операции.

Тердон
источник
1

Вы можете переместить содержимое папки статистики во вновь созданный каталог, а не перемещать саму папку. Если вы переместите всю папку, вам придется выполнить другую команду, чтобы изменить права доступа к каталогу.

mkdir -p <path>/backup-xxx
mv statistics/* <path>/backup-xxx/.
Киран Кумар Аннам
источник