t-hom’s diary

主にVBAネタを扱っているブログ…とも言えなくなってきたこの頃。

空気モニターのファン交換。ホコリの量でAruduino Uno正規品のパワーを実感。

※この記事はホコリ閲覧注意です。といってもホコリっぽいホコリだけで虫とかはでません。そもそも私が虫嫌いなのでそんなものを写真におさめることはないです。

今回は自作の空気モニターのファンから異音がしたので交換。

使用しているのはこちらの製品。

※製品ラベルは当時と変わってるけどサイズや消費電力・駆動電圧は同じ。


以下の記事を書いたのが2020年11月末なので、2年ちょっと頑張ってくれた感じ。
thom.hateblo.jp

最後に掃除したのが1年前にこの記事を書いたとき。
thom.hateblo.jp

ただそのときは稼働から1年使っていたにもかかわらず、うっすらホコリが見えるかな。。っていう程度だった。

そして今回開けてみたところ、見事にびっしりと埃が。。

Arduinoマイコン。これ湿気るとショートしそうだな。。

ダストセンサー。

排気口。

普通はこんな汚れているとうわぁ汚ぇって思うんだけど、あの小型ファンがちゃんと仕事している証拠なので個人的には嬉しいホコリの量。

正直、この小型ファンほとんど音もしないしほんとに意味あんのか半信半疑だった。

そしてArduino Pro Microで使っていた1年間はほとんどホコリが付かないのに対し、Unoに変えてこうなったということはやはりそれまでが電力不足だったんだろう。電源まわりがしっかりしてるっていう話はどうやらマジっぽい。

それでこれを交換するわけだけども、ホットボンドでぐるっと周囲を固めたので剥がすのにかなり苦労する羽目に。

ホットボンド正直舐めてた。

力業で剥がすとパネルごとパキっといきそうだし、もっかいパネルをプリントするにも今3Dプリンター1ミリノズルに変えてるので精度落ちるんだよなぁ。。0.4に戻すのも面倒だし。。

てことで頑張った。

段ボールカッターをノコギリ替わりにホットボンドとパネルのつなぎ目をゴリゴリと削ぎつつミニラジペンでむしる。プラペンチでブレードを分離して上下左右の薄いところを切断し4つの角パーツに分かれたところでネジザウルスで慎重にもぎ取った。

だいぶ道具の本来の用途とズレてるけど作戦は無事に成功。
凝りもせず新しいファンをホットボンドでがっちがちに固めた。
無事に異音も収まり作業は以上。

ただArduino Pro Microで使ってたときは耳を近づけてもほとんど音がしなかったけど、Unoだとさすがに耳を近づけたら音がする。
てことは、Pro Micro時代はほとんど仕事してなくて本気を出したのはUnoに変えたここ1年ということか。
そうなるとまた1年後くらいに壊れても不思議ではないので予備をポチっておいた。

以上。

2,600円の激安電子負荷でACアダプタ性能をチェックする

前回ラズパイの電力不足についてACアダプタが原因だったと書いたけど、実は原因究明のために可変電子負荷モジュールを発注していた。

電子負荷はちゃんとした製品を買うとローコスト版で5~6万、高いものだと20万近くもする。
簡易実験用として基盤むき出しのタイプがAmazonで沢山売られているが、ちゃんとケースがついててこの値段というのはまぁまぁいい感じ。

ちょうどさっき届いたので共立電子のACアダプタを試してみたい。

ちなみに同梱物は本体のみで説明書の類は無い。Amazonの商品説明画像がすべて。
ケーブル類もついてないので電源供給は自分で準備が必要なので注意。モジュールという名前のとおり、製品というより部品扱いである。

裏側には負荷装置自体の動作に必要な電力源を繋ぐVと記号の書かれた端子と、テストしたい電源(電池やACアダプタ等)を繋ぐLと記号の書かれた端子がある。

端子Vには5~30Vを供給すれば良いので適当にUSBケーブルを接続。端子Vへの給電はパソコンのUSBバスパワー程度の電力で足りる。プラスマイナスだけ逆接しないよう注意。

端子Lには共立電子のACアダプタを繋ぐのでとりいそぎ秋月で買った4Aまで対応しているDCジャックを繋いだ。マル信無線電機製の普及品は0.5Aまでしか対応してないので要注意。

