2016-11-04 5 views
1

複数のインスタンスを同時に実行できるbashスクリプトがあります。ただし、値を取得するためには、Oracleデータベースへのsqlplus接続があります。この値が複数のbashスクリプト・インスタンスによって同時にフェッチされている場合、最初のインスタンスはまだ処理中ですが、2番目のインスタンスはすでに「古いデータ」を検証しているため、同じ値を取り出す可能性があります。Bash linux複数のインスタンスがsqlplusコマンドの実行を待つように強制する

私は、PIDFILEで関数をロックする2つのオプションしか考えられません。欠点は、pidファイルが削除される前にユーザーが操作を中止すると、問題が発生することです。もう1つは、ps -ef | grep 'scriptname' | wc -lでカウントされる最大プロセスの宣言に基づいてスクリプト全体をロックする方法です。しかし、これはデータベース部分だけでなく、スクリプト全体をロックします。

別のオプションがありますか?データベースへのこのsqlplus接続を捕捉することが可能なので、この関数がインスタンスの1つによって実行されている間に複数の実行インスタンスを一時停止することができますか?

答えて

1

tmpファイル(この例では/tmp/pidfile)で一意の値を使用し、スクリプトの中止または完了時にリセットすることができます。

更新:これは固まっているようですが、下のテストを参照してください。

#!/bin/bash 


bashpid="$$"      # Records PID of script. Unused so far 
pidfile=/tmp/pidfile    # pidfile var 
pidlimit=2      # pidlimit 

cleanup() {      # cleanup operations 
     exit 
    } 

pidreset() {     # trap operations (if reqd) 
     pkill -a -P "$bashpid" 
     kill -9 0 
    } 

trap "pidreset" SIGINT   # trap (if reqd) 


countpid() {     # This is the true PID count, only called 
           # Once allowed in the database block 
           # This includes self instance 

    ps aux | grep "$(basename $0)" | grep -v grep > $pidfile 

} 

countloop() {     # This counts PID while waiting for a spot 
           # (-1 decrement since self is included but 
           # not yet granted access to database block) 
    echo "((("$(ps aux | grep "$(basename $0)" | grep -v grep | wc -l)") - 1))" | bc > $pidfile 

} 
databasecall() {    # The database script calls 

    touch $pidfile 
    pidcount="$(cat $pidfile | wc -l)" 
    until [[ "$pidcount" -le "$pidlimit" ]]; do 
     echo "too many processes" 
     countloop 
     pidcount="$(cat $pidfile | wc -l)" 
     sleep 5 
    done 

    # ================ Start of Database access Code ================ 
    # Go ahead and do database stuff 
    # Write this script into the pidfile incrementing its count also 

    countpid 
    pidcount="$(cat $pidfile | wc -l)" 
    echo "We're in" 
    echo "Scriptcount: $pidcount (Including this one)" 
    sleep 5 
    cleanup 
    # return/whatever 
    # ================ End of Database access Code ================ 

} 



echo "Main script block"   # Main script outside of Database block 
sleep .1 


databasecall      # Call database function 


cleanup       # Call to housekeeping 

は、それが正常に動作しますが、これが発生した場合、私は確かではないんだけれども、pidlimitより1つ多いの実行に落ち着くか、それはまだ私のテストシナリオだ場合

をテストします。

 
bash>echo "imrunning & sleep .5 ; imrunning & sleep .5 ; imrunning & sleep .5 ; imrunning & sleep .5 ; imrunning" > /tmp/initrunning ; chmod +x /tmp/initrunning 
bash>/tmp/./initrunning 
Main script block 
We're in 
Scriptcount:  1 (Including this one) 
Main script block 
We're in 
Scriptcount:  2 (Including this one) 
Main script block 
too many processes 
Main script block 
too many processes 
Main script block 
too many processes 
We're in 
Scriptcount:  3 (Including this one) 
We're in 
Scriptcount:  3 (Including this one) 
We're in 
Scriptcount:  3 (Including this one) 
bash

+0

これは確かに私のスクリプトをより単純なものにするものではありません。スクリプト全体をロックするのに比べてかなり面倒ですが、うまくいくと思います。 これをすべてテストしてスクリプトを修正するには時間が必要です。だから私はこれの後に学んだ(しかし、私はまだ試していない)他のオプションは1つだけです。 1つの接続のみを許可するスキーマユーザーを作成することです。 あなたのコード、時間、労力をどうもありがとう! :) –

+0

@IvanMお聞きします!最初にデータベースへの接続を厳密にロックしようとしていたことが私には分かりませんでしたので、スクリプトの一部をロックする機能にもっと焦点を当てました。私の最後には未知のものがたくさんありますが、SESSIONS_PER_USERパラメータは読み取り操作に影響しますか?あなたが完全に読書を制限しようとしている場合。パフォーマンスのニーズに応じて、 'lsof -t/path/to/db.sql'を使ってファイルへの物理アクセスを検出することができます。 – hmedia1

+0

@IvanM上記のクリーンアップ()セクションのロックファイルを削除/チェック/クリーンアップすることができます。これはctrl + cをキャッチするためのテンプレートですが、エンドユーザーからの発信として適切なイベントを割り当てることができます。 – hmedia1

関連する問題