ねじまきまきまき -Random Note-

やったこと忘れないための雑記

WSL2を使ってみる

やりたいこと

サーバーを直接扱うでもいいんだけど、WSL2(LinuxWIndowsサブシステム)があったなぁって思い出したので、そろそろWindows内に環境を作ってみようという感じ。
遊ぶための環境って意味合いもあるけど、Docker Desktopを使用するためにセットアップが必要だったっていうのが大きい。
デフォルトのubuntuを使用する前提。

インストール用ドキュメント

代替はマイクロソフトのドキュメントを見れば問題なくセットアップは完了する。
Windows Subsystem for Linux に関するドキュメント | Microsoft Docs

WSLとWSL2の違い

違いとしてはここを見ればいい。
WSL 1 と WSL 2 の比較 | Microsoft Docs

WSLインストール

書いてある通り、コマンド1個でインストールまで完了する。
WSL のインストール | Microsoft Docs

sudo時にパスワード不要設定

とりあえず更新とかいろいろやっていくことになるけど、そのためにsudoが必要になってくるけど、わざわざパスワードを打ち込むのも面倒なので、sudoersの設定をやってあげることにする。
sudo時のパスワード入力を省略する【ubunutu/CentOS】 - F27P

更新

インストール直後だとWIndowsセットアップ直後みたいに、いろいろ更新作業が必要になる状態になっているので、手動で更新してあげる。
Windowsみたいに自動更新はないので、手動で更新するか、自動更新を仕込む必要がある。
とはいえ、メンドクサイノデ手動で十分だと思う。
Ubuntu のアップデート方法 - Qiita

日本語化

セットアップ直後は言語設定がデフォルトなので日本語では表示してくれない。
そのままでもいいけど、せっかくなので設定してみる。
WSL2のUbuntu 20.04を日本語化する - Qiita

ssh接続

Windows Terminalで使うだけならそこまで重要じゃないけど、Visual Studio CodeとかTeratermといったものでの接続を想定すると、ssh接続を行うのがよい。
そのための設定を行う。
といってもこの辺りはよくあるいつもの流れ。
WSL2のUbuntuにSSH(公開鍵/秘密鍵)で接続する - Qiita

WSLでsystemctlを使用する場合

WSLではMS製のinitが動いているらしく、systemctlでサービスの管理が行えない。
このままだとsshdをいちいち起動してあげないと使えないといったこともあるので、そのあたりが面倒であればwsl.confを使ったり、代替のsystemctlを入れる必要がある。

wsl.confを使用する場合

wsl.confで起動時にサービスを自動起動する設定が行える。
ただしこれは今のところWindows11でしか使用できないため、Windows10でこの設定を行うことは出来ない。
WSL での詳細設定の構成 | Microsoft Docs

systemctlでサービスの管理を行うためにはこれが詳しい。

wsl.confで制御出来ないのでwslコマンドのオプションで起動時にサービス開始するようにすることもできるが、それはそれでめんどくさいこともあるので、systemd代替のサービスを使用することで解決できる。
Windows 10 or 11 (WSL2)のUbuntuでsystemctlを利用する方法(systemdをPID1で動作させる方法) | Snow System

wslコマンドオプションで自動起動させる

wslコマンドでディストリビューションを起動させるようにすればサービスの起動も行える。

wsl --help
Copyright (c) Microsoft Corporation. All rights reserved.

使用法: wsl.exe [Argument] [Options...] [CommandLine]

Linux バイナリを実行するための引数:

    コマンドラインを指定しない場合、既定のシェルが起動され wsl.exe ます。

    --exec、-e <CommandLine>
        既定の Linux シェルを使用せずに、指定したコマンドを実行します。

    --
        残りのコマンドラインをそのまま渡します。

オプション:
    --cd <Directory>
        指定したディレクトリを現在の作業ディレクトリとして設定します。
        ~ が使用されている場合は、Linux ユーザーのホームパスが使用されます。パスが始まる場合
        文字が含まれている場合は、Linux の絶対パスと解釈されます。
        それ以外の場合、この値は Windows の絶対パスである必要があります。

--分布、-d <Distro>
        指定したディストリビューションを実行します。

    --ユーザー、-u <UserName>
        指定されたユーザーとして実行します。

