A Day In The Boy's Life -38ページ目

A Day In The Boy's Life

とあるエンジニアのとある1日のつぶやき。

LinuxネタではなくOracleネタではあるのですが。

運用開始後にDBが正常に動作しているか監視したいという要件はよくあったりしますので、サービス監視ネタとしてまとめてみたいと思います。

環境は、Oracle11.2.0(2ノードRAC構成)、RedHat6.2環境をベースに書いています。



Oracleのサービス監視をする


サービス監視の一環として、正常にDBが稼動しているかどうかを動作しているプロセスの個数で監視(いわゆるプロセス監視)するケースはよくありますが、Oracleは動作するプロセスが非常に多かったりしますし、サービスの動作確認用コマンドが用意されていたりするので、それを応用してシェルで自動チェックする仕組みを作ってみます。


利用するコマンドは、下記のcrsctlコマンドでリソースの状況を表示するオプションをつけて実行します。


$ crsctl stat res -t
--------------------------------------------------------------------------------
NAME           TARGET  STATE        SERVER                   STATE_DETAILS
--------------------------------------------------------------------------------
Local Resources
--------------------------------------------------------------------------------
ora.DG1_CTRL.dg
               ONLINE  ONLINE       oradb1
               ONLINE  ONLINE       oradb2
ora.DG2_DATA.dg
               ONLINE  ONLINE       oradb1
               ONLINE  ONLINE       oradb2
ora.DG3_ARCH.dg
               ONLINE  ONLINE       oradb1
               ONLINE  ONLINE       oradb2
ora.LISTENER.lsnr
               ONLINE  ONLINE       oradb1
               ONLINE  ONLINE       oradb2
ora.asm
               ONLINE  ONLINE       oradb1                Started
               ONLINE  ONLINE       oradb2                Started
--- snip ---

--------------------------------------------------------------------------------
Cluster Resources
--------------------------------------------------------------------------------
ora.LISTENER_SCAN1.lsnr
      1        ONLINE  ONLINE       oradb1
ora.LISTENER_SCAN2.lsnr
      1        ONLINE  ONLINE       oradb2
ora.LISTENER_SCAN3.lsnr
      1        ONLINE  ONLINE       oradb2
ora.cvu
      1        ONLINE  ONLINE       oradb2
ora.oradb1.vip
      1        ONLINE  ONLINE       oradb1
ora.oradb2.vip
      1        ONLINE  ONLINE       oradb2
ora.oradb.db
      1        ONLINE  ONLINE       oradb1                Open
      2        ONLINE  ONLINE       oradb2                Open
--- snip ---


上記のように、このコマンドでリソースの状況が確認できるうえに、TARGET(しかるべき状態)とSTATE(現在の状態)が表示できるので、これを比較することでリソースの状況がチェックできそうです。


ただ、これは視覚的にすごく見やすいのですが、プログラムから見れば処理しにくい部分があるため、「-t」オプションを除いたコマンド実行結果を利用します。


$ crsctl stat res
NAME=ora.DG1_CTRL.dg
TYPE=ora.diskgroup.type
TARGET=ONLINE             , ONLINE
STATE=ONLINE on oradb1, ONLINE on oradb2

NAME=ora.DG2_DATA.dg
TYPE=ora.diskgroup.type
TARGET=ONLINE             , ONLINE
STATE=ONLINE on oradb1, ONLINE on oradb2

NAME=ora.DG3_ARCH.dg
TYPE=ora.diskgroup.type
TARGET=ONLINE             , ONLINE
STATE=ONLINE on oradb1, ONLINE on oradb2

NAME=ora.LISTENER.lsnr
TYPE=ora.listener.type
TARGET=ONLINE             , ONLINE
STATE=ONLINE on oradb1, ONLINE on oradb2

NAME=ora.LISTENER_SCAN1.lsnr
TYPE=ora.scan_listener.type
TARGET=ONLINE
STATE=ONLINE on oradb1
--- snip ---


この結果だと、TARGETとSTATEの部分がカンマ区切りで取得できるのでスクリプト的に処理しやすかったりします。



