write ahead log

ロールフォワード用

goでlifegame書いた

そういや書いたことないな.と思ったので書いた.

github.com

作ってみると中々面白く, 色々なパターンを試してみたくなる.

引き込まれるというのも納得である.

バグってなけりゃいいけど.
(テストとか書いてないし)

こんな感じ

block

glider

ハチの巣

参考

ライフゲーム - Wikipedia

CentOS7でsystemdを使ってgolangで作ったプログラムをデーモン化する

0. 始めに

CentOS7で試します.

UbuntuでUpstartを使った例の延長です.

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

1. プログラムを作る

プログラムは前回と同様のサンプルを使います.

挨拶するだけの単純なものです.

package main

import (
        "net/http"
        "fmt"
)

func main() {
        http.HandleFunc("/", helloHandler)
        http.ListenAndServe(":8080", nil)
}

func helloHandler(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Hello\n")
}

これをhelloというプログラム名でビルドします.

$ go build -o hello

2. Unitファイルを作る(ディレクトリ位置)

CentOS7の場合は下記に作ります. 他のOSも同じかな?調べてませんが.

/etc/systemd/system

実は下記にもUnitファイルがあり, 上記を優先して利用する仕組みだそうです.

/usr/lib/systemd/system

管理者が変更する場合は/etc下へコピーして変更で運用するようです.

3. Unitファイルを作る(作成)

シンプルな例を探して試しました.

これを

/etc/systemd/system/hello.service

として保存します.

;はコメント
#もコメント

[Unit]
# 説明文
Description = Hello Server            

[Service]
# サービス起動時のコマンド
ExecStart = /opt/hello-svr/hello      

# サービス停止コマンド$MAINPIDはメインプロセスのPID参照に利用できる
ExecStop = /bin/kill -HUP $MAINPID    

# サービス再起動コマンド$MAINPIDは上述通り
ExecReload = /bin/kill -HUP $MAINPID && /opt/hello-svr/hello 

# alwaysを指定するとプロセスが死んだ際に常に自動起動する
# デフォルトのnoなら死んだまま
Restart = no                          

# 起動完了の判定条件.
# フォアグラウンドで起動するプログラムはとりあえずsimpleでいい様なので指定.
# forkしてコマンドが終わるタイプはforkingにすればいいらしい
Type = simple                         


[Install]
# 旧来のrunlevelの概念にあたるようです.
# multi-user.target: runlevel:3に相当
# graphical.target: runlevel:5に相当
# 他はman読む方がよさそう
WantedBy = multi-user.target

4. プログラムの配置

当然ですが.

$ sudo cp ~/hello /opt/hello-svr/hello

5. Unitの認識を確認

$ sudo systemctl list-unit-files --type=service | grep hello
hello.service                                 disabled

6. 自動起動をONにする

$ sudo systemctl enable hello

7. サービスを起動する & 確認する

$ sudo systemctl enable hello
Created symlink from /etc/systemd/system/multi-user.target.wants/hello.service to /etc/systemd/system/hello.service.
$ systemctl status hello
● hello.service - Hello Server
   Loaded: loaded (/etc/systemd/system/hello.service; enabled; vendor preset: disabled)
   Active: active (running) since 月 2017-07-17 19:03:03 PDT; 21s ago
 Main PID: 30660 (hello)
   CGroup: /system.slice/hello.service
           └─30660 /opt/hello-svr/hello

8. 動作チェック

$ curl localhost:8080
Hello

9. サービスを再起動する

$ sudo systemctl restart hello

10. サービスを停止する

$ sudo systemctl stop hello

感想

他にも色々出来そうですが, とりあえず今はこれが精一杯.

参考

Systemdを使ってさくっと自作コマンドをサービス化してみる

Systemd入門(4) - serviceタイプUnitの設定ファイル

man systemd.unit の訳

CentOS7にMariaDBを入れる

最初から入ってるかもしれない.

簡単だったけど, やったことなかったしメモ.

1. yumでインストール

入ってたら必要なさそうだけど.

# yum install mariadb mariadb-server

2. エンコーディング指定を変える

UTF8へ.

必要ならどうぞ.

# vi /etc/my.cnf

[mysqld]
....
character-set-server=utf8   #<= 追記

3. systemctlに設定

# systemctl enable mariadb.service
# systemctl start mariadb.service

4. Mariadbの初期セットアップ

# mysql_secure_installation

[Y/n]がたくさん出るけど手抜きの時は基本全部[Enter]
rootパスワードだけは入力した.
解説が親切なので特別心配も要らない.

5. 接続確認

普通にmysqlコマンド使えるんすね.

# mysql -u root -p
Enter password:[rootのパスワード]
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 11
Server version: 5.5.52-MariaDB MariaDB Server