まずは無負荷でテスト。5.13Vと表示されている。

使い方は、ON/OFFボタンで負荷のON/OFFを切り替え、ノブを右に回すと0.01Aずつ電流が上がっていくので、負荷がオンになっていると通常は※電圧が低下していく。
※ACアダプターによっては内部の制御で逆に電圧が上がるようなものもあるとのことなので一概には言えない。

ちなみにこの製品自体の表示が信頼できるのかも気になったので、いつものSANWA製のテスターを間に挟んで電流を計ってみたところ、0.02A程度のズレはあったものの値は追従してくるので誤差が広がることもなく、今回の実験に支障はないレベルだと言える。

では再開して、0.5Aで5.06V。

負荷が1Aになると4.98V。

あれ?以外と頑張ってるな。。

2Aで4.85V。

3Aで4.71V。

おかしい。ラズパイのときは4.5V程度まで下がってたのに。
ラズパイ3B+の推奨アダプターの定格電流は2.5Aだったはずなので、3Aも引っ張って4.71V確保できてるなら電圧低下警告の閾値を下回ることはないはず。

この電子負荷は最大5A、35Wまで引っ張れる使用だけどさすがに配線が発熱すると怖いのでこの辺にしておいた。なお3Aでも長期接続する場合は各配線の定格を確認する必要がある。ジャンプワイヤー等に使われるデュポン端子の定格が3Aなのでこれ以上はヤバそう。


このアダプターは公称値で定格5V/4A Load Regurationが±6%ということは4A引っ張っても4.8Vを維持するはずなので実験結果はやや低めだけど、電圧が公称値を下回ったのはアダプター以外の配線抵抗の影響だろう。


ということで共立電子製のACアダプターに問題はなさそうだ。

で、色々試したところ犯人は延長に使っていたコイツだった。

間に噛ませると0.5A引っ張っただけで電圧が4.7Vまで落ちる。さっきは3Aで4.7だったのに。

1Aだと余裕でUndervoltage。

さすがにこれ以上は怖いのでやめておいた。

ケーブルでの電圧降下が大きいということはそこで電力が損失してるわけなんだけどエネルギー保存の法則ってのがあって、損失といっても消えるわけじゃない。要するに熱に変換されてるということ。電流を引っ張りすぎて加熱・絶縁被覆が溶けてショート・大電流が流れて被覆が発火して火事。。というのが最悪のシナリオ。

ということで犯人も判明し、Amazonで該当の延長ケーブルの低評価レビューも書き終えてスッキリ。

ちなみに延長ケーブルの商品画像ではケーブル部にAWG22と刻印があったので断面積0.3sq相当。私が買ったのは1mなので計算すると、

 電圧降下=(定数35.6 ×長さ1m × 電流1A)÷ (定数1000 × 断面積0.3sq)≒0.12V となるはず。

今回の検証では0.7Vも下がってるので到底AWG22とは思えない。あるいは初期不良品だったのか。。


今回冤罪を喰らわせてしまった共立電子のACアダプター自体はそこそこ優秀のようなのでまた何かに使おうと思う。

Raspberry PiのUndervoltage(電圧低下)対策でアダプターを購入し検証してみた。

先日ラズパイで作成した目覚まし時計が作動しなかった※。
※保険で別の目覚ましをかけてるので遅刻はしてない。

sshログインしようとしたがパスワードを聞かれて入力した段階でConnectionが切断されるという症状を繰り返す。
それでHDMIモニターを繋いでみたところなぜか起動シーケンスが走ってる。なんか再起動されてしまったっぽい。

とりあえずSSH接続できるようになったのでログを確認してみたところ、Undervoltage が大量に発生している。
直接の原因かどうかは分からないけど、ググるとsshログインできなくなるなどの症状も見つかったのでとりあえずこの電圧低下を解消する。

