読者です 読者をやめる 読者になる 読者になる

treedown’s Report

システム管理者に巻き起こる様々な事象を読者の貴方へ報告するブログです。会社でも家庭でも"システム"に携わるすべての方の共感を目指しています。

Debian8 jessieでもclockspeedが使いたい。

サーバ Linux

Pentium系CPUでLinuxを使っているならclockspeedはぜひ入れておきたいプログラムです。
今回はこのマイナーかつ古くからアップデート不要で生き続けるプログラムを記事更新時点(2015年7月現在)最新のDebian jessie(Debian8)で使うための方法を掲載します。
Debianであれば概ね動作に乖離はないと思いますが、この通り実行したからといって結果が同一になることを保証するものではありません。また実施による損害・損失に対して一切の責任を負いかねます。

前提条件

  1. OSはDebian 8 jessie
  2. sudoがインストール・設定済み
  3. make/gccがインストール済み(apt-get installでOK)
  4. sshでサーバ操作が可能
  5. wgetで利用するURLは2015年6月現在で有効
  6. clockspeedはdaemontools上(svc)で動作させる
  7. 作業ユーザ:user01、サーバ名:svr011


その1:daemontoolsをインストールする
まずはclockspeedを動作させるための基盤となるプログラムdaemontoolsをインストールします。
作業用ディレクトリ作成とパッケージダウンロードし解凍
----------------------------------------------
$ mkdir -p /home/user01/src
$ chmod 1755 /home/user01/src/
$ cd src/
$ wget http://cr.yp.to/daemontools/daemontools-0.76.tar.gz
$ ls -la
drwxr-xr-t 2 user01 user01  4096  5月  7 17:43 .
drwxr-xr-x 3 user01 user01  4096  5月  7 17:40 ..
-rw-r--r-- 1 user01 user01 36975  7月 29  2013 daemontools-0.76.tar.gz
$ sudo -s
[sudo] password for user01:
$ tar xvzf daemontools-0.76.tar.gz
~~解凍が始まります。
----------------------------------------------
daemontoolsはいろいろなところからDL可能ですが、作者の推奨通り公式のソースからDLしましょう。
解凍後作成されたディレクトリに移動してパッチのダウンロードと適用を実施します。
----------------------------------------------
# cd ./admin/daemontools-0.76/
# wget http://www.qmail.org/moni.csi.hu/pub/glibc-2.3.1/daemontools-0.76.errno.patch
--2015-05-07 17:52:53--
~省略~
2015-05-07 17:52:53 (20.5 MB/s) - `daemontools-0.76.errno.patch' へ保存完了 [355/355]

# patch -p1 < daemontools-0.76.errno.patch
patching file src/error.h
# package/install
Linking ./src/* into ./compile...
~以下略
----------------------------------------------
wgetコマンドでdaemontools-0.76.errno.patchをダウンロードします。
daemontools-0.76.errno.patchはmakeインストールを実行するとコンパイル環境の相違を埋めてくれます。(error.hファイルの記述を変更してくれます。Cの#include <stdio.h>みたいなあれです。)

パッチ適用後に「package/install」コマンドを実行するとコンパイルが開始し、自動的にインストールまでを完了してくれます。
終了メッセージが、
----------------------------------------------
~ここまで省略~
Copying commands into ./command...
Creating symlink daemontools -> daemontools-0.76...
Making command links in /command...
Making compatibility links in /usr/local/bin...
Creating /service...
Adding svscanboot to /etc/rc.local...
Reboot now to start svscan.

root@svr011:/home/user01/src/admin/daemontools-0.76#
----------------------------------------------
と、「Reboot now to start svscan.」でコマンドプロンプトが入力待ちに戻ってくれば正常終了しています。

その2-1:Debian8用のdaemontools起動設定(rc.localを使う場合)
コンパイルの最終行で「Adding svscanboot to /etc/rc.local...」と記載があります。このメッセージ通りdaemontoolsは/etc/rc.localに自分自身の自動起動を記述してくれます。Debian Wheezyまではインストールが正常に完了すれば自動起動してきたのですが、Debian jessieからは/etc/rc.localは使えないように無効化されています。そのため手動でちょっとファイルをいじってあげないといけないのです。
もしDebian8で導入されたsystemdによる自動起動を設定するほうがお好みの場合にはは後述する「その2-2:Debian8用のdaemontools起動設定(systemdを使う場合)」を参照してください。
現状の対処方法としてrc.localでもsystemdでもdaemontoolsは有効化出来るようです。どちらが推奨かはさておき、動作するので現状ではどちらでもよいことになります。
ただし、手動でsvscanを実行すると、daemontoolsが起動してプロセスとして確認できる(インストールに失敗していない)ことが条件です。

daemontoolsでpackage/install直後のrc.localは以下のようになっています。
----------------------------------------------
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other value on error.
#
# In order to enable or disable this script just change the execution bits.
#
# By default this script does nothing.

exit 0

csh -cf '/command/svscanboot &'
----------------------------------------------
最終行の「csh -cf '/command/svscanboot &'」がインストーラが記述してくれた自動実行用のコマンドラインです。
Debian8ではdaemontoolsデフォルト「csh -cf '/command/svscanboot &'」行のシェル「csh」がcommand not foundとなってしまう。ので、cshをsh(もしくはbash)に変更し、記述を「exit 0」と記載のある行の前に移動することでrc.localでの起動ができるようになる。

説明を訳してみた:
「このスクリプトは、各マルチユーザランレベルの最後に実行されます。
スクリプトが成功またはエラーの時に他のすべての値で「exit 0」が実行されていることを確かめてください。
ただしこのスクリプトを可能にするか、使用不可にするために、実行ビットを変更してください。
デフォルトでは、このスクリプトは何もしません。」
exit 0と記載されている箇所以降の行はすべて無視されてしまいますので、その後ろに記載のあるdaemontoolsは実行されず無視される状況です。
そこでrc.localを編集して使えるようにします。
-------rc.localを使う場合の操作-------
# cp /etc/rc.local /home/user01/bak/etc/rc.local.org
# chmod 755 /etc/rc.local
# vi /etc/rc.local
----------------------------------------------
編集後のrc.localは以下のようになります。
----------------------------------------------
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
#
#exit 0

#csh -cf '/command/svscanboot &'
sh -cf '/command/svscanboot &'

exit 0
----------------------------------------------
いちど自動起動が正常動作するか確かめるためにOSを再起動してみましょう。OS起動後に以下の確認で確かめることができます。
----------------------------------------------
$ ps -ef | grep svscan
root       422     1  0 18:49 ?        00:00:00 /bin/sh /command/svscanboot
root       429   422  0 18:49 ?        00:00:00 svscan /service
user01   720   708  0 18:55 pts/0    00:00:00 grep svscan
----------------------------------------------
OS起動時に「/bin/sh /command/svscanboot」と「svscan /service」がプロセスとして存在していれば、rc.localの自動実行が有効になっています。
これで自動起動するようになりました。

その2-2:Debian8用のdaemontools起動設定(systemdを使う場合)
どうしてもsystemdじゃないとダメ。という御仁のために設定してdaemontoolsが動作したsystemd設定を記述しておきます。

----------------------------------------------
# cd /lib/systemd/system
# ls -la
合計 728
-rw-r--r--  1 root root   403  4月 18 01:37 -.slice
drwxr-xr-x 19 root root 32768  5月  1 11:04 .
drwxr-xr-x  8 root root  4096  5月  1 10:26 ..
-rw-r--r--  1 root root   115 11月  9 13:59 acpid.path
-rw-r--r--  1 root root   199 11月  9 13:59 acpid.service
(省略)
lrwxrwxrwx  1 root root    27  4月 18 01:37 urandom.service -> systemd-random-seed.service
-rw-r--r--  1 root root   392  4月 18 01:37 user.slice
-rw-r--r--  1 root root   497  4月 18 01:37 user@.service
lrwxrwxrwx  1 root root     9  4月 18 01:37 x11-common.service -> /dev/null
----------------------------------------------
デフォルト状態がこのようなファイル構成になっています。
ここにsystemdで自動起動を指示するファイルを作成します。
----------------------------------------------
# touch use.daemontools.svscan.service
# ls -la use.daemontools.svscan.service
-rw-r--r-- 1 root root 0  5月  1 15:13 use.daemontools.svscan.service
# vi use.daemontools.svscan.service

# cat use.daemontools.svscan.service
[Unit]
Description=Daemontools svscan
After=syslog.target

[Service]
ExecStart=/usr/local/bin/svscan /service 2>&1 | /usr/local/bin/readproctitle /service errors: ......................................................
Restart=always

[Install]
WantedBy=multi-user.target
#WantedBy=graphical.target # This is redundant as the graphical.target is an implicit superset of multi-user.target
----------------------------------------------
ファイル作成後、起動設定が適切かどうか確認しましょう。
※確認コマンド:systemctl list-unit-files(で登録されたことを確認できる。)
----------------------------------------------
# systemctl enable use.daemontools.svscan.service
Created symlink from /etc/systemd/system/multi-user.target.wants/use.daemontools.svscan.service to /lib/systemd/system/use.daemontools.svscan.service.

# systemctl list-unit-files
# systemctl status use.daemontools.svscan.service
● use.daemontools.svscan.service - Daemontools svscan
   Loaded: loaded (/lib/systemd/system/use.daemontools.svscan.service; enabled)
   Active: active (running) since 金 2015-05-01 15:45:08 JST; 40s ago
 Main PID: 949 (svscan)
   CGroup: /system.slice/use.daemontools.svscan.service
           └─949 /usr/local/bin/svscan /service 2>&1 | /usr/local/bin/readproctitle /service errors: ......................................................
systemctlコマンドにて作成したserviceファイルを制御する動作を実行します。systemctlはオプション次第でいろいろな動作をするみたいです。
このあたりはもっと詳しいサイトを参照してください。
完了後に、「shutdown -r now」でsvcが正常起動していることを確認しましょう。OS起動後プロセスを見てみましょう。
----------------------------------------------
$ ps -ef | grep svscan
root       445     1  0 17:51 ?        00:00:00 /usr/local/bin/svscan /service 2>&1 | /usr/local/bin/readproctitle /service errors: ......................................................

----------------------------------------------
起動していますね。
かんたんではありますが、ここまでの手順でsystemdによるdaemontools起動が実現できます。

その3:clockspeed-0.62のインストール
ここまででdaemontoolsが動作するようになったので、ようやくdaemontools上で動作するclockspeedのインストールを開始できます。
まずdaemontools同様にダウンロードと解凍を実行します。
----------------------------------------------
# cd /home/user01/src/
# wget http://cr.yp.to/clockspeed/clockspeed-0.62.tar.gz
# tar zxvf clockspeed-0.62.tar.gz
----------------------------------------------
カレントディレクトリに「clockspeed-0.62/」で始まるツリーが作成されます。
解凍したディレクトリに移動して、パッチclockspeed-0.62-q2.diffをダウンロードし適用します。
パッチclockspeed-0.62-q2.diffはファイルclockview.cを編集するのでcpコマンドでバックアップを取得しておきます。
さらにファイルconf-ccの編集が必要です。「gcc -include /usr/include/errno.h」の記述をファイルconf-ccに追記します。
これをやらない状態でmakeすると「make: *** [clockspeed.o] エラー 1」となります。対象のファイル(conf-cc)はgcc -2 とだけ表記されていますが、その箇所をerror.h(フルパスで)と今風に記載を変更してエラーが出なくなります。(コンパイル環境が昔と今で異なるために必要な追記)

さらにconf-homeファイルとclockspeed.cファイルを編集します。どのように編集するかは後述します。
----------------------------------------------
# cd clockspeed-0.62
# cp clockview.c clockview.c.org
# wget http://www.nslabs.jp/archives/clockspeed-0.62-q2.diff
# patch -s -p1 < clockspeed-0.62-q2.diff
# cp conf-cc conf-cc.org
# echo gcc -include /usr/include/errno.h > conf-cc
# vi conf-home
# vi clockspeed.c
----------------------------------------------
※conf-homeファイルの編集
このconf-homeの記述でclockspeedがどこにインストールされるかを指定することができます。
私は、デフォルトのままにせず、インストール場所を自分の都合の良い場所に指定しています。
一言でいうと「/usr/local/clockspeed」にインストールされるように指定を変更しています。
----------------------------------------------
編集前
----------------------------------------------
/usr/djb

This is the clockspeed home directory. Programs will be installed in
.../bin.
----------------------------------------------
編集後
----------------------------------------------
/usr/local/clockspeed

This is the clockspeed home directory. Programs will be installed in
.../bin.
----------------------------------------------

※clockspeed.cファイルの編集
makeコンパイルエラーを発生させる行をコメントアウトし、無効にします。
ただ、これ正しいの?と聞かれても私は答えを持っていません。
これでインストールしてもclockspeedの使いたい機能は使えているから良しとしている、というだけです。
----------------------------------------------
編集前
----------------------------------------------
#include <sys/types.h>
#include <sys/time.h>
#include "readwrite.h"
#include "exit.h"
#include "select.h"
#include "scan.h"
#include "fmt.h"
#include "str.h"
#include "fifo.h"
#include "open.h"
#include "error.h"
#include "auto_home.h"
#include "timing.h"

#ifndef HASRDTSC
#ifndef HASGETHRTIME

  Error! Need an unadjusted hardware clock.

#endif
#endif

struct point {
----------------------------------------------
編集後※3行を"//"を先頭に付けてコメントアウトしています。
----------------------------------------------
#include <sys/types.h>
#include <sys/time.h>
#include "readwrite.h"
#include "exit.h"
#include "select.h"
#include "scan.h"
#include "fmt.h"
#include "str.h"
#include "fifo.h"
#include "open.h"
#include "error.h"
#include "auto_home.h"
#include "timing.h"

#ifndef HASRDTSC
//#ifndef HASGETHRTIME

//  Error! Need an unadjusted hardware clock.

//#endif
#endif

struct point {
----------------------------------------------
ここまでの編集でmakeインストールができるようになります。
# make
してから
# make setup check
と実行してインストールが完了します。
画面は以下のような表記になります。ご参考まで。
----------------------------------------------
# make
nroff -man sntpclock.1 > sntpclock.0
~省略~
./compile clockview.c
./load clockview strerr.a substdio.a error.a str.a fs.a
./compile install.c
./compile hier.c
./load install hier.o auto_home.o strerr.a substdio.a open.a error.a str.a
./compile instcheck.c
./load instcheck hier.o auto_home.o strerr.a substdio.a error.a str.a
# make setup check
./install
./instcheck
----------------------------------------------
ここまででインストール自体は完了しています。

その4:clockspeedを設定
まずは利用する命令をシェル化しておき、使いやすくしましょう。
ここでは「/etc/opt/」配下に各シェルを作成していますが、どこでも構いませんし、作成作業を実行するユーザはroot以外の一般ユーザでも可能です。(clockspeedによる時刻合わせ/時刻管理を実行するユーザで実行してください。)
----------------------------------------------
# cd /etc/opt/
# mkdir clockspeed
# cd clockspeed/
# mkdir task
# cd task/

# vi /etc/opt/clockspeed/viewclock.sh
※ファイルviewclock.shの内容は後述

# chmod +x /etc/opt/clockspeed/viewclock.sh
# /etc/opt/clockspeed/viewclock.sh
before: 2015-05-07 20:39:45.290921000000000000
after:  2015-05-07 20:40:07.247730887822717427

# vi /etc/opt/clockspeed/addclock.sh
# chmod +x /etc/opt/clockspeed/addclock.sh
# vi /etc/opt/clockspeed/chgjstclock.sh
# chmod +x /etc/opt/clockspeed/chgjstclock.sh

# touch /etc/opt/clockspeed/chgtime.sh
# chmod +x /etc/opt/clockspeed/chgtime.sh
# vi /etc/opt/clockspeed/chgtime.sh

----------------------------------------------

作成した各ファイルの内容です。
----------------------------------------------
※viewclock.sh(ntp.nict.jpの1サーバを指定しています。)
 このファイルを実行すると、$SNTPSVで指定したNTPサーバと
 現在のPC上の時計をbefore/afterで比較できます。
----------------------------------------------
#!/bin/sh
SNTPSV=133.243.238.163
PATH=/usr/local/clockspeed/bin:$PATH
sntpclock $SNTPSV | clockview
----------------------------------------------
※chgjstclock.sh
 このファイルを実行すると$SNTPSVで指定したNTPサーバに
 現在の時刻を合わせた後、状態をbefore/afterで表示します。
----------------------------------------------
#!/bin/sh
SNTPSV=133.243.238.163
PATH=$PATH:/usr/local/clockspeed/bin:/command; export PATH
echo PATH=\$PATH:/usr/local/clockspeed/bin:/command >> ~/.profile; export PATH
sntpclock $SNTPSV | clockadd
sntpclock $SNTPSV | clockview
----------------------------------------------
※chgtime.sh
 このファイルは時刻補正データを収集し、ファイルに保管します。
 補正データは何秒かに1回の頻度で継続して緩やかに時刻を
 合わせるために内部時計で秒間≠1秒をカウントする元データです。
----------------------------------------------
#!/bin/sh
#
#ntp.nict.jp.            3365    IN      A       133.243.238.163
SNTPSV=133.243.238.163
PATH=/usr/local/clockspeed/bin:$PATH

#Internet NTP
#インタネット上のNTPサーバを使います。
sntpclock $SNTPSV > /usr/local/clockspeed/adjust &

#Intranet NTP(taiclock)
#ローカルIPを使います。
#taiclock 192.168.XX.X | clockadd
----------------------------------------------
※addclock.sh
 このファイルを実行すると$SNTPSVで指定したNTPサーバから
 時刻補正データを収集し、ファイルに保管したのち、同NTPから
 現在の時刻を取得して内蔵時計を合わせます。
 chgtime.shしたあとにchgjstclock.shするイメージです。
----------------------------------------------
PATH=/usr/local/clockspeed/bin:$PATH
#ntp.nict.jp.    IN      A       133.243.238.163
SNTPSV=133.243.238.163
sntpclock $SNTPSV > adjust &
sntpclock $SNTPSV | clockadd &
----------------------------------------------

その5:最初の時刻合わせ
まずは最初の時刻合わせを一回やっておきます。
先ほど生成した「chgjstclock.sh」を実行すると時刻合わせを実行します。
正しくは、「/usr/local/clockspeed/bin/sntpclock NTPサーバIP | /usr/local/clockspeed/bin/clockadd」というコマンドラインで指定したIPのNTPサーバの時刻情報にPCの内部時計を合わせることができます。
この動作をシェルにしたのが「chgjstclock.sh」です。
----------------------------------------------
$ sudo ./chgjstclock.sh
before: 2015-05-01 12:53:34.153087000000000000
after:  2015-05-01 12:53:34.152797963917367160
----------------------------------------------
時計合わせ直後でbeforeとafterの差が0.000297秒くらいの差になりました。
1ms(1ミリ秒)=0.001秒ですから0.3ミリ秒くらいの差しかありません。

その6:clockspeedを常駐させる
初回の時刻調整が完了したところで、この状態をキープするためにOS起動時にclockspeedが自動起動するように設定します。
daemontoolsのサービスディレクトリにしておけば、svscanが自動的に検出してclockspeedが起動されます。
なんで/service/へシンボリックリンクを貼っているのか、というところはdaemontoolsについて解説してくれているサイトをご覧になってくださいね。
以下のようにしてclockspeed起動のためのサービスディレクトリを作成します。※/usr/local/clockspeed/clockspeed がサービスディレクトリ
----------------------------------------------
# mkdir /usr/local/clockspeed/clockspeed
# cd /usr/local/clockspeed/clockspeed
# touch run
# chmod +x run
# vi run
# ln -s /usr/local/clockspeed/clockspeed /service
# cd /usr/local/clockspeed
# mkdir /usr/local/clockspeed/taiclockd
# cd taiclockd/
# touch run
# chmod +x run
# vi run
# ln -s /usr/local/clockspeed/taiclockd /service
----------------------------------------------
生成するファイル:
/usr/local/clockspeed/clockspeed/runの内容
----------------------------------------------
#!/bin/sh
exec 2>&1
echo 'Starting clockspeed...'
exec env - PATH="$PATH" \
/usr/local/clockspeed/bin/clockspeed
----------------------------------------------
----------------------------------------------
生成するファイル2:
/usr/local/clockspeed/taiclockd/runの内容
----------------------------------------------
#!/bin/sh
exec 2>&1
echo 'Starting taiclockd...'
exec env - PATH="$PATH" \
/usr/local/clockspeed/bin/taiclockd
----------------------------------------------
サーバではないコンピュータ(電源を入り切りする頻度が高いパソコンなど)ではrunスクリプトで直接時刻合わせを初回実行して、OS起動直後から正しい時刻になるように1行加えます。
----------------------------------------------
/usr/local/clockspeed/clockspeed/runの内容(その2)
----------------------------------------------
#!/bin/sh
/usr/local/clockspeed/bin/sntpclock 133.243.238.163 | /usr/local/clockspeed/bin/clockadd
exec 2>&1
echo 'Starting clockspeed...'
exec env - PATH="$PATH" \
/usr/local/clockspeed/bin/clockspeed
----------------------------------------------

確認するためには「svstat」コマンドを実行します。

----------------------------------------------
確認方法
----------------------------------------------

# svstat /service/clockspeed
/service/clockspeed: up (pid 1154) 9 seconds
----------------------------------------------
※正常動作していると上記メッセージです。
こんな感じで情報を認識します。
 サービス名=/service/clockspeed
 状態=up (pid 1154)
 起動継続時間=9 seconds
何回か実行すると継続している時間分「起動継続時間」がカウントアップします。
----------------------------------------------
# svstat /service/*
/service/clockspeed: up (pid 1154) 90 seconds
/service/taiclockd: up (pid 1164) 5 seconds
~12秒後…~
# svstat /service/*
/service/clockspeed: up (pid 1154) 102 seconds
/service/taiclockd: up (pid 1164) 17 seconds

----------------------------------------------
エラーがある場合以下のような表記になります。
----------------------------------------------
# svstat /service/*
/service/clockspeed: up (pid 27481) 0 seconds
# svstat /service/*
/service/clockspeed: up (pid 27481) 1 seconds
# svstat /service/*
/service/clockspeed: up (pid 27481) 0 seconds
----------------------------------------------
※何回やっても「起動継続時間」が増えません(0/1を繰り返す)

この場合にはパーミッション確認や起動エラーのログ調査等実施し、起動を阻害している要因を探し出さなければなりません。
また、runスクリプトの問題(誤表記など)、daemontoolsが正常動作していない、といった複合的な要因を確認するため、手動で起動してみることもいいかもしれません。
-------daemontoolsを手動で起動し確認----------------------------------------------
# svscan /service &
[1] 766
$ ps -ef | grep clock
root       767   766 0 13:35 pts/0   00:00:00 supervise clockspeed
root       768   767 0 13:35 pts/0   00:00:00 /usr/local/clockspeed/bin/clockspeed
----------------------------------------------
※clockspeedのrunスクリプトがdaemontoolsによって動作した例

 

その7:いろいろな仕上げ
時刻合わせをcron登録するには、crontabで
0 0-23/6 * * * /etc/opt/clockspeed/chgjstclock.sh
と仕掛けると6時間おきにNTPサーバと時刻同期し6時間ごとに最新時間に更新します。

addclock.shをatコマンドで仕掛ける。
時刻補正をatコマンドでちょっとづつ期間を空けて実行するように仕掛けます。こんな感じです。
# at "HH:MM DD.MM.YY" -f "/etc/opt/clockspeed/addclock.sh"
これを2015/7/13 0:30に実行するにはこのようにコマンドを実行します。
----------------------------------------------
# at "0:30 13.07.15" -f "/etc/opt/clockspeed/addclock.sh"
warning: commands will be executed using /bin/sh
job 1 at Mon Jul 13 00:30:00 2015
----------------------------------------------
まあこんな感じで、スケジュールを3時間後、1日後、3日後、1週間後、3か月後、1年後、といった具合でatコマンドでスケジュールしておきます。
それぞれ3時間でずれる時差を学習して時刻合わせ、その3日後に3日でずれる時差を学習して時刻合わせ、その1週間後に…といった具合にズレた時差を間隔を徐々に増やして補正することでclockspeedで刻む時刻が正確になってくる、という主旨です。
このあたりはcronで定期的にsntpclockコマンドでadjustに時刻データを引き渡すだけ、という場合もあって、どちらで実行するかはご自分でご判断を。