write ahead log

ロールフォワード用

ubuntu16.04でキーボード設定がおかしくなる(日本語が入力できない)

Ubuntuに久々に戻したところ,キーボード入力がおかしくて1hほど無駄にしてしまった。

ちょっとググると以下のコマンドで対処可能という情報がよく流れてくる.

sudo dpkg-reconfigure keyboard-configuration

実際, 上記でもきちんと入力できるようになる.が,私の環境の場合(Let's Note CF-N9)ログアウトして 再度ログインするとまたキーマップがおかしくなる.

結局下記で対応した. Ibus(mozc)使ってる状況だからだったのかもしれない.

sudo vi /usr/share/ibus/component/mozc.xml

上記の15行目と18行目あたりにlayoutが定義される箇所があるので, ここをjaからjpに変更した.

今のところ問題も特にない.

何度か挫折しつつ不純lispインタプリタを作った

作りました.

github.com

詳細はgithubのREADMEをどうぞ.(酷い英語ですが)

当初は純lispを作ろうと思ったのでpureという名前ですが, tak関数を動かしたいなど欲が出てきたので 純粋でも何でもなくなってます.

GCはありますが, マクロはありません.
(私がマクロをちゃんと理解してないので)

作成時の参考文献は一番下に記載するので興味のある方はご覧ください.

以下は駄文です.

作り始めたきっかけ

以前から何か言語処理系を作ってみたいなと思っていました.
Brainf*ckはともかく, 作ったことがなかったので.

それとは全く別に私は今27才で, 25,27,32というのは個人的に特別な節目になる年齢じゃないかと感じていました.

SIerにいると年齢と共にプログラミングする機会が減っていくのでなんとなく腕試ししたくなる事がよくあります.

「プログラマを名乗るならここら辺で小さくてバグだらけでも良いので言語処理系を作っておきたいな」という事で着手してみました.

何から始めたものか

とはいえ何から始めたらよいのかという事でとりあえずググって色々調べてみました.
が, イマイチピンときません.

ここら辺で割と心が折れます.

本やOSSのコードを写経する事を試みる

とりあえず何かを真似したいという事でOSSやコードの載っている本を買って写経する事を試みました.

lispとかなら割とサンプルも多かったので調べるといくつか出てきます.

が, これもまたイマイチピンときません.

作ってる感がないというか, あんまり頭に入ってこなかったんですよね.

わかったよーな, わからんよーな.

rebuildを聞く

弱ったなーという事で気分転換にrebuild.fmを聞く事にしました. この時まで聞いたことなかったんですが, 以前Cコンパイラ作る記事を見たことがあるruiさんが出るという事でタイミング的にもいいし聞いてみようかなと.

この回だったかな?

(そういえばこの後Matzさんも出てますね.たまたまですが時期がよかった)

トークの中で東大のCPU実験の話がありましたが,その文脈でruiさんから出た
「やってみればいいじゃないですか?」的な一言がとても心に残りました.

細かい文脈などは忘れてしまったんですが,それだけが心に残っています.

やってみる

「まぁ,そりゃそうだな」という事で参考文献ばかり漁らずにやってみることにしました.
とりあえず小さく始めることがベストという事で極小のlisp定義を漁ります.

するとwikipediaで以下を見つけました.

純LISP

「あぁ,こいつならなんとかなるかも」という事でターゲットをこれに絞ります.

1st try

Lispならまぁ大体

  • Readで読んでS式にして
  • Evalで実行し
  • Printで実行結果のS式を文字列にする

という3工程だろうと考えました.

あとはデータ構造ですが,これはLispなら大変わかりやすいので(アトムとペアしかない)何となくこの2つを作ればうまくいくだろうということで着手します.

これで8末くらいから初めて9月末くらいでReadして何かしらEvalしてPrintというところまでこぎつけました.(car, cdrとかは動いた)

が,変数スコープなどを足そうとすると一気に難しくなります.

このあたりで既存コードで作り続けるのは辛いなという事で一度挫折しました.

2nd try

ならもう作り直せばいいわ.という事でゼロからもう一度作り始める事にしました.

1度作ってるだけあってリトライは割とうまくいき, 9月末から始めて10月中頃には終える事が出来ました.日数だと8日かな.

実装を終えて

勉強になったというよりはかなり面白かったというのが正直なところです.
勉強がどうとかいうと聞こえはいいですが,結局面白いのが一番だというのが個人的な結論でしょうか. あとはちょっとでもやり続ける事も割と大事でした. 子供もいるのでなかなか時間が作れないのですが, 仕事の休憩中とか5分でも,その5分で1機能作れたりしましたし.

  • やってみればいい
  • 面白ければ何とかなる
  • 1日5分でいいので続ける

あとはあのタイミングでrebuild.fmを聞かなければおそらく挫折していたと思います. ruiさんとmiyagawaさんにはここでひっそりと感謝を.

参考文献

参考サイトが多すぎるので最早覚えてないのですがブラウザのブックマークに残っているものを並べておきます.

純LISP - wikipedia

  • 間違えなく一番参照回数が多い
  • この記事を見なかったらたぶん作ってない
  • あんまり助かったので初めてwikipediaに寄付しました

rui314/minilisp

  • ruiさんによるlisp実装
  • 機能おおすぎ凄い(macroまであるっぽい)
  • コードきれいだしすごい
  • 困って頭抱えた時に参照した.
  • なので似たコードがちょいちょいあると思う(evalListとか名前一緒)

MiSPLi

  • jsで実装されているlisp
  • かなり良く出来ていてカッコイイ
  • たまにlispの一般的な挙動を確認したいときに使いました

Common Lisp で作る micro Scheme

  • 作り方というよりLISP自体に関する解説がわかりやすかった

ガベージコレクションの実装法と評価

  • どこかの大学の資料(どこなんだろ?確認してないですすんません)
  • GC作る時に役立った

Rubyソースコード完全解説 - 第5章 ガ-ベージコレクション

  • GC作る時にとても役立った
  • 実は以前に一度読んでいたので読みやすかった
  • ありがとう, ありがとう

竹内関数 - wikipedia

  • これを動かせるようにしないと終わらない(気がした)

Windowsのコマンドラインでクリップボードにコピーする

パソコン初心者みたいだけど、知らなかったのでメモっとく.

Windowsのコマンドプロンプトではclipコマンドというものがあって、クリップボードにコマンド結果などをコピーできる.

date /T | clip

貼り付け結果:

2016/10/15 

echoでちょっとしたものを出したり.

echo "hello" | clip

貼り付け結果:

"hello" 

テキストファイルの内容もコピペが簡単

clip < sample.txt

貼り付け結果:

テキストの中身だよ

こりゃ地味に便利

windows10でgit cloneが失敗する

ずっとUbuntuだったのをWindows10に変えたのでファイアウォールではまってしまった.

msys2のgitでgithubからcloneを行うと以下のメッセージが出た.

fatal: unable to access 'https://github.com/twinbird/xl.git/': Couldn't resolve host 'github.com'

なんぞ.ネットワークおかしくなったか?と思ったんだけどファイアウォールが原因だった.

ということでファイアウォールにgitは問題ないアプリだと追加してやる.

追加手順

まず、コントロールパネルからwindowsファイアウォールを開く.

左上の「windowsファイアウォールを介したアプリまたは機能を許可」をクリック

右下の「別のアプリの許可」をクリック

ここの「参照」で

C:\msys64\usr\bin\git.exe

を追加してやればちゃんと動きました.

システム起動時にUNEXPECTED INCONSISTENCYエラーが発生した時の対処

サーバを再起動すると, 見たくないものを見てしまった.

Checking filesystems

/12: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.
            (i.e., without -a or -p options)

            *** An error occurred during the file system check.
            *** Dropping you to a shell; the system will reboot
            *** when you leave the shell.
            Give root password for maintenance
            (or type Control-D to continue):

人間とは困ったもので, こういう時にはじめてバックアップの不確実さに気づくのだ.

なんとかする

何がともあれメッセージ通りに従うことにする.

メッセージによるとファイルシステムのサイズが物理デバイスのブロックと一致していないらしい.

(※結果的に今回はLVMボリューム割り当て変更時のミスだった.もしその他の理由でブロックサイズが一致していなければハード故障の可能性があるので最善の対処は別かもしれない.)

/dev/mapper/VolGroup-lv_home: The filesystem size (according to the superblock) is 2621440 blocks  
The physical size of the device is 2500608 blocks  
Either the superblock or the partition table is likely to be corrupt!

/dev/mapper/VolGroup-lv_home: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.
(i.e., without -a or -p options)
                                [FAILED]

            *** An error occurred during the file system check.
            *** Dropping you to a shell; the system will reboot
            *** when you leave the shell.
            Give root password for maintenance
            (or type Control-D to continue):

上記画面でrootのパスワードを入力する.

Give root password for maintenance
(or type Control-D to continue): [パスワードを入力]

するとrootでログインできる.

(Repair filesystem) 1# 

/etc/fstabを見ると対象のファイルシステムがわかるので確認しておく.

# cat /etc/fstab
[]
/dev/mapper/VolGroup-lv_home   /home     ext4    defaults    1    2
[]

メッセージの指示通り, fsckをかける.

# fsck -t ext4 /dev/mapper/VolGroup-lv_home

すると以下のメッセージが出てくる.
ビビりながらnを入力する.

fsck from util-linux-ng 2.17.2
e2fsck 1.41.12 (17-May-2010)
The filesystem size (according to the superblock) is 2621440 blocks
The physical size of the device is 2500608 blocks
Either the superblock or the partition table is likely to be corrupt!
Abort<y>? [nを入力]

色々出るが, Yで. 以下のようなメッセージが出ると思う.

/12: 107499/2560864 files (1.5% non-contiguous), 83124/2621440 blocks

とりあえずこれで次のステップへ進める.

ファイルシステムの認識と物理ブロックが異なるということだったので,ファイルシステムの認識を是正する.

# resize2fs /dev/mapper/VolGroup-lv_home 2500608 [<= サイズは上記のphysicalに合わせる]

最後にもう一度fsckをかける.fをつけるとcleanな状況でも強制的にかけるらしい.

# fsck -f /dev/maper/VolGroup-lv_home 

締めにリブートする

# reboot

上記まででとりあえずブートできた.

ただ,すぐバックアップを取らないと悲惨なことになるので....

参考

vpsget ディスクイメージを縮小する システム起動時にUNEXPECTED INCONSISTENCYエラーが発生した場合は

golangでプログラムをデーモン化する(ように見せる)

golang標準ではデーモンを作れないという話を聞いたことがありましたが,
デーモン化対応は続いているみたいです.

さて、困った.標準でやりたかったなー.と思っていたのですが,とりあえず作成したプログラム単体でできるように以下の方法を取りました.

  1. os.Args[0]で自身のファイルパスを得る
  2. exec.Command.Start()で外部プログラムとして実行する

ざっくり以下のようになります.

if デーモン化する == true {
    cmd := exec.Command(os.Args[0], "--server")
    cmd.Start()
    return
}
if --serverオプションが指定されていた == true {
    デーモン実行するときに行う処理
}

終了する時にプロセスIDを探してkillしないとならないのがちょっと面倒ですが
要件によってはこれで十分かと思います.

以下は大変参考になりました.ありがたい.

「ほい、これ」ってファイルを渡せる Hoi というツールをつくった

上記のプログラムのgithub


2017/04/27 追記

まともにデーモン化する方法も書いた.

UbuntuでUpstartを使ってプログラムをデーモン化する

golangでWindows10上でSQLite3を使う

golangでSQLite3を使う情報は多いのだけれど,
Windowsで使うとなると一気に情報が減ってしまう.

事前準備

ちょっと面倒ですが,まずはgccが必要です.
以下からダウンロードします.

tdm-gcc

msys2なんかでよく使うMinGWではダメっぽいです.
(msys2使ってるので良い方法があるなら知りたいです)

ライブラリ作者のmattnさんもgolangのビルドにはmsys2使ってないっぽいですね.
github - issues -

そういうわけでcmd.exeでgo getします.

C:\Users\Twinbird>go get github.com/mattn/go-sqlite3

これで準備はOKです.

サンプルコード

見た方が早いですね.

package main

import (
    "os"
    "database/sql"
    _ "github.com/mattn/go-sqlite3"
)

func main() {
    dbfile := "./test.db"

    os.Remove(dbfile)

    db, err := sql.Open("sqlite3", dbfile)
    if err != nil { panic(err) }

    // 単発で実行
    _, err = db.Exec(`CREATE TABLE "messages" ("id" INTEGER PRIMARY KEY AUTOINCREMENT, "msg" VARCHAR(255))`)
    if err != nil { panic(err) }

    // 単発で実行
    _, err = db.Exec(`
      INSERT INTO "messages" ("msg") VALUES(?)`,
        "こんにちは",
    )
    if err != nil { panic(err) }

    // プリペアステートメント
    stmt, err := db.Prepare(`INSERT INTO "messages" ("msg") VALUES(?)`)
    if err != nil { panic(err) }

    if _, err = stmt.Exec("世界"); err != nil { panic(err) }
    if _, err = stmt.Exec("Hello"); err != nil { panic(err) }
    if _, err = stmt.Exec("World"); err != nil { panic(err) }

    stmt.Close()

    db.Close()
}

ビルド

これもcmd.exeでやりましょう.

C:\Users\Twinbird\samples>go build

実行と確認

実行はmsys2環境でもできます.

SQLiteで確認してみましょう.

SQLite version 3.10.0 2016-01-06 11:01:07
Enter ".help" for usage hints.
sqlite> .tables
messages
sqlite> select * from messages;
1|こんにちは
2|世界
3|Hello
4|World

うまくいきました.