Humanity

Edit the world by your favorite way

しばらく Prolog やってみた感想

ここ最近 Prolog を書いていて、「Prolog はどうせ遅いし Prolog の良さはそこじゃない」がやっと体感的に分かってきた気がします。

今の私なりの解釈で言うと、効率の良いデータ構造とアルゴリズムを考えるのが第一義の場面では Prolog の良さは発揮できないという事です。

Prolog でもデータ構造をちゃんと設計してカット多様すればそれなりに速いプログラムを作れるのかもしれませんが、それは普通に逐次的な(手続き的な)プログラムを書いてるのと同じで*1、それよりもバックトラックでナイーブにルールを総当たりする所が Prolog の強みの一つなんだなというのがようやく実感と共に分かった気がします。

しばらく Prolog やってみた今の私の場合、シンプルに素早く人間の思考に近い形で宣言的に書いたコードがそのまま動いてほしい、って事なら Prolog を選ぶと思います。

こう書くと誇張していて良いことずくめの様に聞こえますが、実際にプログラムを作ってさらに公開するとなるとユーザーの環境に合わせる必要があり、その中で選択肢が段々限られてくるので当てはまるケースは意外と少なくなってきます。

他にも必須ではないものの、

  • ワンバイナリで動くと良い (Go, Rust) とか
  • WindowsGUI を使いたいなら .NET 系が楽とか
  • 様々な目的でユーザーが多い言語のが良いとか
    • コントリビューションを貰いたいとか
    • 仕事だったら人員確保のためとか

ちょっと挙げてみただけでも、公開するとなるとユーザーが介入してくるため色々取捨選択をしたり考える事が結構あり、 まぁ当たり前なんですがプログラミング言語はシンプルに素早く人間の思考に近い形で宣言的に書いたコードがそのまま動くだけでは良くないので、必然的に選べる選択肢は狭まります。

私はプログラミングとは目的を達成するために最適なアルゴリズムとデータ構造を考える事だと思っています(いました)。 しかし Prolog 「らしい」コードはそれをむしろ放棄して、アルゴリズム(手順)の代わりにロジック(論理式)を書き、データ構造の代わりに記号操作とユニフィケーションの対応を考えると自然とプログラムが出来上がります。 どちらが優れているという話ではなく、扱っている抽象度のレベルは明らかに Prolog の方が高い。

前述したように Prolog でも手続き的に書いたり、データ構造をモジュールとして定義して提供する事もできますが、そういう使い方が生きる言語というよりは「計算機に計算させたい」というニーズが一番にあってそれを書き下すと勝手に解いてくれる言語、それが Prolog という言語なんだな、というのが今の所の感想です。

*1:それぞれの目標 (goals) 一つ一つの直前にカットを差し込めば、バックトラックがない単純に上から下へ書いた順に動くコードになります

Let's Encrypt の証明書の有効期限をチェックする Cron 用シェルスクリプト

まぁ certbot-auto renew を定期的に実行すればいいんですが、チェックだけしたいって場合のスクリプト。 Cron で毎日実行する事を想定してます。

追記:切れる前メール通知来るの知りませんでした…

具体例

REPORT_DAYS_AGO はデフォルトで 14 が指定されていますが、実行時に指定した場合、その日数でチェックします。

以下は REPORT_DAYS_AGO=20 として実行した場合の出力です。 example.com の証明書が報告日 (=有効期限の終了日 - REPORT_DAYS_AGO) を迎えているので終了コードは 1 です。

$ sudo REPORT_DAYS_AGO=20 ./check-le-date.sh
========== example.com ==========
有効期限が 2018/09/29 で切れます (残り 20 日)
$ echo $?
1

以下は REPORT_DAYS_AGO=19 として実行した場合の出力です。 まだ報告日を迎えていないので出力はなしで、終了コードは 0 です。

$ sudo REPORT_DAYS_AGO=19 ./check-le-date.sh
$ echo $?
0

スクリプト

趣あふれるスクリプトですが、良かったらどうぞ。

gist.github.com

certbot-auto で ImportError: No module named cryptography.hazmat.bindings.openssl.binding

wget https://dl.eff.org/certbot-auto とかしてダウンロードした certbot-auto スクリプトを実行しようとすると、

