GNU/Linux >> Znalost Linux >  >> Linux

Přesouvání adresáře atomicky

Od Linuxu 3.15 nový renameat2 systémové volání může atomicky vyměňovat dvě cesty na stejném systému souborů. Zatím však pro něj neexistuje ani obal glibc, natož způsob, jak k němu získat přístup pomocí coreutils. Takže by to vypadalo nějak takto:

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");

(Samozřejmě byste měli provést správné zpracování chyb atd. – v tomto souhrnu najdete sofistikovanější renameat2 obal.)

To znamená – řešení symbolického odkazu zmiňované ostatními je jednodušší a přenosné, takže pokud bravo již existuje a vy musíte atomicky jej aktualizujte, místo toho použijte symbolický odkaz.

Aktualizace 2020:obal glibc pro toto systémové volání je k dispozici od glibc 2.28, vydaného 1. 8. 2018 (Debian Stretch, Fedora 29). Stále však není přístupný prostřednictvím coreutils.

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

Konečným řešením je kombinace přístupu symbolického odkazu a přejmenování:

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

Samozřejmě, že aplikace přistupující k alfa verzi musí být schopna vypořádat se se symbolickými odkazy měnícími se v cestě.


Zde se můžete podívat na Davidovo řešení, které je plně atomové ... jediný problém, na který byste narazili, je, že -T možnost pro mv není POSIX, a proto jej některé operační systémy POSIX nemusí podporovat (FreeBSD, Solaris atd. ... http://pubs.opengroup.org/onlinepubs/9699919799/utilities/mv.html). S mírnou úpravou lze tento přístup změnit tak, aby byl plně atomický a přenosný napříč všemi operačními systémy 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 ./

například přes:http://axialcorps.wordpress.com/2013/07/03/atomically-replacing-files-and-directories/


Můžete to udělat, pokud použijete symbolické odkazy:

Řekněme, že alpha je symbolický odkaz na adresář alpha_1 a chcete přepnout symbolický odkaz tak, aby ukazoval na alpha_2. Zde je návod, jak to vypadá před přepnutím:

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

Chcete-li, aby alfa odkazovalo na alpha_2, použijte ln -nsf:

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

Nyní můžete odstranit starý adresář:

$ rm -rf alpha_1

Všimněte si, že to ve skutečnosti NENÍ plně atomická operace, ale stane se to velmi rychle, protože příkaz "ln" oba odpojí a poté okamžitě znovu vytvoří symbolický odkaz. Toto chování můžete ověřit pomocí strace:

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

Tento postup můžete libovolně opakovat:např. když máte novou verzi, alpha_3:

$ ln -nsf alpha_3 alpha
$ rm -rf alpha_2

Linux
  1. Přejmenovat soubory v adresáři?

  2. CD do neznámého adresáře na známé cestě?

  3. Simulace pevného odkazu na adresář?

  1. Příkaz přesunutí adresáře pro Linux

  2. JAVA_HOME adresář v Linuxu

  3. CentOS adresářová struktura jako strom?

  1. Pwd bez symbolických odkazů?

  2. Najít vyloučený adresář?

  3. adresář her?