write ahead log

ロールフォワード用

msys2-launcherがすごい便利

msys2ってタスクバーにピン留めできんのかーと思っていたら
twitterでmattnさんが以下の様な事をつぶやいておられました.

探してみるとこりゃ便利そうです.

github - msys2-launcher

入れてみる

pacmanでお手軽に入れられます.

pacman -Sy msys2-launcher

msys64(64bit環境の場合)の配下にmsys2.exeが生成されているのでこれを使えばよいです.
バッチリタスクバーにピン留めできます.

参考

MSYS2 users list

Eclipseでビルド時に"Java heap space"が発生する

Eclipseでビルドするとすぐメモリ不足エラーが発生する.

大体は"GC"とか"heap"とかがメッセージに入る.

(だからロースペックマシンをよく使う私はJavaはあまり使いたくない....)

解決するにはJavaVMをちょっとチューニングとよい.
(メモリがあればの話ではありますが)

eclipse.iniを以下のように変更

~~~~~
中略
~~~~~
--launcher.XXMaxPermSize
1024M # 512Mから変更
~~~~~
中略
~~~~~
-Xms512m #256から変更

これでEclipseを再起動すればそこそこそれっぽく動く.
割り当ての変更だけなので実メモリが小さいと遅くなりますが.

ubuntuでtmuxを使うとlsで色がつかなくなった

現象

ubuntuでtmuxを使うとlsで色がつかなくなった.

なんでだ?と思ったら下記のコマンドでは色がつく.

ls --color=auto

どうも.bashrcが読み込まれていないらしい.(Ubuntuは.bashrcでalias入るので色がつく)
地味に困る.

対処

色々探したらこのサイトの一番下の追記に記載があった.感謝.

.tmux.confに以下を追記.

set-option -g default-shell /bin/bash
set-option -g default-command /bin/bash

bash以外のユーザさんは適宜変えてください.

これで元通り便利になった.

net/httpのhttp.HandlerFuncをラップするテクニック

golangでnet/httpを使うと下記のようなコードを書くことになる.

func main() {
    http.HandleFunc("/foo", fooHandler)
    http.HandleFunc("/bar", barHandler)

    http.ListenAndServe(":8080", nil)
}

ここで全てのハンドラの前に認証を追加したいなどと考えると,各ハンドラ関数に処理を書くのが明らかに無駄だと気づく.

こういう時にはHandlerFuncをwrapするテクニックが一般的なようだ.

func main() {
    http.HandleFunc("/foo", authenticate(fooHandler)) // authenticateでラップする.
    http.HandleFunc("/bar", authenticate(barHandler)) // authenticateでラップする.

    http.ListenAndServe(":8080", nil)
}

func authenticate(fn http.HandlerFunc) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        log.Println("before process") // 処理の前の共通処理
        fn(w, r)
        log.Println("after process") // 処理の後の共通処理
    }
}

シンプルで良い.

catの-(ハイフン)オプションを使う

こんなファイルを用意する.

$ cat > test.txt <<EOS
test
test
test
test
EOS
$ cat > test2.txt <<EOS
test2
test2
test2
test2
EOS

これを普通にパイプでつなぐとパイプで入ってきた入力は無視される.

$ cat test.txt | cat test2.txt
test2
test2
test2
test2

-(ハイフン)を使うとファイルの入力のように扱うことができる.

標準入力を第一引数に指定する感じ.

$ cat test2.txt | cat - test.txt
test2
test2
test2
test2
test
test
test
test

標準入力を第二引数に指定する感じ.

$ cat test2.txt | cat test.txt -
test
test
test
test
test2
test2
test2
test2

ワンライナーとかで便利かも.

opensslを使って鍵の作成・ファイルの暗号化・復号化

opensslを使うと秘密鍵,公開鍵を作ってファイルを暗号化したり,復号化したりできる.

とても面白いのだけど,オプションが多くてややこしいのでメモしておく.

秘密鍵を作る

seckey.pemという名の秘密鍵を作る場合.

$ openssl genrsa -out seckey.pem -aes256 2048
  # 秘密鍵のパスワードとパスワードの確認入力が求められます

公開鍵を作る

seckey.pemという名の秘密鍵を使って,pubkey.pemという名の公開鍵を作る場合.

$ openssl rsa -in seckey.pem -pubout -out pubkey.pem

ファイルを暗号化する

secret.txtを暗号化して,secret.txt.secretを作ってみます.

とりあえずsecret.txtを作ります.

$ cat > secret.txt <<EOS
 this is a
 secret
 text.
EOS

続いて暗号化

$ openssl rsautl -pubin -inkey pubkey.pem -in secret.txt -encrypt -out secret.txt.secret

よくわからない内容のファイルができています.