ImportError: No module named cryptography.hazmat.bindings.openssl.binding

のようなエラーが出る時がある。

詳細なエラー

$ ./certbot-auto --debug
Requesting to rerun ./certbot-auto with root privileges...
Bootstrapping dependencies for Amazon... (you can skip this with --no-bootstrap)
yum is /usr/bin/yum
yum is hashed (/usr/bin/yum)
Loaded plugins: priorities, update-motd, upgrade-helper
amzn-main                                                                                                                                                                               | 2.1 kB  00:00:00
amzn-updates                                                                                                                                                                            | 2.5 kB  00:00:00
1057 packages excluded due to repository priority protections
Package gcc-4.8.5-1.22.amzn1.noarch already installed and latest version
Package augeas-libs-1.0.0-5.7.amzn1.x86_64 already installed and latest version
Package 1:openssl-1.0.2k-12.110.amzn1.x86_64 already installed and latest version
Package 1:openssl-devel-1.0.2k-12.110.amzn1.x86_64 already installed and latest version
Package libffi-devel-3.0.13-16.5.amzn1.x86_64 already installed and latest version
Package system-rpm-config-9.0.3-42.28.amzn1.noarch already installed and latest version
Package ca-certificates-2017.2.14-65.0.1.17.amzn1.noarch already installed and latest version
Package python27-devel-2.7.14-1.123.amzn1.x86_64 already installed and latest version
Package python27-virtualenv-15.1.0-1.14.amzn1.noarch already installed and latest version
Package python27-tools-2.7.14-1.123.amzn1.x86_64 already installed and latest version
Package python27-pip-9.0.3-1.26.amzn1.noarch already installed and latest version
Package 1:mod_ssl-2.2.34-1.16.amzn1.x86_64 already installed and latest version
Nothing to do
Creating virtual environment...
Installing Python packages...
Installation succeeded.
Traceback (most recent call last):
  File "/opt/eff.org/certbot/venv/bin/letsencrypt", line 7, in <module>
    from certbot.main import main
  File "/opt/eff.org/certbot/venv/local/lib/python2.7/dist-packages/certbot/main.py", line 10, in <module>
    import josepy as jose
  File "/opt/eff.org/certbot/venv/local/lib/python2.7/dist-packages/josepy/__init__.py", line 44, in <module>
    from josepy.interfaces import JSONDeSerializable
  File "/opt/eff.org/certbot/venv/local/lib/python2.7/dist-packages/josepy/interfaces.py", line 8, in <module>
    from josepy import errors, util
  File "/opt/eff.org/certbot/venv/local/lib/python2.7/dist-packages/josepy/util.py", line 4, in <module>
    import OpenSSL
  File "/opt/eff.org/certbot/venv/local/lib/python2.7/dist-packages/OpenSSL/__init__.py", line 8, in <module>
    from OpenSSL import rand, crypto, SSL
  File "/opt/eff.org/certbot/venv/local/lib/python2.7/dist-packages/OpenSSL/rand.py", line 12, in <module>
    from OpenSSL._util import (
  File "/opt/eff.org/certbot/venv/local/lib/python2.7/dist-packages/OpenSSL/_util.py", line 6, in <module>
    from cryptography.hazmat.bindings.openssl.binding import Binding
ImportError: No module named cryptography.hazmat.bindings.openssl.binding

certbot-auto は初回実行時に /opt/eff.org/certbot/ 以下にライブラリをインストールしようとするっぽい(なので mv /opt/eff.org/certbot{,.bak} とかするとまた最初から依存ライブラリをダウンロードしようとする)が、 理由は不明だがなぜか一部のライブラリ (cryptography) がインストールされない時がある。 なので手動でインストールしてやると無事動くようになる。

(念のため事前に sudo 無しで動かして、 /opt/eff.org/certbot/ 以下にインストールされることを確認した)

$ sudo /opt/eff.org/certbot/venv/bin/pip install cryptography

インストール中に赤文字で以下のエラー(警告?)が出たので、念のため zope というライブラリもインストールする。

certbot 0.26.1 requires zope.interface, which is not installed.
certbot-nginx 0.26.1 requires zope.interface, which is not installed.
$ sudo /opt/eff.org/certbot/venv/bin/pip install zope