common lisp で何か書いてみる(その2)

どうも。
最近の投稿ペースが速くて自分でも驚きながら書いています。

さて、引き続き caveman2 で何か書いてみようという話です。
が、今回もまた自前のコードを入力する機会は訪れませんでした…

とりあえず目次は以下の通りです。

  • Road to qlot:quickload
  • 穴居人が立ち上がる時

■Road to qlot:quickload

結論:行ってみた限りでは全部行き止まりでした。

や、色々試したんですよ、ホントに。

qlfile の中身を次のようにして、それぞれコメントアウトしながら全部試しました。

# qlfile

github caveman2 fukamachi/caveman
# git caveman2 https://github.com/fukamachi/caveman.git
# ql caveman2 :latest

インストールコマンドも色々やってみました。

  • プロジェクトディレクトリで
    • (qlot:install :myproj1)
    • (qlot:install)
    • (qlot:install :caveman2)
  • プロジェクトディレクトリの一つ上で
    • (qlot:install :myproj1)
    • (qlot:install)
    • (qlot:install :caveman2)

見付けた変数を変えてみたりもしました。

(setq ql-setup:*quicklisp-home* #P"~/myproj1/")
(qlot:quickload :caveman2)

上の色々な組み合わせも試しました。

最終的に挫折しました…(泣)

■穴居人が立ち上がる時

で、qlot を使わずに caveman2 だけでも動かしてみようと試行錯誤して、こちらは何とかサーバを立ち上げる事ができました。

前回で (ql:quickload :caveman2) は通るようになったので、github の README を読みながら進めていきます。

最初のプロジェクト作成は caveman2:make-project で問題無く終了です。

続いて、とりあえずテスト稼動が目的なので、ルーティングとかデータベース操作とかはどんどん飛ばして、サーバの立ち上げに入るわけです。

書いてある通り、おもむろに (myproj1:start :port 8080) を実行… 当然パッケージ myproj1 が無いと怒られます。
そして毎度の如く、苦闘の日々が始まるのです。

まあ、状況としては windows ユーザに linux の bash プロンプト使わせるようなものですね。
やりたい事は分かってるのに、どうやればいいのか分からないというジレンマに陥るわけです。

最終的に動くようになるまで

  • ファイルパスの指定方法
  • 読み込ませるファイル選択

で悩む事になりました。

パスの指定方法は make-project の引数にあったので、それでいけるはずです。
が、カレントディレクトリが何処なのかとか、うっかり #P を付けずに文字列で書いてしまったりとかで、なかなかうまく行きませんでした。

さらに、読み込むファイルが分からないという点が問題の複雑さに拍車をかけることになります。

コマンドの方は load か require あたりだろうと推測しましたが、ファイルに関しては見当もつかなかったので、考えていても仕方無いと割り切って総当たりして解答に辿り着きました。

誰かの役に立つかどうか怪しいところですが、いちおう最終形を載せておきます。

(ql:quickload :caveman2)
(caveman2:make-project #P"~/myproj1/" :author "myname") ; '#P' を付けないとエラー、ディレクトリは未作成でもよい

(load #P"~/myproj1/myproj1.asd") ; これと次は '#P' 無しでも動いたが、一応付けておく
(load #P"~/myproj1/app.lisp")
(myproj1:start :port 8080)

以上です。

VirtualBox のホストオンリーネットワークアダプタで困った件

ここ数日、いろいろ躓いてばかりな気がしますが、今度は VirtualBox のお話です。

毎回だらだらと長い文章になってしまうので、簡潔に書いてみます。

問題:ホストオンリーアダプタのネットワークでホストマシンだけ接続できない
結論:以前の設定が悪さをしてる場合があるので、未使用のサブネットアドレスを割り当ててみると改善される事がある

以上… では説明不足ですよね、はい。

まず VirtualBox の仮想マシンでホストオンリーネットワークアダプタを使っていました。
それで、ホストマシン(VirtualBox 自体を実行してる方ですね)をスリープしてから復帰すると、ホストだけが該当のネットワークで通信できない状態になっていました。
その間もゲストマシン(仮想マシンの方です)同士では問題無く通信できていました。

このような状況でも、最近までは仮想マシンを利用しての開発が無かったので特に問題ありませんでした。
ところが、ここ数日で やれDockerだ common lisp だと仮想マシンを使い倒すようになったため、この接続不良による再起動の嵐が非常に面倒になりました。

同じ問題で悩んでいる人がいるかと思い google 先生に検索してもらって幾つか事例を見て回ったのですが、現象が微妙に違っていたり、書いてある通りに試してみても効き目が無かったりと、うまくいきませんでした。
しかも、途中から「コントロールパネルのネットワークアダプタを無効にするとアイコンが消える」という新たな問題も発生したのです。

その後紆余曲折があり、最終的にはクリーンな状態になるよう

  1. 今あるホストオンリーアダプタを全部削除
  2. 再起動
  3. 今のバージョン(Ver 5.0.x)をアンインストール
  4. 再起動
  5. 以前のバージョン(ver 4.3.x)をインストール
  6. 再起動
  7. ホストオンリーアダプタを新規追加
  8. 再起動
  9. 仮想マシンのネットワークアダプタを新しいのに変更

という作業をして、接続を試しました。
ところがやっぱり駄目で、途方に暮れかけた時にゲスト側に不自然な点を発見したのです。
この時は VirtualBox の設定で DHCP サーバを OFF にしてあったのですが、何故かゲストが DHCP で IP アドレスを取得していました。
不思議に思って別のサブネットに変更してみたところ、それが大当りだったらしく嘘のように素直に仮想マシンと通信できるようになったのです。

それまでに散々いじったので、最後のサブネット変更が決定打だと言い切ることはできませんが、これが最も有力だと思います。
思い返してみると、確かに以前ホストオンリーアダプタを作成したまま virtualbox をアンインストールしたことがありました。
その後に新バージョンを入れ直した時にも、何故かインストール直後にアダプタが有り、気になった覚えもあります。

このような点から、最初に書いた結論が導きだされた次第です。
この記事が解決事例の一つとして、どなたかの参考になればいいなと思います。

common lisp で何か書いてみる(その1)

いつもの如く、唐突に common lisp の勉強をしようと思い立ち、色々見ながら環境設定をしたのでメモ。

思い付きで行動したので、あちこちで袋小路に突き当たりまくっているのは相変らずである。

■alpine linux で環境設定してみた

始まる前から後のことを考え、docker コンテナで動かすと面白そうということで virtualbox で新しく VM を作って alpine linux をインストールした。
debian とか ubuntu と違って、ISO 起動でインストーラが走ってくれるわけではなくて、Wiki を見ながら何とか導入。
パッケージは sbcl と clisp があったから「apk add」で簡単に入った。
ちなみに何度も「apt install」と入力してしまったのはご愛嬌。

問題はここからで、common lisp のパッケージ管理ライブラリ quicklisp を入れてみたが動かない。
ライブラリ自体の読み込みはできるけれど、そこから他のライブラリの自動ロードをするとデバッグモードになってしまう。
しばらく格闘してみたが、このまま環境設定で時間を食ってもアレなので、alpine は放置することにした。

■debian GNU/Linux で環境設定してみた

というわけで、愛用の debian GNU/Linux の VM を立ち上げて、こっちで環境設定してみた。
慣れ親しんだ「apt-get install」で、あっと言う間に sbcl のインストールが完了。
cl-quicklisp というパッケージもあったので、それも入れた。

で、プロジェクトごとにパッケージ管理をしてくれる(ruby の bundler みたいな) qlot というのを入れてみた。
これもすんなりと入ったので「よーし、これでコードが書けるぜー」とか思いながら、web フレームワークの caveman2 を入れ「ようとし」てみた。
…入ったよ、うん、結果的には。それだけで 1時間かかったのを気にしなければ。

その経緯

  1. qlot が初期化できない
    qlot が入った。ql:quickload でロードした。qlfile 書いた。
    さあ (qlot:install :myproj) …あれ?
    エラーした。
    qlfile を空にしてみてもエラーした。
    ライブラリ取得先を ql から git に変えてみてもエラーした。
    …よし、一旦放置。

  2. ql:quickload で caveman2 をロードできない
    さすがに直接 ql:quickload すれば動くだろう… あれ?
    エラーした。パッケージ名の書き方間違ったっけ?
    文字列で “caveman2” … エラー。
    キーワード形式で :caveman2 … エラー。
    クォートして ‘caveman2 … エラー。

    …落ち着け、キーボードは投げるもんじゃない。
    近場には HHK2Lite(英語) は売ってないんだ。
    それに買ったばかりのディスプレイに当たったらどうする。
    とりあえずお茶でも飲んで落ち着くんだ。

    (30分経過)…ふぅ、今日の茶菓子は美味かった。
    お、よく見たらエラーファイル名あるじゃん。cffi?
    とりあえず「apt-cache search」して… cl-cffi …って、そのまんまかい!
    駄目元でインストールっと。これで直ったら微妙だなぁ…
    (ql:quickload :caveman2) Enter!
    え、通るの?原因これだけ?私の30分を返せ!(←責任転嫁:嫁居ないけど)

  3. 改めて qlot
    んー、これなら qlot も動きそうな気がする。
    (qlot:install :myproj) っと。ん、エラー?
    …落ち着け、深呼吸だ。吸ってー、吐いてー、吐いてー、吐…けるかボケェ!吸わんと死ぬわ!
    ……やめよう、一人ボケツッコミは寂しすぎる…

    そうだ、さっきと同じくダイイングメッセージにヒントがあるに違いない。エラーでプロセス死んでるしな。
    死体は語る、犯人は現場に戻る(違)
    えーと…

    error while parsing arguments to DESTRUCTURING-BIND:
    invalid number of elements in
    ("caveman2:latest")」

    …待て、google 翻訳に頼るんじゃない。たぶん翻訳しても、そんなに変わらんし。
    一つずつ順番に行こう。

    • エラー
    • ↓している間
    • 解釈
    • 引数
    • ↓のため
    • DESTRUCTURING-BIND
    • (区切り)
    • 不正な
    • ↓の
    • 要素
    • ↓の中の
    • “caveman2:latest”

    まとめると
    「DESTRUCTURING-BIND のため(に)引数(を)解釈している間(に)エラー」
    「”caveman2:latest” の中の要素の数(が)不正」
    …ん?「caveman2:latest」って qlfile の書き間違い?
    あー、うん。たしかに違うわ。スペース必要なのね。

    よーし、これで動くはず。今日のおやつを賭けてもいい。
    (qlot:install :myproj) …エラー?え、おやつ抜き?えぇっ?
    くそぅ、この恨み晴らさでおくべきか。(←自業自得)
    二度ある事は三度あるのであるからしてヒントはエラーメッセージにあるのである。
    というわけでチェック!
    Component "myproj" not found
    うん、myproj は見付からないよね、今から作ろうと思ってるんだから。
    ……… もしかして :myproj の部分いらない?
    (qlot:install) っと… あー、うん。動いたね。動いちゃったね。
    私のおやつ返せ!(←再度の責任転嫁:もちろん嫁は居ない)

補足:没収されたおやつはスタッフ(= 私)がおいしくいただきました。

VirtualBox に CentOS 6.7 を入れた後で NAT にした時の設定

例によって忘れた時用のメモです。

タイトル通りなんですが、VirtualBox で CentOS 6.7 を使った時に困った話です。
状況としては下のようになります。

  1. ネットワーク設定で最初に NAT以外(ホストオンリー等)のネットワークアダプタを選んだ
  2. そのアダプタを後から NAT にした

この場合、VM を起動しても NAT からインターネットへのアクセスができません。
とりあえず下のように設定したら NAT を通って外へ出られました。

  • /etc/sysconfig/network ファイル
    • GATEWAY の行をコメントアウト(先頭に「#」を追加)する
  • /etc/sysconfig/network-scripts/ifcfg-eth0 を下の内容にする(NIC の数によっては eth0 の「0」を別の数字に読み替えます)
    DEVICE=eth0
    ONBOOT=yes
    BOOTPROTO=dhcp

ちなみに、NAT が動いた時の IP が「10.0.5.15」で、デフォルトルートは「10.0.5.2」でした。
このパラメータを利用して手動設定ができるかもしれません。どなたか試したら教えてください。

今回は短い(当社比)ですが、以上です。