Oracleのリソース状況をチェックするスクリプト


ということで、以下のようなcrsctlコマンド実行結果を解析するシェルスクリプトを書いてみました。


#!/bin/bash

# チェック対象のリソース一覧。SCAN系やVIP、CVUなどのリソースはどちらのノードが持っているか不明なため対象外
RESOURCES=("ora.DG1_CTRL.dg" "ora.DG2_DATA.dg" "ora.DG3_ARCH.dg" "ora.LISTENER.lsnr" "ora.asm" "ora.net1.network" "ora.ons" "ora.oradb.db")

# RAC対象ノード
RACNODES=("oradb1" "oradb2")

# CRSコマンド
CRSCHECK="/opt/app/11.2.0/grid/bin/crsctl check cluster"

# 実行ファイル名
FILENAME="${0##*/}"

# CRSが生きているかチェック
crsstat=`$CRSCHECK | grep "online" | wc -l`
if [ $crsstat -ne 3 ]
then
    logger -p err -t "${FILENAME}" "error: Cannot communicate with Cluster Ready Services"
    exit
fi

# リソースをチェックするコマンド
CRSCMD="/opt/app/11.2.0/grid/bin/crsctl stat res "

# 各リソースをチェック
for res in "${RESOURCES[@]}"
do
# crsctlコマンドを実行しSTATE行を抽出し=で分割して結果を受取る
    result=`$CRSCMD $res | grep "STATE=" | cut -d "=" -f2`
    for node in "${RACNODES[@]}"
    do
# HOST名が存在しないかONLINEでなければそのリソースは停止している可能性がある
        status=`echo $result | grep "$node"`
        if [ -z "$status" ]
        then
            logger -p err -t "${FILENAME}" "error:" $res "on" $node "is missing."
        fi
    done
done


やっていることは、crsctlコマンドの実行結果から監視対象のリソース(RESOURCES配列の中身)のTARGETとSTATEの中身を比較しており、異常があったときにsyslog経由でエラーメッセージを吐き出すというものです。

あとは、Cronとかで数分おきにシェルを実行してチェックするように動作させておけばよいかと思います。


シェルのコメントにも書いていますが、SCAN系やVIPのリソースはどっちのノードが持っているか起動の状況によりばらけたり、1ノードを意図的に落としたときにフェイルオーバーして片ノードによってしまうということがあって監視が難しいので対象外にしています。

Oracle自身もリソースやプロセスに異常があったら自己修復するような機能を備えているので、この辺が完全にアウトになることがあるのか不明ではありますが。


あと、RAC用と書きましたが、対象リソース(RESOURCES変数)や対象ノード(RACNODES変数)を書き換えればSingle環境のOracleでもチェックは可能だと思います。

同様にcrsctlコマンドは利用できるので。


監視としては、syslogにメッセージが吐き出されるので、最終的にはログ監視の中で異常を拾う仕組みにはなっていますが、監視ツールのPandoraとかではスクリプトの実行結果を元に判別できたりもするので、ログに書き出す部分に戻り値を書いてあげてもよいかもしれません。





先日電車に乗っていたら、後ろの方で若い子達が「LINE送って既読になってんのに無視された」って騒いでいました。

ひどいとかぎゃーぎゃー騒いでたんですが、まぁ確かに自分もいい気はしないけど返事を求めてない場合もあるし、求めてたとしても相手の都合もあるだろうし、返事しないならしないで勝手にこっちで進めちまえばいいやーみたいな感覚だったりもするんですが、子供の頃からコミュニケーション手段としてネットが当たり前に使われている世代にとっては、「届いているはずなのに返事しない」って言うのはリアルに会っていて挨拶したのに無視されているような感覚を持っているのかなとも思ったりしました。



届いたという感覚が生み出すジレンマ


情報機器の発達とともに当たり前につながる手段を誰しもが手に入れている状況下では、相手に届けたメッセージが届いているとわかるとともに誰しもがどんな場所でも返答できる環境を作り出しています。

