単一の引数を許可するBourneシェルスクリプトがあります(テキストファイルサイズは通常数KBです)。デフォルトでは、このスクリプトはscp
このテキストファイルをリモートサーバーにコピーするラッパーです。スクリプトはscp
元のファイルを試みませんが、ファイルのハードリンクまたはコピーを作成します。
#!/bin/sh
TRANSFER_FILE=/var/tmp/acc_transfer_link_$$
INPUT_FILE=$1
# Linking is always a better option, so try it first
ln $INPUT_FILE $TRANSFER_FILE 2>/dev/null
RC=$?
if [ $RC -ne 0 ]; then
cp $INPUT_FILE $TRANSFER_FILE
fi
スクリプト作成者がコメントを残しました。
リンクは常により良いオプションなので、まず試してみてください。
なぜこれが起こるのですか?ハードリンクを作成するよりもコピーするのに少し時間がかかるからですか?他に理由がありますか?
答え1
時々違うよね
リンクの設定はデータのコピーよりも高速ですが、結果ファイルは元のファイルと同じ内容を持ち、修正は両方のファイルに表示されます。これが利点かどうかは、リンク/コピーを作成した理由によって異なります。また、ハードリンクは同じファイルシステム内でのみ機能するため、マウントがソースディレクトリ/var
と/var/tmp
は別の場合、リンクは機能しません。
しかし、ここでユースケースが何であるかを知りたいです。スクリプトの目的がにあるファイルをコピーすることであれば、元のファイルから直接実行されずに$1
コピーされるのはなぜですか?まず、ローカルコピーは、コピープロセス中にソースファイルが変更された可能性があり、ファイルを一貫性のない状態にコピーしてはならないと仮定する理由がある場合にのみ必要です。しかし、ここにはアプローチにいくつかの問題があります。$TRANSFER_FILE
scp
1)ローカルコピーを作成することもcp
同じ問題があります。ローカルコピーの作成中にソースが変更されることもあります。 2)リンクln
は即時ですが、ハードリンクは元のデータと同じデータを指すため、リンク前にファイルを開いたすべてのプロセスは引き続きデータを変更できます。
リンクしてから(類似の方法を使用して)ファイルが他のプロセスで開かないようにするかlsof
、一部のアプリケーション固有の方法でコピーを作成してデータの一貫性を確認する必要があります。どちらもあまり単純ではないので、アトミック修正を実行する一般的な方法は、ファイルの新しいコピーを作成し、名前を古いコピーに変更することです。これにより、名前を変更する前にファイルを開いたプロセスは以前のバージョンを取得し、名前を変更した後にファイルを開いたプロセスは新しいバージョンを持ちます。しかし、どちらも不完全なコピーを見ることはできません。ただし、これはファイルを読み取るプログラムではなくファイルを変更するときに行う必要があります。