Apr  3 08:10:26 alarm kernel: [666805.526610] hwmon hwmon1: Voltage normalised
Apr  3 08:10:32 alarm kernel: [666811.574663] hwmon hwmon1: Undervoltage detected!
Apr  3 08:10:38 alarm kernel: [666817.622687] hwmon hwmon1: Voltage normalised
Apr  3 08:10:40 alarm kernel: [666819.638723] hwmon hwmon1: Undervoltage detected!
Apr  6 07:34:04 alarm kernel: [   11.679173] hwmon hwmon1: Undervoltage detected!
Apr  6 07:35:07 alarm kernel: [   76.190739] hwmon hwmon1: Voltage normalised
Apr  6 07:35:10 alarm kernel: [   78.206732] hwmon hwmon1: Undervoltage detected!
Apr  6 07:35:16 alarm kernel: [   84.254724] hwmon hwmon1: Voltage normalised
Apr  6 07:35:18 alarm kernel: [   86.270717] hwmon hwmon1: Undervoltage detected!
Apr  6 07:53:45 alarm kernel: [  118.526706] hwmon hwmon1: Voltage normalised
Apr  6 07:53:47 alarm kernel: [  120.542739] hwmon hwmon1: Undervoltage detected!

もともと使っていたのは共立電子産業の5V 4A出力のアダプタ。
出力電流が大きくて良さそうだと思って買ったんだけど、結論から言ってラズパイで使うには電圧の低下が大きくてダメだった。

訂正:真犯人は延長ケーブルだったので訂正。共立電子製のACアダプタは悪くなかった。
thom.hateblo.jp



無負荷時の電圧が5.2V。

ラズパイへの供給電圧を確認する方法だが、GPIOの5V端子とGND端子を測定すれば良さそうだ。この時点で4.8V。

そして目覚ましシステムはUSBバスパワーでスピーカーを鳴らすのでそちらでも電圧降下が考えられる。

USBスピーカー単体を別の5V USBアダプタから給電して電流値を計ってみたところ、ボリューム最大で音楽を鳴らすと0.2~0.5A程度だった。

ラズパイに繋いで音楽を鳴らしたときにどうなるかというと、、本体電圧が4.67Vまで低下。

更に警告音を複数組み合わせたアラームを鳴らすと。。

これはいかん。。無負荷時の5.2Vから比較すると0.7Vも低下してる。
ラズパイは電圧が4.6Vを切るとUndervoltageを出すらしい。様々な理由でコンセント側の電圧変動も供給電圧に影響を与えるそうなので日常的に電圧低下が発生している理由も頷ける。

それで色々ググっていたらラズパイの公式ACアダプターは5.1V表記であることが判明。5.1Vを謳うアダプタというのはかなり珍しいが探せば色々と見つかる。

私が買ったのはこちらのアダプタとUSB-Type CからMicro USBへ変換するアダプタ。

ラズパイ3B+で使うのでMicro USBのアダプタがあればベストだったけど5.1Vで2.5A以上の出力があってMicro USBとなるとAmazonでは良さげなものがみつからず、わざわざ他のサイトに登録して買うのも面倒なのでUSB Type Cのアダプタにした。

まずは無負荷計測してみたところ5.35V。

ちょっと電圧が高すぎる気がするので大丈夫なのか調べてみたところ、公式アダプタも5.36V最大だよっていう情報があった。。
forums.raspberrypi.com

更に調べてみた。以下にラズパイ3に対応した公式アダプタの仕様書がある。
https://datasheets.raspberrypi.com/power-supply/micro-usb-power-supply-product-brief.pdf

ほんとだ。大丈夫そう。

Load regulationというのは負荷変動に対して電圧がどれくらい変動するかという指標。
5.1Vのプラマイ5%だから公式アダプタは4.845V~5.355Vの範囲で動作するということ。

一般的には無負荷時の方が電圧が高いので無負荷5.35Vなら公式と同じだろう。

ラズパイに繋いで同じように計測してみたところ、何も音楽を流さない状態で約5.349V。旧アダプタは同条件で4.83Vだったのでこの時点で0.5V近くのアドバンテージがある。

音楽を再生すると5.32V

アラームを再生すると5.3V

電圧の低下は微々たるものである。ということでこちらのアダプターを採用することにした。

さらにもう1つ嬉しい誤算が。何気なく買ったUSB-CからMicro USBへのアダプタであるが、これまで使っていたものより少しだけ端子が長かったのだ。

