2012-01-14 14 views
8

を防止bashのもとでロック行うための、シンプルで、一見信頼性の高い方法は次のとおりです。は、ロック伝播に

exec 9>>lockfile 
flock 9 

しかし、bashは悪名高い実行されるプログラムを含むすべてのフォークのものに、このようなFDロックを伝播するなど

がありますbashにfdを複製しないように伝える方法はありますか?プログラムの終了時に、ロックがどのように終了しても、ロックがfdに添付されることは素晴らしいことです。

私は同じようなものを行うことができます知っている:

run_some_prog 9>&- 

しかし、それはかなり面倒です。

もっと良い解決策はありますか?

答えて

8

あなたはファイルディスクリプタはflock(1)経由でコマンドを実行する前に閉じられなければならないことを指定するには、flock(1)に(自己文書の性質上のスクリプトで書き込みのために良いかもしれない長いオプション--closeを、)-oコマンドラインオプションを使用することができます。

-o, --close 
      Close the file descriptor on which the lock is held 
      before executing command. This is useful if command 
      spawns a child process which should not be holding 
      the lock. 
+0

Thx!まさに私が探していたもの。 – user1050755

+2

'flock 9 'では動作しません。これは' flock -o lockfileコマンド[args ..] 'の場合のみです – Tino

1

FDをbash内でclose-on-execとしてマークする方法はないので、いい方法はありません。

1

-oはファイル記述子では機能しません。ファイル記述子では機能しません。ファイルディスクリプタのロックを解除するには、-uを使用する必要があります。

私は何をすることはこれです:

# start of the lock sections 
LOCKFILE=/tmp/somelockfile 
exec 8>"$LOCKFILE" 
if ! flock -n 8;then 
     echo Rejected # for testing, remove this later 
     exit   # exit, since we don't have lock 
fi 

# some code which shouldn't run in parallel 

# End of lock section 
flock -u 8 
rm -f "$LOCKFILE" 

ロック意志を保持するだけのプロセスを意味し、ファイルディスクリプタがロックをしたプロセスによって閉鎖されると、他のすべてのプロセスが終了しますので、この方法ファイル記述子のロックを解除し、ロックファイルを削除します。

4

明らかにflock -o FDは問題を解決しません。同じシェルスクリプトで、後でコマンドに対して余分FDを取り除くためにトリックはこのように、FDを閉じセクションに残りの部分をラップすることです:

var=outside 

exec 9>>lockfile 
flock -n 9 || exit 
{ 

: commands which do not see FD9 

var=exported 
# exit would exit script 

# see CLUMSY below outside this code snippet 
} 9<&- 
# $var is "exported" 

# drop lock closing the FD 
exec 9<&- 

: remaining commands without lock 

これは近く、ビットCLUMSYですFDの現在の位置はロックから離れている。

あなたは、これが「自然」コマンドの流れを失うことなく、一緒に属するものを一緒に保つリファクタリングすることができます

functions_running_with_lock() 
{ 
: commands which do not see FD9 

var=exported 
# exit would exit script 
} 

var=outside 

exec 9>>lockfile 
flock -n 9 || exit 

functions_running_with_lock 9<&- 

# $var is "exported" 

# drop lock closing the FD 
exec 9<&- 

: remaining commands without lock 

別のフォークを犠牲にして自然なコマンドフローに加えて、追加のプロセスを保持して少しよりよい執筆少し異なるワークフローがあります。これはしばしば便利です。あなたが本当にbashが閉じたFDを「隠す」に追加のファイル記述子を(紹介してスキップしていないことを確認したい場合は、

var=outside 

exec 9>>lockfile 
flock -n 9 || exit 
(
exec 9<&- 

: commands which do not see FD9 

var=exported 
# exit does not interrupt the whole script 
exit 
var=neverreached 
) 
# optionally test the ret if the parentheses using $? 

# $var is "outside" again 

# drop lock closing the FD 
exec 9<&- 

: remaining commands without lock 

ところで:しかし、これは、外殻に変数を設定することはできません。実際のフォーク)。例えば、デーモンを実行してロックを永久に保持する場合、後者の変種が推奨されます。 lsof -nPstrace your_scriptはお友達です。