サーバーと一緒にUPS非対応なTeraStationをシャットダウンする

ウチのやや古いTeraStation(HS-DHTGL/R5)はUPSに対応してませんが、どこかで先人がハックしていないかとググったところ、「Tera Stationをremoteからshutdownする方法」というブログ記事を発見しました。なるほど、wgetコマンドを使ってWeb管理インターフェイスのシャットダウンを実行する訳ですね。早速試してみたところ、ウチのDHTGLちゃんWeb管理インターフェイスの仕様が変わったらしく上記記事のスクリプトは使用できませんでした。そこで基本アプローチを拝借しつつ、DHTGL用に改変を試みました(以下、ファームウェアは1.15での情報です)。

■解析編

まずそもそも元スクリプトはwgetのBASIC認証用のパラメーターで認証を突破してますが、DHTGLはBACIS認証ですらない。結構苦労しましたが、まとめると、

  • /cgi-bin/top.cgiにPOSTでパラメーターを送ることで動作している(元スクリプトではts.cgi)
  • gPage、gMode、gType、gKeyといったhidden値で実際の表示ページや動作を規定している
  • ログインページから送られるhidden値はgPage=top、gMode=authでID、PWはそれぞれtxtAuthLoginUser、txtAuthLoginPasswordというフィールド名で送られる
  • 一旦認証が通ると、gSSSとgRRRというhidden値が生成されセッション管理に用いられる
  • シャットダウンの時は認証情報の代わりにgSSS、gRRRをつけ、gPage=maintenance、gMode=shutdown、gType=shutdownを送る

といった感じ。gSSSはセッション毎、gRRRはページ遷移毎にユニークに生成されてるっぽいです。gSSSは「07ae46da8acb13a7ba9c99acf3ef66f9」のような16進数値、gRRRは「463273411635750418」のような10進数値です。

つまり認証(gSSS、gRRR取得)とシャットダウン実行でwgetを2回実行する必要があるみたいでした。

■実装編

シェルスクリプトやsedに使い慣れてないのであまり綺麗な実装ではないですが晒してみます。うまいことすればTMPファイルを減らしたり無くしたりできそうなもんですが、よくわからなくて2つほど生成してます。もっとエレガントな方法があれば是非教えて下さい。

#!/bin/sh
#
# rc script to shutdown Tera Station by knakao
#

#REQUIRE LOGIN

WGET=/usr/bin/wget
SERVER=192.168.0.***
USER=admin
ADMIN_PASSWD=**********
URL="http://$SERVER/cgi-bin/top.cgi"
TMPFILE="/tmp/ts_shutdown.tmp"
TMPFILE2="/tmp/ts_shutdown2.tmp"

ts_down()
{
    # Loging in as administrator
    OPT="–post-data=txtAuthLoginUser=$USER&txtAuthLoginPassword=$ADMIN_PASSWD&gPage=top&gMode=auth -O $TMPFILE -q -T 5"
    $WGET $OPT $URL

    cat $TMPFILE | grep gSSS > $TMPFILE2

    gSSS=sed 's/.*name="gSSS"  value="\([^"]*\).*/\1/g' $TMPFILE2
    #echo ‘Current gSSS is ‘$gSSS

    gRRR=sed 's/.*name="gRRR"  value="\([^"]*\).*/\1/g' $TMPFILE2
    #echo ‘Current gRRR is ‘$gRRR

    OPT="–post-data=gPage=maintenance&gMode=shutdown&gType=shutdown&gSSS=$gSSS&gRRR=$gRRR -o /dev/null -q -T 5"
    $WGET $OPT $URL

    rm -f $TMPFILE
    rm -f $TMPFILE2
}

case $1 in
start)
;;

stop)
ts_down;
;;
esac

このファイルを実行可能にして/etc/init.d/terastation等として置きます(RedHat系)。赤字部分は適宜書き換えて下さい。

手動で実行するには

/etc/inin.d/terastation stop

などとします(なお当たり前ですがstartオプションは無視されます)。せっかくrcスクリプト形式なので適当な/etc/rc*.dディレクトリにシンボリックリンクを張るとか、/etc/rc.d/init.d/haltに書いておけば自動実行されるんですが、通常のメンテナンス時にも一緒にTeraStationまで落ちるのが難点ですね。UPSによるシャットダウンの時だけに実行できる仕組みがある場合はそちらを利用するのが良いでしょう。

あとTeraStation自体と途中のハブもUPSでまかなっていないと意味がないのでご注意を。

OS再起動後にPostfixがエラーでメール送受信できなくなる時の覚え書き

我が家のCentOS + Postfix + SpamAssassinで運用しているSMTPサーバーが、OS再起動後にエラーを出してクライアントからの送信や外部からのメール受け取りができなくなる現象が発生していました。原因究明は簡単で/var/log/maillogをみると、迷惑メールフィルタSpamAssassinが使用する/var/run/spamass.sockにパーミッションがないせいだとわかります。このファイルのオーナーをpostfixにしてやれば解決します。実はもうずっと前からこの現象が起きてたのですが、OSを再起動する機会自体が少ないので、都度手動で対応していました。

ですが最近の計画停電で発生頻度があがってきたので、まじめに対応をしようと。

で、このファイルを作成するのが/etc/init.d/spamass-milterです。このファイルの中に下記のようなブロックがあります。

start() {
        echo -n $"Starting $desc ($prog): "
        daemon $prog -p $SOCKET -f $EXTRA_FLAGS
        RETVAL=$?
        [ ! -s $SOCKET ] || sleep 30
        chown postfix $SOCKET
        echo
        [ $RETVAL -eq 0 ] && touch /var/lock/subsys/$prog
        return $RETVAL
}