実はこれまでのアダプタはラズパイにケースを付けたらケースの厚みで挿し込みが甘くなってしまい、軽く引っ張るだけで抜けてしまう状況だったのだが、この微妙な端子の長さの違いによってしっかりと挿し込めるようになった。

ということでアダプタを変えたらUndervoltage警告は出なくなった。

ただし注意点として、個体によっては無負荷時に5.4V出るものがあるらしいので真似する場合はあくまで自己責任でお願いしたい。
まぁ実際はラズパイ側で5.355Vからバッファは取っているはずなのでそこまで繊細じゃないとは思うけど壊れたと言われても困るので念のため。

終わりに

これまでACアダプタといえば入出力の電圧・電流とプラグ形状だけ見てれば充分と考えていたが、他にもロードレギュレーション、ラインレギュレーションなどの特性があることが分かり勉強になった。
時折、家電などで必ず専用のアダプタを使えっていう指定があるのはどうやらこのためらしい。

特にノートPC等の高額なデバイスを使う際はちゃんと純正のアダプタを使う用にしたい。

以上

pythonリマインダーにエラーハンドリングを追加

昨日紹介したpythonリマインダーについて、エラ―処理を追加したのでご紹介。
thom.hateblo.jp

元のコードがファイル名の日付書式に頼ってリマインドを実行する都合上、ファイル名の入力ミスで正しく日付を読み取れないとpythonエラーにより処理を停止してしまう。

コマンドで実行していればエラーが見えるが、今回のようにスケジューラーで黒画面を出さない場合は何も起きずにエラーに気づくことが無い。
これではリマインダーとしてイマイチなので、エラー処理を追加した。ついでにtasksフォルダが無いケースやiconファイルが無くなったケースなど考えうるシチュエーションをカバーした。

import os
import glob
from datetime import datetime as dt
from plyer import notification


base_path = os.path.dirname(os.path.abspath(__file__))
files = glob.glob(os.path.join(base_path,"tasks\*"))
cnt = 0
err = 0
for file in files:
    str_task_time = os.path.basename(file)[0:16]
    try:
        task_time = dt.strptime(str_task_time, "%Y_%m_%d_%H_%M")
        if dt.now() > task_time:
            cnt += 1
    except:
        err += 1


notify_title = "ERROR"
notify_message = "不明なエラー"

if not os.path.exists(os.path.join(base_path,"tasks")):
    err += 1
    notify_message = "tasksフォルダが存在しません。\n"+base_path+"を確認してください。"
else:
    if err > 0:
        notify_message = "タスクファイル名の日付書式を確認してください。\n"+base_path+r"\tasks"
    else:
        if cnt > 0:
            notify_message = str(cnt)+" 個の期限切れタスクを処理してください。\n"+base_path+r"\tasks"

icon_path = os.path.join(base_path, "notify.ico")
if not os.path.exists(icon_path):
    err += 1
    icon_path = None
    notify_message = "notify.icoが見つかりません。\n"+base_path

if err == 0:
    notify_title = "Reminder"

if err+cnt > 0:
    notification.notify(
        title=notify_title,
        message=notify_message,
        app_name="Py Notify",
        app_icon=icon_path,
        timeout=10
    )

あと外出先で何か追加したいリマインダーを思いついた場合にどうするか悩んだけど、これはスマホのTo Doリストアプリを使い、pythonリマインダーの方にはスマホからpythonリマインダーに転記するというタスクを登録した。

スマホのリマインダーも登録だけしてちゃんと確認・消し込むということががなかなか定着しなかったけど、これで解決できると思う。

また、土日は終日リマインドを有効にしたいのでスケジューラーのトリガーを複数にして平日と休日でリマインド時間帯を分ける修正も行った。

以上。

pythonでWindows通知を使ったリマインダーの仕組みを作る

いつかやりたいことをまとめたリストをWishリストと呼ぶらしい。
作っただけでは忘れ去ってしまうので今回はWishリストのリマインダーシステムを作りたい。

いつこれをするという確定したスケジュールであればカレンダーに入れてしまえば良いんだけど、いつかやりたいので時々思い出したいみたいな微妙な案件って結構あると思う。

そういうのを、例えば1か月後にリマインドしてくれる仕組みが欲しい。
それも単発ならカレンダーで済むんだけど、そのワンアラームを無視してしまったらおしまいなので、設定した期限が到来すると、以降は明示的にリスケするまでしつこくリマインドするような仕組みを作りたかった。最近作った目覚ましのスヌーズと同じ考えである。