$ cat secret.txt.secret
K>Fp] 4{^ F'ݿqgs&@ߟ%[jÜ
I50@1{._j?@w"BkAX+'
6>IgޓM=Fv^1v    p+zUޟ/Nؽ{$QR؃І+C
                               0>jB~*

ファイルを復号化する

seckey.pemを使ってsecret.txt.secretを復号化します.

cat secret.txt.secret | openssl

実行結果

$ cat secret.txt.secret | openssl rsautl -decrypt -inkey seckey.pem
Enter pass phrase for seckey.pem:  # 秘密鍵のパスワードを入力
this is a
secret
text.

割と簡単にできるんですね.

golangでファイル・ディレクトリを操作する

ちょっとしたツールを作るのにも, DBを使うのが面倒な時にもファイル操作は便利.

サンプルコードの実行にはosパッケージをインポートしてください. (Printしてるものには当然fmtも)

import (
    "os"
    "path/filepath" //ファイルパス操作の時は
)
ディレクトリを作る
// パーミッション0777でfooを作成
if err := os.Mkdir("foo", 0777); err != nil {
    panic(err)
}
サブディレクトリも作る

サブディレクトリもまとめて作りたい時

// パーミッション0777でhoge/fugaを作成(サブディレクトリもまとめて作る)
if err := os.MkdirAll("hoge/fuga", 0777); err != nil {
    panic(err)
}
ファイル・ディレクトリの名前変更

fooをbarに変更

if err := os.Rename("foo", "bar"); err != nil {
    panic(err)
}
ファイル・ディレクトリの移動

fooの下のtest.txtをbarへ移動.こちらもRenameを使う(どうなんだろう,これ)

if err := os.Rename("foo/test.txt", "bar/test.txt"); err != nil {
    panic(err)
}
ファイル・ディレクトリの権限変更

コマンドのchmodと変わらないですね.

if err := os.Chmod("foo", 0666); err != nil {
    panic(err)
}
ファイル・ディレクトリの削除

下記では中身のあるディレクトリは消せません(rmdirと同じですね)

if err := os.Remove("foo"); err != nil {
    panic(err)
}
ファイル・ディレクトリの削除(中のファイルごと)

これで中身があろうと消せます.

if err := os.RemoveAll("foo"); err != nil {
    panic(err)
}
ファイル・ディレクトリの存在確認

statでエラーが無いかで判断するのが良いようです.

_, err := os.Stat("foo.txt")
if err == nil {
    fmt.Println("あった")
} else {
    fmt.Println("なかった")
}

もうちょっと複雑な操作

ここから先はfilepathもインポートしてください. (Printしてるものには当然fmtも)

import (
    "os"
    "path/filepath"
)
指定ディレクトリ下のファイル・ディレクトリ一覧の取得

filepath.Walkを使います.
これはちょっとややこしいので全部書きます.
walk_funcは匿名関数の方がわかりやすい場合もあるかもしれません.

package main

import (
    "fmt"
    "os"
    "path/filepath"
)

func walk_func(path string, info os.FileInfo, err error) error {
    // ディレクトリか判断
    if info.IsDir() {
        // hoge/foo以下は無視する
        if path == "hoge/foo" {
            // 無視するときはfilepath.SkipDirを戻す
            return filepath.SkipDir
        }
    }
    // パスを印字
    fmt.Println(path)
    // 普通はnilを戻す
    return nil
}

func main() {
    root_dir := "."
    err := filepath.Walk(root_dir, walk_func)

    if err != nil {
        panic(err)
    }
}

実行結果

ディレクトリが荒れててちょっとわかりづらいですが.

twinbird@:~/go/src/file_operate$ ./file_operate 
.
bar
bar/test.txt
blog.txt
file_operate
foo
hoge
sample.go
twinbird@:~/go/src/file_operate$ tree .
.
├── bar
│   └── test.txt
├── blog.txt
├── file_operate
├── foo
├── hoge
│   └── foo
│       └── test2.txt
└── sample.go

ちょっと解説入れると

  • filepath.Walkはディレクトリやファイルが見つかるたびにwalk_funcをコールバックで呼び出すことになります.
  • コールバックのinfoにはファイル情報が入っているので参照できます.
  • コールバックの戻り値にfilepath.SkipDirを使えば,走査中の配下のディレクトリは無視するようです.基本はnilを戻します.

ファイルパスの操作

ファイル操作するときにはファイルパスの操作もセットみたいなもんでしょう.

絶対パスを取得する

filepath.Absを使います.

abs_path, err := filepath.Abs(".")
if err != nil {
    panic(err)
}
fmt.Println(abs_path)

実行結果

/home/twinbird/go/src/file_operate
ファイル名を取得する
base_path := filepath.Base(`C:\Users\IMAI\Desktop\test\a.txt`)
fmt.Println(base_path)

実行結果

a.txt
ファイルパスを連結する
base_path := `C:\Users\IMAI\Desktop\test`
file_path := "a.txt"
joined_path := filepath.Join(base_path, file_path)
fmt.Println(joined_path)

実行結果

C:\Users\IMAI\Desktop\test\a.txt
拡張子を取得する
file_path := "a.txt"
ext := filepath.Ext(file_path)
fmt.Println(ext)

実行結果

.txt