GNU/Linux >> Belajar Linux >  >> Linux

Memindahkan direktori secara atomik

Sejak Linux 3.15, renameat2 baru system call secara atomik dapat bertukar dua jalur pada sistem file yang sama. Namun, belum ada pembungkus glibc untuk itu, apalagi cara coreutils untuk mengaksesnya. Jadi akan terlihat seperti ini:

int dirfd = open(".../base", O_PATH | O_DIRECTORY | O_CLOEXEC);
syscall(SYS_renameat2, dirfd, "alpha", dirfd, "bravo", RENAME_EXCHANGE);
close(dirfd);
system("rm -rf alpha");

(Tentu saja, Anda harus melakukan penanganan kesalahan yang benar, dll. – lihat intisari ini untuk renameat2 yang lebih canggih pembungkus.)

Yang mengatakan - solusi symlink yang disebutkan oleh orang lain lebih mudah dan portabel, jadi kecuali bravo sudah ada dan Anda harus perbarui secara atomik, alih-alih gunakan symlink.

Pembaruan 2020:pembungkus glibc untuk panggilan sistem ini tersedia sejak glibc 2.28, dirilis 01-08-2018 (Debian Stretch, Fedora 29). Itu masih tidak dapat diakses melalui coreutils.

int dirfd = open(".../base", O_PATH | O_DIRECTORY | O_CLOEXEC);
renameat2(dirfd, "alpha", dirfd, "bravo", RENAME_EXCHANGE);
close(dirfd);
system("rm -rf alpha");

Solusi terakhir adalah menggabungkan symlink- dan pendekatan rename:

mkdir alpha_real
ln -s alpha_real alpha

# now use "alpha"

mkdir beta_real
ln -s beta_real tmp 

# atomically rename "tmp" to "alpha"
# use -T to actually replace "alpha" instead of moving *into* "alpha"
mv -T tmp alpha

Tentu saja, aplikasi yang mengakses alfa harus dapat menangani perubahan symlink di jalur.


Mengambil solusi David di sini, yang sepenuhnya atom ... satu-satunya masalah yang Anda temui adalah -T opsi untuk mv adalah non-POSIX, dan OS POSIX tertentu mungkin tidak mendukungnya (FreeBSD, Solaris, dll. ... http://pubs.opengroup.org/onlinepubs/9699919799/utilities/mv.html). Dengan sedikit modifikasi, pendekatan ini dapat diubah menjadi sepenuhnya atomik, dan portabel di semua OS POSIX:

mkdir -p tmp/real_dir1 tmp/real_dir2
touch tmp/real_dir1/a tmp/real_dir2/a
# start with ./target_dir pointing to tmp/real_dir1
ln -s tmp/real_dir1 target_dir
# create a symlink named target_dir in tmp, pointing to real_dir2
ln -sf tmp/real_dir2 tmp/target_dir
# atomically mv it into ./ replacing ./target_dir
mv tmp/target_dir ./

contohnya melalui:http://axialcorps.wordpress.com/2013/07/03/atomically-replacing-files-and-directories/


Anda dapat melakukan ini jika menggunakan symlink:

Katakanlah alpha adalah symlink ke direktori alpha_1, dan Anda ingin mengalihkan symlink untuk menunjuk ke alpha_2. Inilah tampilannya sebelum beralih:

$ ls -l
lrwxrwxrwx alpha -> alpha_1
drwxr-xr-x alpha_1
drwxr-xr-x alpha_2

Untuk membuat alpha merujuk ke alpha_2, gunakan ln -nsf:

$ ln -nsf alpha_2 alpha
$ ls -l
lrwxrwxrwx alpha -> alpha_2
drwxr-xr-x alpha_1
drwxr-xr-x alpha_2

Sekarang Anda dapat menghapus direktori lama:

$ rm -rf alpha_1

Perhatikan bahwa ini BUKAN sebenarnya operasi yang sepenuhnya atomik, tetapi ini terjadi dengan sangat cepat karena perintah "ln" membatalkan tautan dan kemudian segera membuat ulang symlink. Anda dapat memverifikasi perilaku ini dengan strace:

$ strace ln -nsf alpha_2 alpha
...
symlink("alpha_2", "alpha")             = -1 EEXIST (File exists)
unlink("alpha")                         = 0
symlink("alpha_2", "alpha")             = 0
...

Anda dapat mengulangi prosedur ini sesuai keinginan:mis. ketika Anda memiliki versi baru, alpha_3:

$ ln -nsf alpha_3 alpha
$ rm -rf alpha_2

Linux
  1. Temukan Kecualikan Direktori?

  2. Mensimulasikan Tautan Keras Ke Direktori?

  3. Perintah Pindah Direktori Linux

  1. Direktori JAVA_HOME di Linux

  2. Struktur direktori CentOS sebagai pohon?

  3. direktori game?

  1. Pwd Tanpa Symlink?

  2. Ganti Nama File Di Direktori?

  3. Cd Ke Direktori Nama-Tidak Dikenal Di Jalur yang Diketahui?