目覚まし時計の話はこちら。
thom.hateblo.jp


さて、今回思いついたのがWindowsのトースト通知を使うアイデア。あれ地味だけど意外と注意を引く。
1回じゃ見逃してしまうことが多いけど、しつこく何度も表示されたらさすがに気になって確認する。
在宅時は基本PCの前にいるのでちょうど良さそうだ。

てことで出来たがって運用中の図がコレ。

PythonでWindows通知を扱うにはplyerモジュールが必要なのでpipでインストールしておく。
※最初playerだと思ってインストールしたら別物だったのでスペル注意。

コード:pynotify.pyw

※拡張子pywは見慣れないと思うけど、こうしておくと関連付けプログラムがpythonwとなるので実行時の黒い画面が出ない。

import os
import glob
from datetime import datetime as dt
from plyer import notification


base_path = os.path.dirname(os.path.abspath(__file__))
files = glob.glob(os.path.join(base_path,"tasks\*"))
cnt = 0
for file in files:
    str_task_time = os.path.basename(file)[0:16]
    task_time = dt.strptime(str_task_time, "%Y_%m_%d_%H_%M")
    if dt.now() > task_time:
        cnt += 1

if cnt > 0:
    notification.notify(
        title="Reminder",
        message=str(cnt)+" 個の期限切れタスクを処理してください。\n"+base_path+r"\tasks",
        app_name="Py Notify",
        app_icon=r"C:\Users\ho_\dev\pytodo\notify.ico",
        timeout=10
    )

使い方

注意)いつものとおり、私が自分で使えれば良いのでユーザーフレンドリーではない。

フォルダ構成としては上記のスクリプトと同じ階層にnotify.icoという任意のアイコンとtasksフォルダを用意し、tasksフォルダ内にはyyyy_mm_dd_HH_MM_タスク名.txtの形式でタスクごとにファイルを保存しておく。

例)

このスクリプトを実行した際、ファイル名の日次が現在時刻よりも古い場合は期限切れタスクとしてカウントされ、期限切れタスクが1つでもあればWindows通知が出るという仕組み。

そしてこれをWindowsタスクスケジューラーで定期実行する。
なおタスクスケジューラ自体はググれば使い方分かると思うので固有の設定のみ紹介。

トリガーはこんな感じ。

私の場合在宅勤務もあるので、勤務中に発生しないよう毎日18時に起動して5分毎に実行され、4時間有効(つまり22時まで通知が続く)という設定にしている。

操作はこんな感じ。

※pythonwにすること。pythonでも動くけど黒いコマンド画面が表示されてしまうのでダサい。


これで一応リマインドシステムのアルファ版は完成としよう。
ただまぁ、リスケするのに逐一手でファイル名を修正するのが面倒なのでそのあたりはドラッグ&ドロップするとn日リスケするスクリプトとか、そういう方向性で思案中。

おわりに

リマインダーなんて探せばいくらでもありそうなもんだけど、意外とピンとくるものが無い。
リマインドを受け取っても1回確認したらおしまいというものが多い。どれもこれも、人の自由意志に信頼を置きすぎている。

リマインドにおける「確認した」は実に不確実である。私みたいな怠惰な人間に、そんな簡単に確認ボタンなんて押させちゃいけないんだ。
すでに完了したものについて既定の手順を踏んで解除 or 次のリマインドを再指定する以外の選択肢はない方が良いと思う。
これが今回自分で構築しようと思った理由である。

以上。

https通信でEV証明書を示す緑のバーが廃止された理由について調べてみた。

今週末は自宅サーバーのメンテや自動アップデート設定などメンテに勤しんでいたのだが、Web系のツールが増えてくるとHTTPSで通信がしたくなってくる。

所詮イントラからしかアクセスしないのでプライベート認証局を立てて運用しようかと少しSSL※について学習することにした。