Windows Subsystem for Linux を管理するための引数:

    --ヘルプ
        使用方法に関する情報を表示します。

    --install [Options]
      追加の Windows Subsystem for Linux ディストリビューションをインストールします。
      有効なディストリビューションの一覧を表示するには、'wsl--list--online' を使用してください。

        オプション:
            --distribution, -d [Argument]
                名前を指定して配布をダウンロードしてインストールします。

                引数:
                   有効なディストリビューション名 (大文字と小文字は区別されません)。

                例:
                    wsl --install -d Ubuntu
                    wsl --install --distribution Debian

    --set-default-version <Version>
         新しいディストリビューションの既定のインストールバージョンを変更します。

    --shutdown
        直ちに、すべての実行中の配布および WSL 2
 軽快なユーティリティの仮想マシンを終了します。

    --status
        Linux の Windows Subsystem の状態を示します。

    --update [Options]
        オプションが指定されていない場合、WSL 2 カーネルは更新され
 、最新バージョンになります。

        オプション:
            --rollback
                以前のバージョンの WSL 2 カーネルに戻します。

Windows Subsystem for Linuxのディストリビューションを管理するための引数:

    --export <Distro> <FileName>
        ディストリビューションを tar ファイルにエクスポートします。
ファイル名には、標準出力として - を使用できます。

    --import <Distro> <InstallLocation> <FileName> [Options]
        指定した tar ファイルを新しいディストリビューションとしてインポートします。
ファイル名には標準入力として - を使用できます。

        オプション:
            --version <Version>
                新しいディストリビューションに使用するバージョンを指定します。

    --list, -l [Options]
        ディストリビューションの一覧を表示します。
        オプション:
            --all

                現在実行中のディストリビューションのみを表示します。
            --quiet, -q
                ディストリビューション名のみを表示します。

            --verbose, -v
                すべてのディストリビューションに関する詳細な情報を表示します。

            --online, -o
                'wsl --install' を使用してインストールするために使用できるディストリビューションの一覧を表示します。

    --set-default, -s <Distro>
       ディストリビューションを既定として設定します。

    --set-version <Distro> <Version>
        指定されたディストリビューションのバージョンを変更します。

    --terminate, -t <Distro>
        指定されたディストリビューションを終了します。

    --unregister <Distro>
        ディストリビューションの登録を解除し、ルートファイルシステムを削除します。

これを利用することになる。
以下はディストリビューション名がUbuntuである場合にsshサービスをディストリビューション起動時に起動させる方法。

wsl -d Ubuntu -- sudo service ssh start

PowerShellでduコマンドっぽいものを作ってみる

やりたいこと

Linux/Unix系でよくあるduコマンドに近いものがWindowsで欲しかった。
クローズ環境で使うので、フリーソフトウェアとかでも気軽に入れられないので、代替として使えそうなものを組んでみる。
たぶん同じようなことをやっている人はいると思う。

duコマンドの出力イメージ

duコマンドは指定されたディレクトリ配下のサイズをはじき出しつつ最後に引数ディレクトリのサイズを出力してくれる。
ということで、イメージとしてはこういうやつを作るっていうことになる。

$ du -h etc
8.0K    etc/kernel/postinst.d
12K     etc/kernel
4.0K    etc/subversion
36K     etc/logrotate.d
4.0K    etc/smartmontools/smartd_warning.d
24K     etc/smartmontools
4.0K    etc/security/namespace.d
4.0K    etc/security/console.perms.d
8.0K    etc/security/limits.d
12K     etc/security/console.apps
~~~中略~~~
52K     etc/dconf/db
68K     etc/dconf
22M     etc

実装のため

PowerShellを使う

PowerShellスクリプト実行を行う時には実行ポリシーの変更が必要だったりするが、それはめんどくさいので、powershell -command -の仕組みを利用して、直接スクリプトを流し込んで実装するようにした。
これを利用すれば設定変更の必要もなくなるので、ぐっと使いやすくなる気がする。

duコマンドとの違い

duとの違いとして、duは標準出力には引数に渡した対象ディレクトリとサブディレクトリのみ出力される。
今回作るものは対象フォルダと直下のサブフォルダ・ファイルはすべて列挙するようにする。