これは利便性を高めるとともにSNS疲れのような弊害も生み出しているわけですが、多くの人がそれを読める環境にいる(またはすぐに読め無くても数時間のうちに読めるだろう)場合、返事をよこさないことに不信感や不満を持つケースというのはあると思います。


「読んだ」という行為ができれば「書く」という行為もできるだろうという感覚を持つことは自然なことかもしれません。

ただ、実際には読むと書くとではコストが全然違ってくるわけで、読むのは何も考えずに少しのアクションで読めるのに対して、書くのは状況を把握したり考えたりした上で多くの文字を打ち込むという行為が必要になります。

会議中にメッセージを読むことはできても書くことは難しかったりもするわけです。


一方で、いくらネットでの情報伝達が容易になったとはいえ、私たちが住むリアルな世界でも様々なことが起きているわけで、ネットの文章だけを通してみるとそれはネットの中で起きているかのように錯覚してしまうんですけど、きちんと相手がいることなので当然リアルな世界で起きていることばかりなわけです。

データを通してやり取りするデジタルの世界に文章を放り投げるとあたかもそれは相手の頭の中に届くような感覚を持ちますが、リアルで話す言葉よりもずっと弱いものだったりもします。

現実世界での行為というものに時間をとられるだけでなく、その世界にいる人たちとの今のつながりを大事にしている人も多くいるわけで、それを押しのけて差し込んでくるデジタルの世界からのメッセージの優先度ばかりが高となるわけではないわけです。


まぁ、優先度は低くてもいいから時間のあるときに返事が欲しいというのは思うところですが、よっぽど返事が無いのであれば、文章がわかりづらいか、返事しづらい内容なのか、絶え間なくそっちのけで優先度を高いことを生み出している忙しい人か、はたまた嫌われているのか、何れにせよ本当に大事なことであれば電話するか直接会って話すかをした方がよいとは思います。

リアルに会う、話すという手続きを簡略化できるのがメールであったりTwitterやLINEのようなショートメッセージサービスではあるのですが、その分多くの情報にさらされているわけで、届く情報量というのはデータの中にある文章より断然小さくなってしまうのではないかと感じているところです。



情報スピードについていけない現実


先ほど書いたように、LINEとか親しいグループの中でやり取りする情報というのは数が多かったりしますしますので、そこで流れていく情報に自分が送ったメッセージがどんどん押し流されていくことがあったりします。

いろんな人とやり取りしていると返事を求めたメッセージが読み飛ばされたり、後で返事しようと思っていても次々に流れてくる新しい情報に脳内のメモリは埋め尽くされてしまいます。


そんな状況の中で、「じゃあ何時返事くれるの?」って言われても、さっき書いたように書くというコストが高い分なかなか「今でしょ!」っていえない現実があったりして、並列処理としてうまく情報をコントロールできない人は多いと思います。

以前に読んだ「ワーク・シフト ― 孤独と貧困から自由になる働き方の未来図〈2025〉 」という本の中で、これからは今よりももっと多くの情報が飛び交い時間に追われ続ける未来を予想してたりもするのですが、現在の状況でもスピード感についていけないと感じている人は多いのではないでしょうか。


ブログでは長文が流れてきて読む気がしないし、TwitterやFacebookではリアルな今が伝えられて今の自分とのギャップに思い悩み、LINEでは感情を変わりに表現してくれるスタンプの応酬で会話が無いという状況が刻々と進んでは変化していったりするわけです。

その全てを真っ向から受けて制御していくだけでも大変なわけで、これから生まれてくる新たなサービスや流行についていくとなるといつかは自身の頭と体が破綻するでしょう。


自分自身も、Twitterなんかで次から次へと流れてくる情報に面白みを感じていた時期がありましたが、追えば追うほどキリが無いという感覚をあるときから感じ出して、自分に降りかかる情報量をコントロールするようになって来ました。

時間があれば、ひっきりなしに情報を浴びるのも悪くないと思うのですが、常にそんな情報を浴びているのは仕事をしていたり現実の世界の中で両立させるのは無理だと感じているからです。