※実際に学習するのはTLS(Transport Layer Security)という後継技術である。SSL(Secure Socket Layer)とTLSは厳密には別物だけど母親がプレステをいつまでもファミコンと言い続けるような感覚でみんなSSLって呼ぶので技術者ももういいやそれでと諦めてるっぽく、2023年現在はSSLといえばふつうTLSのことを指す。頑なにTLSと呼ぶのもなんかキモい奴になるが、SSL/TLSと表記すると分かってる奴感がでる。


それでAmazonで以下の書籍を調達しのだが、ブラウザのアドレスバーに表示されるグリーンのEV証明が懐かしい。

引用:位置No.754/1643

この書籍の第2版発行が2017年なので当時はまだグリーンの表示があったのだ。
無くなったのは2019年にリリースされたChrome 77かららしい。

あれ結構好きだったんだけどいつの間にか無くなって不思議に思っていたのでこの機会に調べてみた。

まずは窓の杜ニュースから引用

これは“Identity Verified(本人確認)”といった組織名で取得したEV証明書を用いることで、ユーザーを混乱に陥れることができる例がセキュリティ研究者から指摘されていたため。iOSの「Safari」では対策のためEV証明書の組織表示がすでに廃止されており、「Google Chrome」もそれに追随した格好だ。

引用元:「Google Chrome 77」が正式公開 ~アドレスバーのEV証明書発行元表示は廃止 - 窓の杜

うん、混乱のもとになるというのは分かったけど、まだあんまりピンとこない。
“Identity Verified(本人確認)”といった組織名で取得したEV証明書って何やねん。

てことで「セキュリティ研究者から指摘」というリンク先を辿ってみた。

the EV badge takes up valuable screen real estate, can present actively confusing company names in prominent UI, and interferes with Chrome's product direction towards neutral, rather than positive, display for secure connections

引用元:Chromium Docs - EV UI Moving to Page Info
ページ訳より:

EV バッジは画面の貴重な領域を占有し、目立つ UI で紛らわしい会社名を頻繁に表示する可能性があり、安全な接続のためにポジティブではなくニュートラルな表示に向かう Chrome の製品の方向性を妨げます。

うん、まぁ所在地が実在して金さえ払えば、紛らわしい偽カンパニーでもEVバッジ取れるからな。そのことかな。


更にそこから辿ったExternal Researchに答えがあった。

One disadvantage of positive security indicators is that users have to look for them. In actual usage scenarios, security is rarely a user’s primary goal [15].
Anti-phishing tools that provide only neutral or positive information are easier to ignore than phishing warnings [16].
Positive security indicators can also mislead users of a legitimate web site that has been hijacked by an attacker using web vulnerabilities such as cross-site scripting.

引用元(PDF):An evaluation of extended validation and picture-in-picture phishing attacks https://www.adambarth.com/papers/2007/jackson-simon-tan-barth.pdf

Google翻訳より:

肯定的なセキュリティ インジケーターの欠点の 1 つは、ユーザーがそれらを探す必要があることです。 実際の使用シナリオでは、セキュリティがユーザーの主要な目標になることはめったにありません [15]。
中立的または肯定的な情報のみを提供するフィッシング対策ツールは、フィッシング警告よりも無視しやすい [16]。
肯定的なセキュリティ インジケーターは、クロスサイト スクリプティングなどの Web 脆弱性を使用する攻撃者によってハイジャックされた正当な Web サイトのユーザーを誤解させる可能性もあります。

なるほど。つまり「このページは安全だ」と主張することができるグリーンのバッジを逆手にとってユーザーを誤解させ、必要な警戒を解かせてしまうため、肯定的な情報を提供する対策というのは逆効果になりうるということだな。

そして調べると主に2種類の攻撃に弱いということが分かった。
ひとつは紛らわしいドメインを用いるホモグラフ攻撃。google.comであるべきところをgoog1e.comとかそういうやつ。
もうひとつはWebサイトの中にブラウザに見せかけた画像を張り、そこのアドレスバーをグリーンにするピクチャインピクチャ攻撃。
参考:https://www.researchgate.net/figure/Picture-in-picture-attack-Both-the-outer-real-window-and-the-inner-fake-window-are_fig2_220797116

結論

肯定的なセキュリティ表示は悪用されるからやめた。アドレスをよく見て普段から警戒すべき。

以上

Linuxの設定ファイルをデプロイする為のBashスクリプト