対象の渡し方

ソースにべた書きとか、引数で対象を渡すというオーソドックスな方法もあったのだが、確認したいフォルダは複数あったのと、対象に変動があった時にわざわざソースを修正することや実行用のbatを編集するのは馬鹿らしいと思ったので、入力用のテキストファイルを用いることとした。

結果の出し方

アウトプットは標準出力に出すだけだと後から(どこがどれだけ増えたとか)比較することもできないので、テキストファイルに吐き出すようにした。
その際にファイル名は日付時刻を使用してなるべくユニークになるようにした。

作ったもの

以下に作ったモノたちのコードを並べる。
これらを使用することで、やりたいことができていることは確認できている。

起動用のbatファイル

PowerShellスクリプトファイルを実行するための起動用batファイル
やることはPowerShellスクリプトファイルの呼び出しだけなので、シンプル。
ファイル名は何でもよい。

@(type dirlist.ps1) | powershell -command -

PowerShellスクリプト

実際に仕事をするPowerShellスクリプトファイル。
ファイル名は何でもよいが、batでは「dirlist.ps1」としているので、デフォルトはこれ。
ファイル名を変える場合はbat内の呼び出しファイル名も変えること。

$ErrorActionPreference = "SilentlyContinue"
$RDate = Get-Date -Format "yyyyMMddHHmmss"
$File_Name = $RDate + ".txt"
$DummyPath ="dummypath/"

### list.txtから対象フォルダと直下のフォルダ・ファイルのサイズを取得してファイル出力
### 直下のフォルダ・ファイル処理が終わったら指定されたフォルダサイズも出力(ソートのためにダミー文字を付ける)

### 出力ファイルにヘッダー行を出力
[String]::Format("{0}`t{1}", "Path", "Size") | Out-File $File_Name -Encoding default

### list.txtの行数分繰り返す
foreach ($list in Get-Content "list.txt" -Encoding Default) {
    Write-Output $list
    $j = 0
    $k = 0

    ### サブフォルダの情報を拾う
    foreach ($i in (Get-ChildItem "$list" | ForEach-Object {$_.FullName})) {

        ### パスの最後が\の場合は削除
        ### 削除後にソートするためのダミー文字列を文字列最後にセット
        $ppath = (($i -replace "\\+$", "") -replace "$", "$DummyPath")
        $k = (Get-ChildItem -LiteralPath "$i" -Recurse -Force | Measure-Object Length -Sum).Sum

        ### フォルダ・ファイルサイズが0の場合は出力時に文字列変換する
        if($null -eq $k) {
            ### フォルダ・ファイルサイズが0の場合
            $k = 0
            [string]::Format("{0}`t{1:#,#}", $ppath, [string]$k) | Out-File $File_Name -Encoding default -Append
        }
        else {
            ### フォルダサイズが0じゃない場合
            [string]::Format("{0}`t{1:#,#}", $ppath, $k) | Out-File $File_Name -Encoding default -Append
        }

        ### 編集した出力用パスをクリア
        $ppath = $null

        ### 合計値計算
        $j = $j + $k
    }

    ### パスの最後が\だったら削除
    ### 削除後にソート用ダミー文字列を付与
    $plist = (($list -replace "\\+$", "") -replace "$", "$DummyPath")

    ### list.txtに記載されたフォルダ自体の書き出し
    [string]::Format("{0}`t{1:#,#}", $plist, $j) | Out-File $File_Name -Encoding default -Append
}

### CSV読み取り機能を使って編集
### Path順でソートして出力
$CSVData = Import-Csv -Path $File_Name -Encoding Default -Delimiter "`t"
$CSVData | Sort-Object -Property Path -unique | Export-Csv -Path $File_Name -Encoding Default -NoTypeInformation -Delimiter "`t"


### ファイルを読み込んで、ダミー文字列を削除して出力
$OutData = Get-Content -Encoding Default $File_Name | ForEach-Object {$_ -replace "$DummyPath", ""}
$OutData | Out-File $File_Name -Encoding default

$ErrorActionPreference = "Continue"

使ってみる

テスト用のフォルダ構成