ネットの世界に生きている人はそれに押し流されること無くその流量の中でコントロールできていたりするのですごいな、と感じるわけですが自分には無理なので「基本的にTwitterは読まずに書くだけにする」とか「常に情報が更新されるSNSよりは好きなときに好きなだけ読めるブログの方がいいよなぁ」とか思ってたりもします。


きっと「既読無視とかひどい」っていってた子もそんな情報を絶え間なくあびる環境にいたら無視することも出てくるでしょうし、無視した相手もそんな世界に疲れているのかもしれませんし、まぁそんなことをつながっていることを理由にいちいち考えなくても神経すり減らすだけなので、もっとゆるく考えて自分にあったコミュニケーション手段と情報量というのをキープしてネットにつながっていたほうが楽しいんじゃないのって思う今日この頃です。




Linux上のユーザーのリソースの使用状況であったり、運用のポリシーを下に様々な制限を加えたいという場合があります。

例えば、利用するディスクスペースや生成するプロセス数の制限であったり、ログイン数を限定するという具合です。


ということで、その制限方法をまとめていきたいと思いますが、環境としてはRedHat5.9をベースに書いています。

 

 

/etc/security/limits.confに制限内容を書く

 

 

 

ユーザーのリソース制限の設定はこのファイルに内容を書いていきます。
例えば、あるユーザーが生成するプロセス数を限定したいという場合

 

 

foo    soft    nproc   20
foo    hard    nproc   100

 

 

のように書いておきます。

 

 

書式としては

 

 

ユーザー名(または@グループ名または*で全ユーザー) soft | hard 識別子 設定値

 

 

となります。

 

nprocが最大プロセス数を定義するための識別子となるので、今回の場合はfooユーザーに対して20のプロセス数までしか起動できない設定となります。

 

softとhardの設定の違いは、softが一般ユーザが変更できる限界値で、hardはrootが変更できる限界値となります。

 

この状態で、プロセスを大量に生成してみたいと思います。

簡易的にプロセスを大量に作るShellプログラムとして下記のようなものを用意します。

(とはいってもsleepプロセスをバックグラウンドで20個作るだけですけど)

 

#!/bin/bash
for i in `seq 1 20`
    do sleep 10 & done

 

 

実行直後にpsコマンドで見てみると

 

 

$ ps aux | grep sleep
--- snip ---
foo      3162  0.0  0.0  58924   524 pts/3    S    11:52   0:00 sleep 10
foo      3163  0.0  0.0  58924   524 pts/3    S    11:52   0:00 sleep 10
foo      3164  0.0  0.0  58924   524 pts/3    S    11:52   0:00 sleep 10
foo      3165  0.0  0.0  58924   524 pts/3    S    11:52   0:00 sleep 10
foo      3166  0.0  0.0  58920   524 pts/3    S    11:52   0:00 sleep 10
foo      3168  0.0  0.0  65416   828 pts/3    S+   11:52   0:00 grep sleep

 

 

と、プロセスが作られています。

 

この場合は、限界値が20なのでこのShellスクリプト実行直後にエラーがでます。

確認する場合は、別のユーザーまたはrootで確認する必要があります。

 

$ ./proc.sh
./proc.sh: fork: リソースが一時的に利用できません

 

 

この状態で何かコマンドを打ってみたり、fooユーザーでログインすると同様に

 

 

-bash: fork: リソースが一時的に利用できません

 

 

というようなエラーが出てリソース利用の制限に引っかかっていることがわかります。
syslogのほうもsecureログに近い内容のものが出力されます。

 

 

Jul 31 11:58:48 localhost sshd[9341]: Accepted password for fuga from 192.168.100.1 port 57033 ssh2
Jul 31 11:58:48 localhost sshd[9341]: pam_unix(sshd:session): session opened for user foo by (uid=0)
Jul 31 11:58:48 localhost sshd[9343]: Disconnecting: fork failed: Resource temporarily unavailable
Jul 31 11:58:48 localhost sshd[9341]: pam_unix(sshd:session): session closed for user foo

 

 

最後から2つ目のメッセージに書いてあるように、リソースが一時的に利用できないというメッセージが残されています。

 