Linuxの設定ファイルはviやnanoなどのエディタで簡単に更新できるが、間違えると致命的な障害に繋がるためロールバックできるようにバージョン管理したい。

前回はGitBucketサーバーを建てたという記事を書いたが、実際にやりたかったのはDNS/DHCPの設定管理である。
thom.hateblo.jp

これで一応バージョン管理できるようになったが、BINDもDHCPも複数フォルダに設定が散らばっているので逐一コピーするのは面倒だし手動コピーはミスの元になる。そこで今回は本番からGit作業フォルダへ設定ファイルを取り込んだり、Git作業フォルダからデプロイする為の汎用的なBashスクリプトを書いてみた。

(参考)BINDとISC-DHCPの主要設定ファイルのフォルダ構成

/
├─etc
│  ├─bind
│  │      named.conf
│  │      named.conf.local
│  │      named.conf.options
│  │
│  ├─default
│  │      isc-dhcp-server
│  │
│  └─dhcp
│          dhcpd.conf
│
└─var
    └─cache
        └─bind
                local.thom.jp.zone

差分チェック用スクリプト「.check.sh」

Gitのリポジトリ上に構成したフォルダ構造をベースにLinux実機上の同じファイルと比較を行い差分があれば表示する。

例えばリポジトリ作業フォルダが~/dns_dhcpだとすると、
~/dns_dhcp/etc/bind/name.confと/etc/bind/name.confで差分があれば表示
~/dns_dhcp/etc/bind/name.conf.localと/etc/bind/name.conf.localで差分があれば表示
~/dns_dhcp/etc/bind/name.conf.optionと/etc/bind/name.conf.optionで差分があれば表示
~/dns_dhcp/etc/default/isc-dhcp-serverと/etc/default/isc-dhcp-serverで差分があれば表示
以下略~

という風にフォルダツリー上の全てのファイルを比較する。

コード

#!/bin/bash