適当な構成としている以下のものでテストを行っている。
マルチバイト文字を含むパス有無とファイルが無いフォルダという環境。

C:.
├─dummy
│      test
│
└─ダミー
    ├─1
    │      test.txt
    │      テスト.txt
    │
    ├─2
    └─3
            test

入力ファイル

ソースを見てもらえればわかる通り、「list.txt」が決め打ちで読み込むファイルとなっている。
そのため、上記のテスト用環境に合わせてこんな感じの入力ファイルを用意した。

C:\tmp\test\dummy
C:\tmp\test\ダミー

batファイルを動かして動作を確認

batファイルのコマンドプロンプトウインドウに実行中の入力ファイル行が表示される。
これは大量データの処理時に、どこを実行しているのかがわからなくなったためにあえて出力するようにしているもので、なくてもいい。

出力結果サンプル

出力結果のテキストファイルは起動用のbatとPowershellスクリプトファイルと同じフォルダに「日付時刻.txt」といったファイル名で出力されるので、それを確認する。
今回はこんな感じのものが出来上がっている。
C:\tmp\test\dummyにはファイルが1ファイルしか存在していないので、それのファイルサイズと合計が出力されている。。
C:\tmp\test\ダミーにはサブフォルダが3つあるので、それぞれのファイルサイズと合計が出力されている。

"Path"	"Size"
"C:\tmp\test\dummy\test"	"3,000,000"
"C:\tmp\test\dummy"	"3,000,000"
"C:\tmp\test\ダミー\1"	"30,000"
"C:\tmp\test\ダミー\2"	"0"
"C:\tmp\test\ダミー\3"	"10,000"
"C:\tmp\test\ダミー"	"40,000"

この辺もっとやりようがある気がするってところ

PowerShellのデフォルトエンコードUTF-8Shift_JISかがバージョンによって変わるので、もしかしたらバグる可能性はある。
duの出力順みたいな感じでソートさせているので、ダミー文字列を使った処理をやっているが、ダミー文字が記号だとソート時に最上段に行ってしまうのでアルファベット文字列としている。
エラーは無視しつつ、階層内のすべてのファイルサイズを合計しているので、実値と違いが出ることはあるはず。

リアコンバーターを買った

買ったもの

使っているカメラはPENTAX K-5なので、PENTAXのHD PENTAX-DA AF REAR CONVERTER 1.4X AWを購入。
www.ricoh-imaging.co.jp

これを使えば、焦点距離が1.4倍になるので、ちょっと伸ばしたいときに使えるかなーって思っている。

そろそろK-3 Mk3あたり買いたい気もするけど、K-5で十分というのもあるので、踏ん切りがつかないところ。
そこで現在主力レンズとして使用しているのが、18-135mmのズームレンズということもあって、もうちょっと望遠が欲しい時に使えるかもしれないということで、リアコンバーターを買おうと思ったのが始まり。

ちなみに、18-270mmのレンズも持っているけど、なかなか重いのもあって主力レンズからは外している。

写真比較

適当に同じ位置から同じ被写体を撮ってみたので、比較してみる。
フォトライフの制限で10MB以上のファイルアップロードは出来ないので、ついでにレベル補正してからファイルサイズを縮小しているので、トリミングやごみ処理などはまったくやっていない。

コンバーター有り


f:id:neji_shiki:20211204093005j:plain
f:id:neji_shiki:20211204093018j:plain
f:id:neji_shiki:20211204093033j:plain
f:id:neji_shiki:20211204093422j:plain
f:id:neji_shiki:20211204093430j:plain

18mm相当と135mm相当に伸ばした時の写真をそれぞれ見比べてみると、焦点距離とともに画角も相応の変化があることがわかる。
とはいえ、135mmの1.4倍だとしても200は行かないので、極端な差は見えにくい。
もうちょっと伸ばしたいということは十分遂げられたので、こんな感じでいいかな。

とりあえず

普段使う用としては、18-270mmを止めた時と同じで、そのままだと重すぎるというのがあるので、常に使うということはないと思う。
まあいい感じに使っていけたらいいかな。

Let’s Encryptのルート証明書変更対応をやった

やったこと

ログをとるのを忘れてたので何もないけど…。
使用しているサーバOS(CentOS7)のパッケージ更新だけ。