ちなみに、この設定は設定後にログインしたユーザーに対して有効になります。

現在の状況を確認したければ、

 

$ ulimit -u
20

 

 

で、確認できます。
動的に変更したい場合は、

 

 

$ ulimit -u 30
-bash: ulimit: max user processes: cannot modify limit: 許可されていない操作です

 

 

にて変更できます。

 

上記の場合は、一般ユーザーがnprocを20までしか変更できないのに対して、30に設定しようとしたのでエラーがでています。

 

もう1つ、特定ユーザーのログイン数を制限してみたいと思います。

 

 

foo    -       maxlogins       5

 

 

この状態でターミナルを5つ以上開いてログインしようとすると、拒否されます。

 

secureログの方にも

 

Jul 31 09:38:34 localhost sshd[32519]: Accepted password for foo from 192.168.1.100 port 63460 ssh2
Jul 31 09:38:34 localhost sshd[32519]: pam_limits(sshd:session): Too many logins (max 3) for foo
Jul 31 09:38:34 localhost sshd[32519]: pam_unix(sshd:session): session opened for user foo by (uid=0)
Jul 31 09:38:34 localhost sshd[32519]: error: PAM: pam_open_session(): Permission denied
Jul 31 09:38:34 localhost sshd[32521]: Received disconnect from 192.168.1.100: 2: disconnected by server request

 

 

接続をサーバー側で拒否したことがわかります。

 

その他にlimit.confやulimitコマンドで制限できるものには下記のようなものがあります。

 

項目 リソース名
core 吐き出すcoreファイルのサイズのリミット
data 最大データサイズ
fsize 最大ファイルサイズ
nofile オープンできる最大ファイル数
rss 実行プロセスのメモリサイズ
stack 最大スタック数
cpu CPU割り当て時間
maxlogins 最大ログイン数
maxlogins 最大ログイン数

 

 

その他の項目や設定方法はlimits.conf内にコメントがありますので、そちらも参照してください。

 


 

limits.confの制約と制限

 

limits.confに書くことでユーザーのリソースが制限されるわけですが、全てにおいて適用されるわけではありません。

 

元々、このlimits.confはpam_limits.soという共有ライブラリで提供されており、pam.dディレクトリにあるsystem-authファイルなんかで読み込まれています。

 

session     required      pam_limits.so

 

 

下記のサイトなんかを参考にすると、sessionというタイプの指定はユーザー認証前後に実行するということなので、この時にリソースの使用状況が制限内かチェックしているようです。

 

 

PAMによる認証の仕組みを調べてみたAdd Star @ GeekFactory

 

 

その他にも、

 

 

# grep -l "pam_limits.so" ./*
./atd
./runuser
./sudo
./sudo-i
./system-auth
./system-auth-ac

 

 

なんかのファイルにてpam_limits.soが読み込まれているので、それぞれのコマンド実行時にリソースの制限がかかるわけですが、これ以外の場合やそもそもpamを利用していないアクションをした場合は制限されません。

 

自動起動スクリプトなんかから実行しているユーザーにも制限を加えたいという場合は、その自動起動スクリプトにulimitコマンドを書いて制限を加えるか、下記のようにOS起動時のスクリプトに書いてしまうという方法があるようです。

 

ulimitが効かない不安を無くす設定 @ 外道父の匠

 

 

まぁ、自動起動スクリプトの中でsuしてたりrunuserしてたりする場合は、pamを通るので制限がかかるかと思いますが。

 

現在の設定内容の確認および設定時のオプションは、下記のコマンドを実行すればわかります。

 

$ ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 38911
max locked memory       (kbytes, -l) 32
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 10240
cpu time               (seconds, -t) unlimited
max user processes              (-u) 38911
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

 

 

先に書いたnproc(-uオプション)の変更のように、上記のそれぞれのオプションを指定して制限を動的に変更しておけば起動時に制限を反映することができます。

 

 

プロセスを大量発行するユーザー(例えばApacheユーザーとか)、利用者にサーバーを開放するけど大きなファイルや大量のファイルを扱われたくないというような場合に制限をかけておくと便利でしょう。