while read -r f; do
	str1="${f:0:3}"
	if [ "$str1" != "./." ]; then
		if [ -f $f ]; then
			echo $f
			diff $f ${f#.}
		fi
	fi
done < <(find ./ -mindepth 1)

最初に紹介するので少し詳しめに書く。残り2スクリプトはコピペしてちょっといじくった程度なのでこれがベース。
まず一番ややこしいのはwhile文の構成。
以下を参考にほぼコピペなんだけど、一応どういう処理なのか調べてみた。
programwiz.org


前提として、whileの基本系はこう。

while 条件式
do
     繰り返す内容
done

セミコロンは単に2行を1行にまとめる為である。

while 条件式; do
     繰り返す内容
done

whileにreadとつけて変数を渡すと、リダイレクトされたファイル一覧から順次変数に格納するようなループが作れる。
VBAでいうFor Eachっぽいイメージ。

while read 変数; do
     繰り返す内容
done < ファイル一覧(空白文字や改行区切り)

元のコードではfが変数。

また、Bashでは標準でバックスラッシュがエスケープ記号扱いになってしまうため、readに-rオプションを付けるとそれを防いでくれる。
ここまでの説明を元コードに当てはめるとこうなる。

while read -r f; do
     繰り返す内容
done < ファイル一覧(空白文字や改行区切り)

最後、ファイル一覧を渡す場面ではプロセス置換という手法が使われており、<(コマンド)のように書くとコマンドの実行結果をそのまま参照できる。

つまりfindで現在フォルダ直下(./)を深度最低1、最大無限(指定なし)まで掘り下げてファイル一覧を表示すね処理がfind ./ -mindepth 1なので、これをプロセス置換でwhile read do doneに突っ込んでやると現在フォルダ直下に対してFor Each処理ができるという理屈。

ただ done <(find ./ -mindepth 1)でもうまく動く気がしてて、なんでdone < <(find ./ -mindepth 1)と、リダイレクトが1段階余計に入ってるのかは不明。
参考元サイトがそうしてて、イマイチ理由が分からないけどうまく動いてるのでいじってない。

ここまででwhile文は攻略できた。

while read -r f; do
    繰り返す内容
done < <(find ./ -mindepth 1)

str1="${f:0:3}"では、ファイル名が格納された変数fから先頭3文字を変数str1に格納している。
これはgit管理の.gitフォルダやスクリプト自身をチェック対象に含めないために"./."で始まるパス(つまり隠しファイル・隠しフォルダ)を次のIf文で除外する為の処理。
スクリプト自身が隠しファイルなので実行時は./.check.shとする。"./"は現在ディレクトリの~という意味で、そのあとの"."は隠しファイルのファイル名の接頭辞なのでとてもややこしい。。

if [ -f $f ]; thenは、$fというファイルが存在したら(-f)という意味。つまりディレクトリをチェック対象から除くためのif。

diff $f ${f#.}の部分も少しややこしい。
$fにgit作業フォルダ内のファイルパスが入っているのだが、実行パスを基準に表示されるので、ドットで始まるパスになっている。
例えば./etc/bind/name.confといった感じ。

${f#.}はその変数fから先頭から数えて一番ちかいドットを削除するという処理なので、上記の例だとドットが外れた/etc/bind/name.confとなり、本番の設定ファイル格納パスになる。

つまりdiffコマンドではGit上のパスにあるファイルと本番環境にあるファイルを比較している。

以上、長々となったけど解説終わり。

本番ファイル回収用スクリプト「.collect.sh」

本番機のファイルをGit作業フォルダに回収してくるコード。
Git作業フォルダ内が上書きされるので注意。
これはsudo ./.collect.shとして実行する。※chmod +xで実行権限を足してる場合の話。

コード

#!/bin/bash

while read -r f; do
	str1="${f:0:3}"
	if [ "$str1" != "./." ]; then
		if [ -f $f ]; then
			echo $f
			cp -pf ${f#.} $f
			chown $SUDO_USER:$SUDO_USER $f
		fi
	fi
done < <(find ./ -mindepth 1)

構成はほとんど同じ。
コピーコマンドに-pでパーミッションと所有者とタイムスタンプが保持される。※主にタイムスタンプを保持したかったため。
また、-fを付けると上書きしますかという確認をスキップして強制コピーとなる。
※環境によってはcpがcp -iにエイリアスされてる場合があるらしいのでその場合は先頭にバックスラッシュを付け\cp -fとすればエイリアス無効化された生のcpを実行できるようだ。

また、chownでオーナーをsudo実行ユーザーに変更している。
※このコマンドはsudo実行するので$USERだとrootになってしまう。

デプロイ用スクリプト「.deploy.sh」

これはGit作業ディレクトリから本番の各フォルダへデプロイするためのスクリプト。

コード

#!/bin/bash

while read -r f; do
	str1="${f:0:3}"
	if [ "$str1" != "./." ]; then
		if [ -f $f ]; then
			echo $f
			chown --reference=${f#.} $f
			chmod --reference=${f#.} $f
			cp -up $f ${f#.}
			chown $SUDO_USER:$SUDO_USER $f
		fi
	fi
done < <(find ./ -mindepth 1)

chownに--referenceが付いているが、これは本番ファイル${f#.}を参照に同じオーナーをGitHub作業フォルダのファイル$fに付与するというコマンド。
chmodも同じパーミッションを参照させて付与している。つまりデプロイ前に本番と環境を合わせているという処理である。
そしてcpに-pでタイムスタンプを維持しつつ、-uで更新アリの場合だけ更新するような処理。
タイムスタンプが本番より古い場合は更新されないので安心。

最後にGit作業フォルダ内のファイルオーナーをchowonで実行ユーザーに戻しているが、これは本番環境ファイルはroot所有だったりbind保有だったりするのでGit作業フォルダ内のファイル更新は通常ユーザー権限で更新できるようにするために戻す処理である。



さて、長々と説明が続いてしまったけど、取り急ぎこれで理想的なデプロイ環境が整った。
次回DNS・DHCPがぶっ壊れてもあんし。。。と思ったけどgitbucketへのアクセスがそもそもできなくなるか。。

まぁ少なくとも本番機のデータが飛んでもgitbucketサーバー上にコンフィグは残るので最悪の事態は避けられる。
そこらへんの対策はまた今度考えよう。

以上。

当ブログは、amazon.co.jpを宣伝しリンクすることによってサイトが紹介料を獲得できる手段を提供することを目的に設定されたアフィリエイト宣伝プログラムである、 Amazonアソシエイト・プログラムの参加者です。