気づいた経緯

IRC ProxyのWebクライアントのためにDDNSに登録してドメインを取得しているのだが、DDNSサービス側から一定期間内にIPアドレス通知がないと連絡があった。
DDNSへのIPアドレス通知については、cronに登録したシェルが一定サイクルで動作し続けているため、まずはDDNS側でのサービス変更を疑った。
もちろんそういうわけはなかったので、サーバに入っていろいろ見てみようとしたところ、開始5分で理由が分かったのが今回のこと。
DDNSへのIPアドレス通知URLのプロトコルとしてhttpsを使用していたのだが、これを手動で動かしてみるとSSLサーバ証明書の問題だということが分かった。
使用しているDDNS自体のSSLサーバ証明書がLet's Encryptであるため、これをどうにかしないとどうにもならないということを把握した。

やったこと

ということで、考えられる手段として、以下のものが考えられた。

  1. httpsではなくhttpを使用する
  2. httpsを使用しつつも証明書の検証を行わないようにする
  3. 証明書の問題をちゃんと対応する

この手段の中から、ちゃんと対応することにした。
といっても難しいことは何もなく、パッケージ更新するだけですべて終わった。
ということで更新が何かあるかを確認してみたらいくつかあったので、更新。

yum check-update
yum update

おわり。

携帯電話/スマートフォン遍歴

主旨というほどでもない

思い出せるうちに今までに使ったメイン回線(au)の遍歴をまとめてみる。
他にWillcomとかMVMO回線のもいくつかあったけど、製品名とか思い出せないものもあるので割愛。

今までの遍歴

C5001T(ネイビー)

https://time-space.kddi.com/ketaizukan/2001/4.html
高校を卒業したぐらいに買ったやつ。
たぶん買ったのはネイビー。
携帯電話は高校を卒業するまでは特に必要性を感じなかったからこの時に新規契約した。
後から知ったけど、東芝端末にあったガチャブルとかいう通知がある場合に折り畳みをちょっとでも開けばバイブレーション機能を動かしてくれるっていうのが地味に便利だった。
ポケットとかバッグからわざわざ出さずとも、ケータイを開けば見ないといけないかどうかがわかったのがよかったよね。

INFOBAR(ICHIMATSU)

https://time-space.kddi.com/ketaizukan/2003/8.html
初めて見たときの衝撃は今でも色あせていないとおもうぐらい強烈だった。
とはいえ、C5001Tを買った後のスパンもあったので、たぶん発売開始から1年ぐらいしてから機種変更したんじゃないかと思う。
ボタンは押しやすいし、バッグの中でも邪魔にならないしってことでかなり使い勝手が良かった。

W31T(ソルティホワイト)

https://time-space.kddi.com/ketaizukan/2005/17.html
IFOBARとは違ってフラットデザインのテンキーだけど、方向キー型セレクターがはっきりとした凹凸だったっていうのと、背面ディスプレイが割と大型だったおかげで使いやすかった。
折りたたんだ状態でも薄型というのと、PCサイトビュアーのおかげでネットサーフィンが捗った。

W52SA(フィールブラック)

https://time-space.kddi.com/ketaizukan/2007/20.html
このころ割とあった画面回転系の端末のひとつ。
ワンセグがついてきたけど使った記憶がないのは、まあそんなもんだよね。
操作系はボタンがフラットなのに押しやすい、セレクター周りもボタン操作含めて目で見ずとも操作できたのでスムーズに使えた。
ただひとつだけ、通常の画面方向で折りたたむと本体の角度設定のおかげで若干開きにくかった。
画面を回転させた状態だとそうでもなかった。
丸みを帯びた形状ではなく、シャープな形状ということで、折りたたみ面に指が入りにくかったことが難点だった。
確かこれを使っているころにはてなハイクがオープンしたんだよね。

T001(スターズブラック)

https://time-space.kddi.com/ketaizukan/2009/25.html
ボタン操作系は問題なし、東芝なのでガチャブル機能もあったってことでストレスなく使えた端末。
有機ELディスプレイだったってのははてなハイクで画像を見る機会が増えたこともあり、使いやすい感覚があった気がする。
フルチェン機能についてはつかわなかった。

