2010/04/06

Solaris 8から10にあげたらスクリプトの時間の計算がおかしくなった。原因はTZでの時差補正を利用したテクニックが通用しなくなったため。 #solaris #tips

「Solarisのバージョンを8から10にあげたら、急にスクリプトの動作がおかしくなったんだ。見てくんない?」

手持ちの仕事も詰まってるのに、なんで他人さまのシステムの面倒まで見なくちゃいかんのよ、だいたいテストしとけよな移行前に……なんて思っても、 顔には出せないのが下っ端の悲しさ。まして少し前に美味しいベトナム料理屋さんを紹介してもらった手前、断るに忍びなく調べちゃったというお話。

割と似たようなトコロで苦しんでる人が多そうなので、1ポストに仕上げてみた。

そのスクリプトでおかしくなっていたのは「今日からxx日前」を「yymmdd」(100406 とか)の形式で出力する機能。Solaris 10になった途端、xx日前ってのを無視するようになったんだと。

でスクリプトの中で、その機能は:

set O_DATE = "-E "`env TZ=JST$T_LIMIT date '+%y%m%d'` 

このように書かれていた。O_DATEって変数に「yymmdd」が入る。$T_LIMITは「xx日前」ってのを時間帯で表現したもの。(例えば 30日前なら30日×24時間で 720 って数字が入る)

ボクは知らなかったのだけど、TZ環境変数による時差の補正(JST+1とかやると、日本時間プラス1時間を表示してくれる)を利用した、時間を計算するための常套テクニックらしい。そう思ってスクリプトの元の作者を思い浮かべれば……あぁ、確かに古参のSolarisユーザだ。

実はSolarisのdateコマンドはGNU dateのようにxx時間前とかxx日前なんかを表示してくれる便利な機能はない。なので、このような小技を使ってやるのだけど。

24時間以上の時差なんて、地球上では論理的にあり得ないよね?

そんなわけで、ある時点で実装が厳密になったんである。つまり、24時間以上の時差が指示されたら結果は保証しないよ、というカタチで。従って、 Solaris 10では、TZ+`expr xx*24`ってテクニックは利用できない。

選択肢は二つ。GNU dateを含むCoreutils(その昔はShellutilsもしくはsh-utilsと呼ばれてたそうな)をインストールするか、自分でコードを書くか。

サーバ管理者のリテラシやら環境のクリーンさやら、あれこれ加味して今回は後者を取ることにした。仕様は:

  • 引数として遡る日数を数字で受け取る
  • 引数として数字以外のものが与えられたときには無視する
  • 返り値として yymmdd の形式で実行した日から「引数」日分さかのぼった日付を返す

これだけ。あとは、これを元のスクリプトから呼んでやればよろし。

なおスクリプトを作るのにTcl/Tk(とゆーかTclの部分だけ)を使っている。ここでは、tclshのインストールパスが /usr/sfw/bin になってる想定で。(ホントは env tclsh ってやるのがお行儀が良いんだけど、対象のシステムではパスが通ってなかったので直書きした)

#!/usr/sfw/bin/tclsh8.3

if { ![string length $argv] } {
   set aBack 0
} else {
   set aBackD [lindex [split $argv { }] 0 ]
   if { [regexp {^[0-9]*$} $aBackD] } {
      set aBack [expr $aBackD * 24 * 60 * 60]
   } else {
      set aBack 0
   } 
}

set aDate [clock format \
 [expr [clock second] - $aBack] \
 -format %y%m%d]

puts $aDate
return -code 0 $aDate

以上。

この手のスクリプトはcshやbashなんかの範囲だけで書こうとすると大層メンドくさいけれど、tclshのようなLL言語を使えば15分くらいで組めてしまう。今どきのサーバOSなら、Perl, Ruby, Tclあたりはデフォルトで入ってそうなものであるし。

サーバ管理者たるもの、やっぱりLL言語の一つ, 二つは修行しておくべきなんだよね。ボクも、もっと修行しなくちゃ。

blog comments powered by Disqus