Copyright (c) 2000, 2016, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]>

表示がMariaDBになっててようやく気付くレベル.

互換性意識されててよい.というかまぁ, forkだもんね.

DBマイグレーションツール gooseを使う

データベースのマイグレーションツールで自分に合ったのを探していて, 割といいのを見つけたので使い方をメモしておく.

自分としては

  1. SQLで書ける
  2. 開発言語に依存しない
  3. 開発環境に依存しない
  4. テストデータ投入まで規約がある

を備えているのが欲しかった.

gooseは最後の以外は満たしているのでかなりいい感じ.

インストール

ここは定番で.

$ go get bitbucket.org/liamstask/goose/cmd/goose

ただし, Windowsの場合SQLiteを使うせいかビルドエラーになる.

$ go get bitbucket.org/liamstask/goose/cmd/goose
# bitbucket.org/liamstask/goose/cmd/goose
C:\Go\pkg\tool\windows_amd64\link.exe: running gcc failed: exit status 1
/usr/lib/gcc/x86_64-pc-msys/5.3.0/../../../../x86_64-pc-msys/bin/ld: -lmingwex が見つかりません
/usr/lib/gcc/x86_64-pc-msys/5.3.0/../../../../x86_64-pc-msys/bin/ld: -lmingw32 が見つかりません
/usr/lib/gcc/x86_64-pc-msys/5.3.0/../../../../x86_64-pc-msys/bin/ld: -lmingwex が見つかりません
/usr/lib/gcc/x86_64-pc-msys/5.3.0/../../../../x86_64-pc-msys/bin/ld: -lmingw32 が見つかりません
collect2: エラー: ld はステータス 1 で終了しました

ここで書いた時の現象と一緒だし, たぶんそう.

解決するにはTDM GCCを入れてコマンドプロンプトからgo getを実行しなおせばいい.

(MSYS2だと動作しないので注意.たぶんCygwinもじゃないかなぁ)

設定

何がともあれディレクトリを作ります. 名前はdbでないとダメなようで.(-pathオプションで変えられますが)

$ mkdir db

設定ファイルが必要になるが, 面倒なのでサンプルをコピーしてくる.

$ cd db/
$ cp $GOPATH/src/bitbucket.org/liamstask/goose/db-sample/dbconf.yml ./

後は接続先に合わせて変更する.

サンプルはPostgresだったので, ここではMySQLにしておく.
(mymysqlは誤植ではない, 使うgolangのドライバを明示的に指定している)

development:
    driver: mymysql
    open: [DB名]/[ユーザ名]/[パスワード]

MySQLにログインして, データベースも作っておきましょう.

> CREATE DATABASE demo;

接続確認のために状態確認する.

$ goose status
goose: status for environment 'development'
    Applied At                  Migration
    =======================================

使う

ここまで来るとかなり単純.

というか単純なものが欲しかったんだけど.

テーブルを作る(upする)

マイグレーションファイルを作るには以下のコマンドを使います.

$ goose create [テーブル名] sql

とりあえずUsersテーブルを作ってみる.

$ goose create users sql
goose: created C:\msys64\home\twinbird\dropbox\lab\sample\db\migrations\20170623171909_users.sql

出来たファイルを編集.

$ vi db/migrations/20170623171909_users.sql

こんなのが出来てます.シンプルでいいっすね.

-- +goose Up
-- SQL in section 'Up' is executed when this migration is applied


-- +goose Down
-- SQL section 'Down' is executed when this migration is rolled back

それぞれ編集します.

-- +goose Up
-- SQL in section 'Up' is executed when this migration is applied

CREATE TABLE users(
    id SERIAL,
    name varchar(20),
    email varchar(20)
);

-- +goose Down
-- SQL section 'Down' is executed when this migration is rolled back

DROP TABLE users;

いよいよ, マイグレーションしましょう.

$ goose up
goose: migrating db environment 'development', current version: 0, target: 20170623171909
OK    20170623171909_users.sql

うまくいきました.

戻す(downする)

そのままです.

$ goose down
goose: migrating db environment 'development', current version: 20170623171909, target: 0
OK    20170623171909_users.sql

バージョンを見る(dbversion)

バージョンはタイムスタンプそのままみたいですね.

$ goose dbversion
goose: dbversion 20170623171909

最新バージョンに上げ直す(redo)

過去のコミットまで戻った時は便利そうです.

$ goose redo
goose: migrating db environment 'development', current version: 20170623171909, target: 0
OK    20170623171909_users.sql
goose: migrating db environment 'development', current version: 0, target: 20170623171909
OK    20170623171909_users.sql

感想

自分が求めていたものが大体満たされていて非常に良い感じ.

自作しようかと思っていたけど, 作らなくてよかった.