INFOBAR A01(KURO)

https://time-space.kddi.com/ketaizukan/2011/18.html
INFOBARスマートフォン1機種目。
色はICHIMATSUっぽいっていう理由でKUROにしたけど、物理ボタンが3つしかなかったのでNISHIKIGOIでもよかったかなって思った。
片手で無理なく操作できるサイズ感と物理キーによる操作が行えたことで、スマートフォン1台目としてはよかったのかもしれない。
惜しむらくはデザインに振っているおかげで処理レスポンスが悪くなりやすかったというのが、デザインケータイもといデザインスマホですねって思ったけど、これだけを使っているうちは、こんなもんかって思えていたので不自由はなかった。

INFOBAR A02(AOAO)

https://time-space.kddi.com/ketaizukan/2013/13.html
INFOBAR A01にそこまで不自由さは感じていなかったけど、A02の本体在庫がなくなりかけていたので買ったという若干後ろ向きな購入動機。
A01に対して大きくなったのと、iida UIの餅とかゼリーに例えられる独特な操作アニメーションが好感を持てた。
操作感についてはA01よりも格段に使いやすくなっていたので、問題らしい問題はなかった。
個人的に使用した端末では、バッテリーカバーが取り外せた最後の機種だったわけだけど、正直防水性云々よりもバッテリー交換が容易なほうが嬉しかったりする。※いざとなったら逆のことを言いそうではある。
次の機種への機種変更間際にはふいに電源が落ちる等の不具合っぽい現象も起きていた。

INFOBAR A03(NISHIKIGOI)

https://time-space.kddi.com/ketaizukan/2015/12.html
カラーリングに惹かれないというがっかり感があったので、NISHIKIGOIを購入。
物理ボタンは押し感のないタイプだったけど、A01のデザインに近しいことで使っていて楽しめた。

INFOBAR xv(NISHIKIGOI)

https://time-space.kddi.com/ketaizukan/2018/16.html
クラウドファンディングで資金集めしたことでも話題になったガラホ
(支援したのでコマンド操作で名前出てくる)
だいたいのサイズ感とか初代INFOBARに近くてよかったんだけど、ボタンの押しづらさとかも目立った端末。
なによりブラウザ操作がストレスいっぱいだったのは辛かった。
とはいえ必要十分な「携帯電話」としては、こんなものだよねっていう感じも強かった。

AQUOS sense5G SHG03(ブラック)

https://time-space.kddi.com/ketaizukan/2021/1.html
INFOBAR xvのバッテリーがいきなり落ちるようになってきたので、買い換えた。
5Gになったけど、そこまでの恩恵はまだ感じていない。
基本的にスマホじゃゲームをやらないので、高スペックは求めないけど、動作も機敏でストレスはほぼ感じない。
ただ不思議なことに、たまにバイブレーションが動作しなくなる気がしているが、再起動すれば解決するのでとりあえずはしのいでいる。

certbotコマンドのオプション指定について

cetbot用cron設定見直し

cronの設定値

現在の設定内容は以前も書いたが以下のような感じ。

certbotコマンドが正常終了となったらstone再起動用のbashを起動している。

00 00 01  \*  \* sudo /usr/bin/certbot renew && /Local/stone_run.bash 1>/dev/null 2>&1 &

ただし、わざわざ&&でコマンドをつなげることをせずともオプションとかを使用すれば、再起動できるっぽい。

certbotコマンドの再考

usageはこんな感じ。

$ certbot --help renew
usage: 

  certbot renew [--cert-name CERTNAME] [options]

optional arguments:
  -h, --help            show this help message and exit
  -c CONFIG_FILE, --config CONFIG_FILE
                        path to config file (default: /etc/letsencrypt/cli.ini
                        and ~/.config/letsencrypt/cli.ini)

