45

同じ親ディレクトリに2つのディレクトリがあります。親ディレクトリベースと子ディレクトリalphaおよびbravoを呼び出します。alphabravoに置き換えたい。最も簡単な方法は次のとおりです。

rm -rf alpha
mv bravo alpha

mvコマンドはアトミックですが、rm-rfはアトミックではありません。アルファブラボーにアトミックに置き換えるbashの簡単な方法はありますか?そうでない場合、複雑な方法はありますか?

補遺:

ちなみに、ディレクトリが短期間存在しなくても、克服できない問題ではありません。アルファにアクセスしようとする場所は1つだけであり、重要なことを行う前にアルファが存在するかどうかをチェックします。そうでない場合は、エラーメッセージが表示されます。しかし、これを行う方法があればいいのですが。:)iノードを直接変更する方法があるかもしれません。

4

16 に答える 16

58

最終的な解決策は、シンボリックリンクと名前変更のアプローチを組み合わせることです。

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

もちろん、alpha にアクセスするアプリケーションは、パス内で変化するシンボリック リンクを処理できなければなりません。

于 2012-06-04T19:15:48.490 に答える
21

シンボリックリンクを使用すると、これを行うことができます:

alpha がディレクトリ alpha_1 へのシンボリック リンクであり、そのシンボリック リンクを alpha_2 を指すように切り替えたいとします。切り替え前はこんな感じ。

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

alpha が alpha_2 を参照するようにするには、ln -nsf を使用します。

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

これで古いディレクトリを削除できます:

$ rm -rf alpha_1

これは実際には完全にアトミックな操作ではないことに注意してください。ただし、「ln」コマンドはリンクを解除してすぐにシンボリック リンクを再作成するため、非常に迅速に行われます。この動作は strace で確認できます。

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

必要に応じてこの手順を繰り返すことができます。たとえば、新しいバージョンの alpha_3 がある場合:

$ ln -nsf alpha_3 alpha
$ rm -rf alpha_2
于 2008-11-21T01:28:28.877 に答える
17

ここでDavidのソリューションを取り上げます。これは完全にアトミックです...あなたが遭遇する唯一の問題は、-Tオプションmvが非POSIXであるため、特定のPOSIX OSがそれをサポートしていない可能性があることです(FreeBSD、Solarisなど.. http://pubs.opengroup.org/onlinepubs/9699919799/utilities/mv.html ) 。わずかな変更により、このアプローチは完全にアトミックになり、すべての POSIX OS で移植可能になります。

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 ./

例: http://axialcorps.wordpress.com/2013/07/03/atomically-replaceing-files-and-directories/

于 2013-07-05T15:55:16.367 に答える
8

セマフォとして機能するには、別の保証されたアトミック操作を使用します。

したがって、ファイル操作の作成と削除がアトミックである場合:

1) 「セマフォ」というファイルを作成します。

2)それが成功した場合(既存のファイルと競合しない場合)にのみ、操作を実行します(プロセスに応じて、アルファをプロセスするか、ディレクトリを移動します)

3) rm セマフォ。

于 2008-11-21T01:33:45.230 に答える
6

両方の操作でアトミックを意味する場合、私はそうは思わない。最も近いのは次のとおりです。

mv alpha delta
mv bravo alpha
rm -rf delta

しかし、それでもアルファが存在しなかった小さなウィンドウがあります。

アルファが存在しないときにアルファを使用しようとする可能性を最小限に抑えるために、次のことができます(権限がある場合)。

nice --20 ( mv alpha delta ; mv bravo alpha )
rm -rf delta

これにより、操作が行われている間、プロセスの優先順位が大幅に上がりますmv

補遺で述べているように、アルファをチェックする場所が1つだけで、そこにない場合はエラーになる場合は、そのコードをすぐにエラーにならないように変更できますが、短時間で再試行してください(2回のmv操作で1秒未満) 。 -アルファを頻繁に交換しない限り、これらの再試行によって問題が軽減されるはずです。

于 2008-11-21T00:51:57.017 に答える
4

SQLiteのドキュメント セクションFile Locking and Concurrency in SQLite Version 3には、同時読み取り、排他的書き込み、およびクラッシュ後のロールバックを制御するエスカレートするロック プロトコルの詳細な説明があります。それらのアイデアのいくつかはここに当てはまります。

于 2009-11-07T23:00:18.477 に答える
4

これでうまくいくはずです:

mkdir bravo_dir alpha_dir
ln -s bravo_dir bravo
ln -s alpha_dir alpha
mv -fT bravo alpha

strace mv -fT bravo alpha ショー:

rename("bravo", "alpha")

私にはかなりアトミックに見えます。

于 2014-01-06T21:50:52.983 に答える
1

iノードに直接アクセスしている場合でも、ユーザースペースでiノード値をアトミックに交換する方法はありません。

于 2008-11-21T01:19:56.977 に答える
1

操作のアトミックな性質について心配しても意味がありません。とにかく、他のタスクによるアルファへのアクセスはアトミックではありません。

Oddthinking のセマフォ アプローチが唯一の方法です。

他のタスクを変更できない場合は、置換を行う前に実行されていないことを確認する必要があります。

于 2008-11-21T04:17:12.390 に答える
0

これを行うための原子的な方法はないと思います。あなたの最善の策は、次のようなことをすることです。

mv alpha delme
mv bravo alpha
rm -rf delme
于 2008-11-21T00:51:34.287 に答える
0

mv と ln はアトミック操作に使用できます。ln(1) を使用して、Web アプリケーションをアトミックにデプロイしました。

シンボリックリンクを置き換える正しい方法は、ln -nsf を使用することです

ln -nsf <target> <link_name>

例えば

$ mkdir dir1
$ mkdir dir2
$ ln -s dir1 mylink
$ ls -l mylink
lrwxrwxrwx  1 phil phil 4 Nov 16 14:45 mylink -> dir1
$ ln -nsf dir2 mylink
$ ls -l mylink
lrwxrwxrwx  1 phil phil 4 Nov 16 14:46 mylink -> dir2
于 2009-11-16T14:48:00.087 に答える
0

覚えておくべきことは、この移動/削除が発生したときにプロセスがアルファ版のファイルを開いている場合、プロセスは気付かず、ファイルが閉じられて最終的に削除されると、書き込まれたデータは失われるということです。

于 2008-11-21T03:38:51.237 に答える
-2

次のようなことをしてみませんか。

rm -rf alpha/*
mv bravo/* alpha/
rm -rf bravo/

これは、アルファのすべてが破棄され、アルファが削除されることはなく、すべてのコンテンツが移動されることを意味します。

于 2008-11-21T04:44:07.250 に答える