ドキュメント読むとGo Migrationsってのもあるけど, これは使いそうにないなぁ.

LinuxからWindowsネットワークにアクセスする

要するに, CentOS7からSambaでWindowsネットワークをマウントしたい.

1. とりあえずsambaクライアントを入れる.

# yum install samba-client cifs-utils

2. Firewall許可対象へ追加

# firewall-cmd --permanent --zone=public --add-service=samba

3. 共有フォルダを探してみる

smbclient -L [Windowsホスト名]

4. マウントする

# mount -t cifs -o user=[共有フォルダのマシンのユーザ],password=[共有フォルダのマシンのパスワード] //[サーバIP]/[共有フォルダ] [マウントポイント]

ちなみにパスワード指定が無い場合は以下.

# mount -t cifs -o user=[共有フォルダのマシンのユーザ],password= //[サーバIP]/[共有フォルダ] [マウントポイント]

5. アンマウントする

書くまでもないけど....

# umount [マウントポイント]

CentOS7のKVMにCentOS7(ゲスト)をインストールする

CUIでやります.

0. KVMの設定

過去の記事に譲ります.

1. イメージをダウンロード

ISOファイルが無いと始まらないのでダウンロードします.

CentOS

上記から好きなバージョンを選べばよいかと.

今回はCentOS7で.

# mkdir /var/lib/libvirt/iso
# cd /var/lib/libvirt/iso
# curl http://ftp.iij.ad.jp/pub/linux/centos/7.3.1611/isos/x86_64/CentOS-7-x86_64-DVD-1611.iso > CentOS-7-x86_64-DVD-1611.iso

2. ゲストOS用のディスク領域を作成する

とりあえずqcow2フォーマットのディスクサイズは10Gで.

# cd /var/lib/libvirt/images
# qemu-img create -f qcow2 CentOS-7-x86_64-DVD-1611.iso 10G
Formatting 'CentOS-7-x86_64-DVD-1611.iso', fmt=qcow2 size=10737418240 encryption=off cluster_size=65536 lazy_refcounts=off

3. インストールする

以下のコマンドで.
RAMは1GB, CPUコアは1にした.
長いから忘れそう.

# virt-install \
--name centos7 \
--hvm \
--virt-type kvm \
--ram 1024 \
--vcpus 1 \
--arch x86_64 \
--os-type linux \
--os-variant rhel7 \
--boot hd \
--disk /var/lib/libvirt/images/centos7.qcow2 \
--network network=default \
--graphics none \
--serial pty \
--console pty \
--location /var/lib/libvirt/iso/CentOS-7-x86_64-DVD-1611.iso \
--extra-args "console=tty0 console=ttyS0,115200n8"

上記を実行するとCentOS7のコンソールインストーラが実行されるので画面表示に従って進めていけばいい.

extra-argsを指定しないとコンソール接続できなくなるので注意.

インストール後は画面指示通り Ctrl+] で脱出を.

4. 状態の確認

# virsh list
 Id    名前                         状態
 ----------------------------------------------------
  3     centos7                        実行中

5. ゲストへのコンソール接続

# virsh console centos7

6. ネットワークの設定(再)

が、ここまでやってもゲストからネットワークにつながらない.

ホストに戻って以下を.

# virsh attach-interface --type bridge --source br0 centos7

上記でネットワークインターフェースをホットアタッチできるそうで.

再度コンソール接続するとちゃんとIPが取れてました.

余談

ホストからゲスト上のDHCP割り当てIPを取得する方法がわからないのが辛い.

NAT状態なら以下で取れていたようですが.

# virsh net-dhcp-leases default

まぁ、ブリッジ作るとホストは関係ないともいえるので, 取得する方法はないのかも.

終えて

色んなところではまった.
いい加減まとまった知識を得たい.
良い本でもあればいいんだけど.

参考

仮想マシン構築(KVM)

Libvirt/KVM 管理の VM に NIC を追加 (ホットアタッチ) する

golangで実行中のOSの種類を判別する

簡単だった.ポータビリティがすごい.

package main

import (
    "fmt"
    "runtime"
)

func main() {
    switch runtime.GOOS {
    case "windows":
        fmt.Println("running on Windows.")
    case "darwing":
        fmt.Println("running on Mac OSX.")
    case "linux":
        fmt.Println("running on Linux.")
    case "freebsd":
        fmt.Println("running on BSD.")
    default:
        fmt.Println("running on Other OS.")
    }
}

[実行結果]

$ ./sample.exe
running on Windows.
  • darwin
  • windows
  • freebsd
  • linux

くらいあればとりあえずは事足りる気がする. (調べてないけど, Plan9とかも対応してそうだよね....)

参考

The Go Programming Language - Package runtime