renew:
  The 'renew' subcommand will attempt to renew all certificates (or more
  precisely, certificate lineages) you have previously obtained if they are
  close to expiry, and print a summary of the results. By default, 'renew'
  will reuse the options used to create obtain or most recently successfully
  renew each certificate lineage. You can try it with `--dry-run` first. For
  more fine-grained control, you can renew individual lineages with the
  `certonly` subcommand. Hooks are available to run commands before and
  after renewal; see https://certbot.eff.org/docs/using.html#renewal for
  more information on these.

  --cert-name CERTNAME  Certificate name to apply. This name is used by
                        Certbot for housekeeping and in file paths; it doesn't
                        affect the content of the certificate itself. To see
                        certificate names, run 'certbot certificates'. When
                        creating a new certificate, specifies the new
                        certificate's name. (default: the first provided
                        domain or the name of an existing certificate on your
                        system for the same domains)
  --dry-run             Perform a test run of the client, obtaining test
                        (invalid) certificates but not saving them to disk.
                        This can currently only be used with the 'certonly'
                        and 'renew' subcommands. Note: Although --dry-run
                        tries to avoid making any persistent changes on a
                        system, it is not completely side-effect free: if used
                        with webserver authenticator plugins like apache and
                        nginx, it makes and then reverts temporary config
                        changes in order to obtain test certificates, and
                        reloads webservers to deploy and then roll back those
                        changes. It also calls --pre-hook and --post-hook
                        commands if they are defined because they may be
                        necessary to accurately simulate renewal. --deploy-
                        hook commands are not called. (default: False)
  --force-renewal, --renew-by-default
                        If a certificate already exists for the requested
                        domains, renew it now, regardless of whether it is
                        near expiry. (Often --keep-until-expiring is more
                        appropriate). Also implies --expand. (default: False)
  --allow-subset-of-names
                        When performing domain validation, do not consider it
                        a failure if authorizations can not be obtained for a
                        strict subset of the requested domains. This may be
                        useful for allowing renewals for multiple domains to
                        succeed even if some domains no longer point at this
                        system. This option cannot be used with --csr.
                        (default: False)
  -q, --quiet           Silence all output except errors. Useful for
                        automation via cron. Implies --non-interactive.
                        (default: False)
  --preferred-chain PREFERRED_CHAIN
                        If the CA offers multiple certificate chains, prefer
                        the chain with an issuer matching this Subject Common
                        Name. If no match, the default offered chain will be
                        used. (default: None)
  --preferred-challenges PREF_CHALLS
                        A sorted, comma delimited list of the preferred
                        challenge to use during authorization with the most
                        preferred challenge listed first (Eg, "dns" or
                        "http,dns"). Not all plugins support all challenges.
                        See https://certbot.eff.org/docs/using.html#plugins
                        for details. ACME Challenges are versioned, but if you
                        pick "http" rather than "http-01", Certbot will select
                        the latest version automatically. (default: [])
  --pre-hook PRE_HOOK   Command to be run in a shell before obtaining any
                        certificates. Intended primarily for renewal, where it
                        can be used to temporarily shut down a webserver that
                        might conflict with the standalone plugin. This will
                        only be called if a certificate is actually to be
                        obtained/renewed. When renewing several certificates
                        that have identical pre-hooks, only the first will be
                        executed. (default: None)
  --post-hook POST_HOOK
                        Command to be run in a shell after attempting to
                        obtain/renew certificates. Can be used to deploy
                        renewed certificates, or to restart any servers that
                        were stopped by --pre-hook. This is only run if an
                        attempt was made to obtain/renew a certificate. If
                        multiple renewed certificates have identical post-
                        hooks, only one will be run. (default: None)
  --deploy-hook DEPLOY_HOOK
                        Command to be run in a shell once for each
                        successfully issued certificate. For this command, the
                        shell variable $RENEWED_LINEAGE will point to the
                        config live subdirectory (for example,
                        "/etc/letsencrypt/live/example.com") containing the
                        new certificates and keys; the shell variable
                        $RENEWED_DOMAINS will contain a space-delimited list
                        of renewed certificate domains (for example,
                        "example.com www.example.com" (default: None)
  --disable-hook-validation
                        Ordinarily the commands specified for --pre-hook
                        /--post-hook/--deploy-hook will be checked for
                        validity, to see if the programs being run are in the
                        $PATH, so that mistakes can be caught early, even when
                        the hooks aren't being run just yet. The validation is
                        rather simplistic and fails if you use more advanced
                        shell constructs, so you can use this switch to
                        disable it. (default: False)
  --no-directory-hooks  Disable running executables found in Certbot's hook
                        directories during renewal. (default: False)
  --disable-renew-updates
                        Disable automatic updates to your server configuration
                        that would otherwise be done by the selected installer
                        plugin, and triggered when the user executes "certbot
                        renew", regardless of if the certificate is renewed.
                        This setting does not apply to important TLS
                        configuration updates. (default: False)
  --no-autorenew        Disable auto renewal of certificates. (default: True)

これを見ると、cronなどで自動実行する場合はquietオプションを推奨されている。

また、pre-hook/post-hook/deploy-hookの各オプションでcertbot動作前後や証明書更新が行われた場合のみの処理も行うことが可能っぽい。

このhookオプションは/etc/letsencrypt/renewal-hooks配下にファイルを置くことでも代替できるようなので、用途を考えるとオプションよりもディレクトリにファイルを置いたほうがいいのかもしれない。

新しいcron用コマンド

上記の考察から、quietオプションとpost-hookオプションを使用するとこうなる。

sudo /usr/bin/certbot renew --quiet --post-hook /Local/stone_run.bash

stoneの起動シェルの変更

stone用の起動シェルについてもこのタイミングでいろいろ見直しを行った。

というのも、一度/etc/letsencrypt/renewal-hooks配下にシンボリックリンクを作成する想定で動作を見ていた時に不具合が発生することがわかったためだ。

以下が修正後の起動シェルになる。

例のごとく、シェルと同ディレクトリにあるstone.+confファイルの数だけ処理を繰り返すというところは変わらない。

変わったのはBASE_DIR変数の取得方法で、dirnameに直接$0を渡すのを止め、realpathコマンドをかます形になっている。

これはシンボリックリンクを動作させた場合、$0に設定されるのはシンボリックリンクのパスなので、シェルファイル自体のパスを取得するための変更となっている。

ちなみにreadlinkではなくrealpathとしているのは、この方法ではreadlinkが想定した動作をしてくれなかったためとなる。

readlinkコマンドを使って$(dirname $(readlink -e $0))みたいなことをやってみたところ、どうもうまく動作しなかったので、ワンラインで動作できたrealpathコマンドで代替した感じ。

#!/bin/bash -l

#BASE_DIR=`dirname $0`
BASE_DIR=`dirname $(realpath $0)`
cd ${BASE_DIR}

## Kill
if [ `ps -ef | egrep "stone.+conf" | egrep -v "grep|sudo|bash" | wc -l` -ne 0 ]; then
        for stone_proc in `ps -ef| egrep "stone.+conf" | egrep -v "grep|sudo|bash" | awk '{print $2}'`
        do
                sudo kill -9 ${stone_proc}
        done
fi

sleep 10

## Start
while true
do
        for target_conf in `ls stone*.conf`
        do
                        if [ `ps -ef | egrep ${target_conf} | egrep -v "grep|sudo|bash" | wc -l` -eq 0 ]; then
                                        nohup sudo /usr/local/bin/stone -C ${BASE_DIR}/${target_conf} 1>/dev/null 2>&1 &
                        fi
        done

        if [ `ps -ef | egrep "stone.+conf" | egrep -v "grep|sudo|bash" | wc -l` -eq `ls stone*.conf | wc -l` ]; then
                break
        else
                sleep 10
        fi
done

exit 0

動作検証

検証というほどでもないが、これがうまく動くことを確認するため、quietオプションを外して、dry-runオプションを付けた状態で動かしてみる。

$sudo /usr/bin/certbot renew --dry-run --post-hook /Local/stone_run.bash
Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/example.com.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cert not due for renewal, but simulating renewal for dry run
Plugins selected: Authenticator standalone, Installer None
Starting new HTTPS connection (1): acme-staging-v02.api.letsencrypt.org
Simulating renewal of an existing certificate for example.com
Performing the following challenges:
http-01 challenge for example.com
Waiting for verification...
Cleaning up challenges

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
new certificate deployed without reload, fullchain is
/etc/letsencrypt/live/example.com/fullchain.pem
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations, all simulated renewals succeeded: 
  /etc/letsencrypt/live/example.com/fullchain.pem (success)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Running post-hook command: /Local/stone_run.bash

予定通りの結果が得られたので、これでいいこととする。