Hina-Mode

とある呑んだくれエンジニアの気が向いた時に書く戯言

MySQLの自動負荷検知&再起動のスクリプト組んでみた

これも必要にかられて。。。。
週末プログラマだと平日会社に要るときに異常があってDB死んだりしたら即終了(というか実際に起きたんですが)なので、
取り急ぎやばそうだった
LA、メモリ利用量、スレッド数
の3点をチェックし、超えていたら再起動をかけてやむなきを得(れたらいいな)るようにしてみました。
参考までに下に内容を載せておきます。

#!/bin/bash

#setting
mailto="hoge@fuga.com"
sbj="From db load monitoring tool."

# limitation num
thread_limit=150
la_limit=10
mem_limit=16

# common function
send_mail() {
  from=$1
  to=$2
  inputEncoding="utf-8"
  outputEncoding="iso-2022-jp"
  subjectHead="=?${outputEncoding}?B?"
  subjectBody="`echo "$3" | iconv -f ${inputEncoding} -t ${outputEncoding} | base64 | tr -d '\n'`"
  subjectTail="?="
  subject=${subjectHead}${subjectBody}${subjectTail}
  contents="`echo -e $4 | iconv -f ${inputEncoding} -t ${outputEncoding}`"
  echo "$contents" | mail -s "$subject" "$to" -- -f "$from"
  return $?
}


thread=`echo "show global status like 'Threads_connected%';" | ~/bin/mysql_connect.sh | grep connected | cut -f2`
ret=`echo "${thread} > ${thread_limit}" | bc`
if [ ${ret} -eq 1 ]; then
  send_mail "$mailto" "$mailto" "$sbj" "too many connection. mysql will be restart automatically."
  /etc/init.d/mysqld restart
  exit
fi

la=`uptime | sed -e "s/.\+load average: //g" | cut -f1 -d" " | cut -f1 -d","`
ret=`echo "${la} > ${la_limit}" | bc`
if [ ${ret} -eq 1 ]; then
  send_mail "$mailto" "$mailto" "$sbj" "load average is over. mysql will be restart automatically."
  /etc/init.d/mysqld restart
  exit
fi

mem=`free | grep Mem: | sed -e "s/ \+/\t/g" | cut -f3 | xargs -i ksh -c 'echo "scale=2;{}/1024/1024" | bc'`
ret=`echo "${mem} > ${mem_limit}" | bc`
if [ ${ret} -eq 1 ]; then
  send_mail "$mailto" "$mailto" "$sbj" "memory using rate is 50% over. mysql will be restart automatically."
  /etc/init.d/mysqld restart
  exit
fi

DRY的な観点でいうともっと簡素に書けやって感じなんですが
取り急ぎなスクリプトなのでもうこれでいいや。。。

そんな感じです。

正規表現の先読み、後読みを活用して"○○pt"の文字列を抽出する

泥臭かったのですが、これくらいしか思いつきませんでした。
自分で運営しているサイトでポイント表記があったのすが○○ptの部分を、他の文字に変更したかったのでどれ位変更する必要があったのか調査してみた。

$ find -type f -name '*.ctp' | xargs grep 'pt' | wc -l
1300

oh...無理。無理だよパパン。
しかも中身見たら「empty」とか「option」とか「javascript」とか書いてあるし。アカン。こんなん1300行もチェックしてられません。

というわけでうまい具合に
「○○pt」はチェックしたいけど上記のような特定のパターンは除外できないかと思って調べてみたら
Linux上で先読み、後読みを利用して除外していく方法が見つかりました。

$ find -type f -name '*.ctp' | xargs grep -P '(?<![sS]cri|i|javascri|em|acce|div-g)pt' | grep -P 'pt(?!ion)' | wc -l
35

おお、35行まで絞れた。これならイケる。
中身もすごくそれっぽいのとれた。すげー助かる。


今後はこんな事しないでいいように定数に変えておこう。。。死にたい。

git logをJIRAに貼り付けられるように整形してみた

今流行のアトラシアン社のチケット管理ツールJIRA。
私も使うことが多いのですが、Gitを使っている時に、
「これリリースしますね」っていうログをJIRAにコメントや本文で貼っつけるのに整形が面倒だったので、予め整形しておいて.bashrcなどのファイルにaliasを入れておくことにしました。

alias gitlog='git log --date=short --no-merges --pretty=format:"|%h|%an|%ad|%s|"'

誰が何時、どのコミットを入れたのかがだいたい分かるので重宝してます。
これを入れておけば

$ gitlog master..develop > log_diff

とかしてあげればmasterブランチからdevelopブランチの差分が一気に取得できます。

【未熟】Linuxの実行中の負荷監視と終了時の負荷平均の自動計算を行なうshellScript

これもずいぶん前に必要に駆られたのでやっつけで作ってみたんですが、
監視を抜けるためにqをpressしたら終了、にしたら
ttyが変になってしまって終了後のcli入力が見れない(一応入力自体はできてる)事に。
というなんともポンコツなスクリプトなのですが、
どなたか何がイケないのか教えていただければすごく助かります。

一応監視内容はmpstatの数値を追っているだけです。
実行後、qキーを押すとスクリプト終了となり、
抜けた後にはawkで自動計算を走らせ、平均値を算出させます。

if [ -t 0 ]; then stty -echo -icanon time 0 min 0; fi
keypress=''
result=''
echo "time	load	%user	%nice	%sys	%iowait"
while :
do
	tl=`uptime | sed -e "s/ \([0-9]\{2\}:[0-9]\{2\}:[0-9]\{2\}\).\+load average:/\1/g" | sed -e "s/ \+/ /g" | cut -d" " -f1,2 | sed -e "s/,//g" | xargs echo -n`
	tl=$tl`echo -n " "`
	tl=$tl`mpstat 1 1 | grep Average | sed -e "s/ \+/ /g" | cut -d" " -f3,4,5,6`
	echo $tl | sed -e "s/ /\t/g" 
	result="$result\n$tl"
	read keypress
	if [ "$keypress" = "q" ]; then
		break
	fi
done

# calc average
echo "check finished."
echo -n "load average: "
echo -e $result | grep -v "time" | awk '{ sum += $2; num++}; END { print sum/num }'
echo -n "user cpu usage: "
echo -e $result | grep -v "time" | awk '{ sum += $3; num++}; END { print sum/num"%" }'
echo -n "iowait average: "
echo -e $result | grep -v "time" | awk '{ sum += $6; num++}; END { print sum/num"%" }'

IPを直接叩かれてアクセスされたくないからmod_writeで防衛した

諸事情ありましてIPで直接サイトを閲覧されると色々面倒だったので、
.htaccessでアクセスを防止することにしました。

apache側に書かなかった理由としては、サーバにこの仕様を書いてしまうと、
rewriteルールが変更になる際に複数サーバで書き直さないといけないので至極面倒だったからです。

その点、.htaccessであれば修正→デプロイで一括なのでとても簡単!capistranoちゃん大好き!

<IfModule mod_rewrite.c>
  RewriteEngine on
  RewriteCond %{HTTP_HOST} [0-9]+\.[0-9]+\.[0-9]+\.[0-9]+
  RewriteRule ^(.*) http://www.mydomain.com/$1 [R=301,L]
</IfModule>

ちなみにmod_rewrite私書くの苦手で、確認もあんまり出来なくて困っていたんですが、
http://htaccess.madewithlove.be/
こんなサイトが在るみたいなので今回はとても助けられました。