ちゃんと6行目で同じことしてるんですね。ただタイミングが早くて実際にこのファイルが作られる前に実行されてしまい、結果としてオーナー変更ができてなかったっぽいです。直前の行にあるsleepコマンドによる待ち時間を長めにとってみたところ解決できたっぽいです。ちなみに確か最初は5だったんですが、10にしてもダメでした。どれくらいの時間が適切かはお使いの環境によると思います。

OS再起動後、/var/run/spamass.sockのオーナーが最初からpostfixになっていれば成功です。

Xen環境でUPSが使用できない時の覚え書き

停電を繰り返すうちにどうもUPSによるサーバーのシャットダウンがちゃんとできてないことがわかってきました。そういえばUPSは前のサーバー機から継続だけど、今のXen環境にしてからあんまり実地テストとかしてなかったなと。

我が家のUPSは三菱のFREQSHIP Fで、同社がフリーで配布しているFREQSHIP-mini for FreeUNIXをインストールして運用しています。起動スクリプト/etc/init.d/freqshipを実行するとなにやらCOMポートがどうのとエラーを返します。設定ファイルは/etc/freqship/UPSFILEで、一行目に、

Port=/dev/ttyS0

という記述があります。UPSとの通信に使用しているCOMEポートとして/dev/ttyS0を指定してあるのですが、これがなんらかの理由で使用できないようです。次に起動時のコンソールメッセージを

dmesg | grep tty

としてttyという文字を含むものを検索。すると、

Xen virtual console successfully installed as ttyS

とXen絡みのメッセージを発見。どうもXenがシリアルポートを占有してしまってるのが問題のようです。そこでググった結果の解決策は、/boot/grub/grub.confを編集し、

title CentOS (2.6.18-194.32.1.el5xen)
        root (hd0,0)
        kernel /xen.gz-2.6.18-194.32.1.el5 dom0_mem=768M
        module /vmlinuz-2.6.18-194.32.1.el5xen ro root=/dev/lvm1/Domain0 xencons=off
        module /initrd-2.6.18-194.32.1.el5xen.img

のように赤字部分を追加し、Xenにシリアルコンソールを使用しないよう指示しました。grub.confには同じようなブロックが複数セット書かれていると思います。大抵は一番上がデフォルトで使用される記述だと思いますが、まぁとりあえず全てに書いておきました。

これで再起動したところ、/etc/init.d/freqshipでエラーが出なくなりました。

停電の多い地区の皆さん、いちどちゃんとシャットダウンできてるかお試しあれ。

■オマケ:XenのDomain-U仮想マシンを自動的に起動する

Domain-0が再起動した後、自動でDomain-U(仮想OS)も起動させたい場合、/etc/xen/autoに設定ファイルを置いておけばいいようです。大抵は/etc/xen/においてあるでしょうから、シンボリックリンクを張っておくのが簡単でしょう。たとえばHogeという定義ファイルなら、

ln-s /etc/xen/Hoge /etc/xen/auto/Hoge

とか。ちなみにXenはシャットダウン時にDomain-Uを自動でサスペンド状態にしてくれて、次回Domain-0起動に自動的に復帰させてくれるようです。上記の設定はちゃんとそれをチェックしてレジュームに失敗した場合のみ実行してくれるみたいなので、Domain-Uが二重に起動してしまうようなことはないようです。賢い。

当ブログ、サーバーの運用状況について

当ブログを設置しているサーバーは物理的には横浜市内にあるので、東京電力の計画停電に応じて適宜停止をしています。ちなみにグループ5です。サーバーごと中部電力エリアの実家に移設することも検討していますが、とりあえず期末の仕事が差し迫ってきてまだ手を付けられていません。

とりあえずブログネタ的には録画PC用にUPSを発注したんですが発送される気配なし。脱乾電池を進めてきた結果、エネループや外部バッテリーの類はそれなりにあるので電池には困ってない感じですかね。懐中電灯もあるし。こないだ省エネ能力の高い湯沸かしポットを買ったところだったのも幸いしてます。あと、停電時でもWiMAXは意外と粘ってくれていて、年末にWM3500R買ったのも当たりだったなぁと。停電中もこれ+各種ノート/タブレット/スマートフォンでネットには不自由しない感じです。

まぁそんな感じですがとりあえずσ(^^)は元気でやっています。お互い頑張りましょう。

sqlite2で全置換する時の覚え書き

とある案件でsqlite2のデータベースのあるテーブルに含まれる文字列の全置換をしたくなったんですが、ググってヒットするselect文で使えるreplaceコマンドはエラーになる。どうもsqlite3からの実装っぽい?

でsubstrを組み合わせた方法とやらも見つけたんですが、いまいち意味がわからず応用できませんでした。

結局、どうしたかというと、ダンプ->sedで置換->新DBにインポートというやり方で、下記の1行で済みました。

sqlite hoge.db .dump | sed –e ‘s/MH\./MF\./’ | sqlite hoge2.db

ちと見づらいですが、色つきの部分を適宜置き換えてご使用下さい。

元データベースファイル:hoge.db

新データベースファイル:hoge2.db

置換元ワード:MH.

置換後ワード:MF.

今回のワード中に含まれるピリオドはエスケープする必要がある為、前に’\’をつけています。

で、sqlite hoge2.dbして問題なく変換されていることを確認したら、元ファイルと差し替えます。