2016年12月3日土曜日

gentooでsystemd-nspawnやってみた

gentooでsystemd-nspawnしてみた


ここのところずっとSolaris Zoneばかりを触っていて、Linux系コンテナから離れていたのですが
最近、systemd-nspawnなるものを知ってしまい、どんなものかと触ってみた。

CentOS7をsystemd-nspawnで動かしてみる


gentooのカーネルは、bridge系、cgroups系、btrfs系はあらかじめ入れたカーネルで起動しておく、この辺はハショリマス

rpmのインストール


luaとcapsを入れておく
ugui7 ~ # USE="lua caps" emerge app-arch/rpm
でbtrfs
ugui7 ~ # emerge sys-fs/btrfs-progs

yumのインストール

ugui7 ~ # emerge sys-apps/yum
ホストOSのyumのディレクトリにCentOS-Base.repoを設置する、適当なCentOSから持ってきても動くはず

* /etc/yum/repos.d/CentOS-Base.repo
# CentOS-Base.repo
#
# The mirror system uses the connecting IP address of the client and the
# update status of each mirror to pick mirrors that are updated to and
# geographically close to the client.  You should use this for CentOS updates
# unless you are manually picking other mirrors.
#
# If the mirrorlist= does not work for you, as a fall back you can try the
# remarked out baseurl= line instead.
#
#

[base]
name=CentOS-$releasever - Base
mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=os&infra=$infra
#baseurl=http://mirror.centos.org/centos/$releasever/os/$basearch/
gpgcheck=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7

#released updates
[updates]
name=CentOS-$releasever - Updates
mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=updates&infra=$infra
#baseurl=http://mirror.centos.org/centos/$releasever/updates/$basearch/
gpgcheck=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7

#additional packages that may be useful
[extras]
name=CentOS-$releasever - Extras
mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=extras&infra=$infra
#baseurl=http://mirror.centos.org/centos/$releasever/extras/$basearch/
gpgcheck=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7

#additional packages that extend functionality of existing packages
[centosplus]
name=CentOS-$releasever - Plus
mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=centosplus&infra=$infra
#baseurl=http://mirror.centos.org/centos/$releasever/centosplus/$basearch/
gpgcheck=0
enabled=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7

yumがpython2系でしか動かないので切り替える
ugui7 ~ # eselect python set 1
ugui7 ~ # eselect python list
Available Python interpreters:
  [1]   python2.7 *
  [2]   python3.4
ugui7 ~ #

CentOS7のインストール


btrfsでsubvolumeを作成、あってるかどうかはわからない
ugui7 ~ # btrfs subvolume create /var/lib/machines/centos7
Create subvolume '/var/lib/machines/centos7'
ugui7 ~ #

subvolumeへcentos7をインストール

ugui7 ~ # yum -y --releasever=7 --nogpg --installroot=/var/lib/machines/centos7 --disablerepo='*' --enablerepo=base install systemd yum passwd emacs-nox iputils iproute NetworkManager

...
...
 sqlite                         x86_64   3.7.17-8.el7        base    393 k
  systemd-libs                  x86_64   219-19.el7          base    356 k
  trousers                      x86_64   0.3.13-1.el7        base    289 k
  tzdata                        noarch   2015g-1.el7         base    431 k
  ustr                          x86_64   1.0.4-16.el7        base     92 k
  util-linux                    x86_64   2.23.2-26.el7       base    1.9 M
  xz                            x86_64   5.1.2-12alpha.el7   base    200 k
  xz-libs                       x86_64   5.1.2-12alpha.el7   base    102 k
  yum-metadata-parser           x86_64   1.1.4-10.el7        base     28 k
  yum-plugin-fastestmirror      noarch   1.1.31-34.el7       base     30 k
  zlib                          x86_64   1.2.7-15.el7        base     89 k

トランザクションの要約
==========================================================================
インストール  5 パッケージ (+159 個の依存関係のパッケージ)
  
合計容量: 108 M
総ダウンロード容量: 91 M
インストール済み容量: 446 M
Downloading packages:
(1/139): emacs-common-24.3-18.el7.x86_64.rpm                                              |  20 MB     00:02
(2/139): emacs-filesystem-24.3-18.el7.noarch.rpm                                          |  58 kB     00:00
(3/139): emacs-nox-24.3-18.el7.x86_64.rpm                                                 | 2.4 MB     00:01
(4/139): expat-2.1.0-8.el7.x86_64.rpm                                                     |  80 kB     00:00
(5/139): file-libs-5.11-31.el7.x86_64.rpm                                                 | 339 kB     00:00
(6/139): filesystem-3.2-20.el7.x86_64.rpm                                                 | 1.0 MB     00:00
(7/139): findutils-4.5.11-5.el7.x86_64.rpm                                                | 559 kB     00:00
(8/139): gawk-4.0.2-4.el7.x86_64.rpm                                                      | 873 kB     00:00
(9/139): gdbm-1.10-8.el7.x86_64.rpm                                                       |  70 kB     00:00
(10/139): glib2-2.42.2-5.el7.x86_64.rpm                                                   | 2.2 MB     00:01
(11/139): glibc-2.17-105.el7.x86_64.rp (35%) 63% [==================           ] 844 kB/s | 2.3 MB     00:01 ETA
...
...
  shared-mime-info.x86_64 0:1.1-9.el7    sqlite.x86_64 0:3.7.17-8.el7    systemd-libs.x86_64 0:219-19.el7
  trousers.x86_64 0:0.3.13-1.el7    tzdata.noarch 0:2015g-1.el7    ustr.x86_64 0:1.0.4-16.el7
  util-linux.x86_64 0:2.23.2-26.el7    xz.x86_64 0:5.1.2-12alpha.el7    xz-libs.x86_64 0:5.1.2-12alpha.el7
  yum-metadata-parser.x86_64 0:1.1.4-10.el7  yum-plugin-fastestmirror.noarch 0:1.1.31-34.el7  zlib.x86_64 0:1.2.7-15.el7

完了しました!
ugui7 ~ # 

passwdの設定


rootのパスワードを設定する
ugui7 ~ # systemd-nspawn -D /var/lib/machines/centos7

# passwd root
....
machinectl loginで入れない場合は以下の設定でpts/0を追記する
guest $ echo "pts/0" >> /etc/securetty

コンテナを起動


コンテナを起動してログインしてみる、やっぱカーネルはgentoo、なんかウケる、「Ctrl + ]」の3連発でコンテナから脱出できる
ugui7 ~ # machinectl start centos7
ugui7 ~ # machinectl login centos7
Connected to machine centos7. Press ^] three times within 1s to exit session.

CentOS Linux 7 (Core)
Kernel 4.4.26-gentoo on an x86_64

centos7 login:

ネットワークの設定がよくわかってない


gentooの設定がよくわからなかった、bridgeで固定IPを設定したが設定の仕方が違う感じがする、だれか標準的なやり方教えて...

* /usr/lib64/systemd/network/80-container-ve.network

「Address=...」をコメントアウト
#  This file is part of systemd.
#
#  systemd is free software; you can redistribute it and/or modify it
#  under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation; either version 2.1 of the License, or
#  (at your option) any later version.

[Match]
Name=ve-*
Driver=veth

[Network]
# Default to using a /28 prefix, giving up to 13 addresses per container.
# Address=0.0.0.0/28
LinkLocalAddressing=yes
DHCPServer=yes
IPMasquerade=yes
コンテナをstartして、vethをbridgeへaddifする
ugui7 ~ # brctl addif br0 ve-centos7
ゲストの中に入ってhost0を確認するとIPがついてる...DHCPになっているけどよくわからん
-bash-4.2# ip a
1: lo:  mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: host0@if5:  mtu 1500 qdisc noqueue state UP qlen 1000
    link/ether xx:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 192.168.0.111/24 brd 192.168.0.255 scope global dynamic host0
       valid_lft 86402sec preferred_lft 86402sec
    inet6 xxxx::xxxx:vvvv:xxxx:xxxx/xx scope link
       valid_lft forever preferred_lft forever
-bash-4.2#

btrfsをつかってクローンしてみる


まず止める、いいかどうかは不明
ugui7 ~ # machinectl poweroff centos7
btrfsのcloneでコンテナをファイルシステムましcloneする
ugui7 ~ # machinectl clone centos7 centos7-c
ugui7 ~ # btrfs sub list /var/lib/machines/
ID 261 gen 1102 top level 5 path srv
ID 262 gen 10687 top level 5 path var/lib/machines
ID 291 gen 10687 top level 262 path centos7
ID 292 gen 10688 top level 291 path centos7/var/lib/machines
ID 293 gen 10688 top level 262 path centos7-c
ID 294 gen 10688 top level 293 path centos7-c/var/lib/machines
ugui7 ~ #
ugui7 ~ # machinectl start centos7
ugui7 ~ # machinectl start centos7-c
ugui7 ~ # machinectl list
MACHINE   CLASS     SERVICE
centos7   container nspawn
centos7-c container nspawn

2 machines listed.
ugui7 ~ #
Linux系のコンテナまわりの違いが、わからない... LXCとかぶるんだけど、勉強し直しか、まぁでも簡単に入れられるので、gentoo 万歳

2016年11月6日日曜日

calimakvoで一人ウツボfesやってきた

久しぶりの海


今日は結構荒れてた


ナガヤで買った170円のゴマサバで戦ってきたが、ウツボオンパレードで、たまんない。


不甲斐なさにちょっと「マジで釣りをやってやろうか」って感じになってきた。

あした、イシグロいって道具揃えようかと思っている

gentoo遣い が釣りやると「こうなる」てきな、資料を晒してやろうと思う...


今日は、ゴマサバぐらいくれてやる、手が生くセェー

ワロス....


2016年7月9日土曜日

filelockをSolarisへ

Solarisにfilelockライブラリを移植する


で、何でこうなったかですが、もともとhaskellのfilelockパッケージがflock関数を内部で利用していたことが事の発端で、Solaris上でbuildするとエラーになる。



...
...
In file included from dist/build/System/FileLock/Internal/Flock_hsc_make.c:1:0:
Flock.hsc: In function 'main':
Flock.hsc:57:16: error: 'LOCK_SH' undeclared (first use in this function)
/usr/gnu/lib/ghc-7.10.3/template-hsc.h:35:10: note: in definition of macro 'hsc_const'
     if ((x) < 0)                                      \
          ^
Flock.hsc:57:16: note: each undeclared identifier is reported only once for each function it appears in
/usr/gnu/lib/ghc-7.10.3/template-hsc.h:35:10: note: in definition of macro 'hsc_const'
     if ((x) < 0)                                      \
          ^
Flock.hsc:58:16: error: 'LOCK_EX' undeclared (first use in this function)
/usr/gnu/lib/ghc-7.10.3/template-hsc.h:35:10: note: in definition of macro 'hsc_const'
     if ((x) < 0)                                      \
          ^
Flock.hsc:61:16: error: 'LOCK_NB' undeclared (first use in this function)
/usr/gnu/lib/ghc-7.10.3/template-hsc.h:35:10: note: in definition of macro 'hsc_const'
     if ((x) < 0)                                      \
          ^
...
...

いつも、忘れたころにやってくる

実際のコードを確認してみる


抜粋しますと
...
flock :: Fd -> Bool -> Bool -> IO Bool
flock (Fd fd) exclusive block = do
  r <- c_flock fd $ modeOp .|. blockOp
  if r == 0
    then return True -- success
    else do
      errno <- getErrno
      case () of
        _ | errno == eWOULDBLOCK
            -> return False -- already taken
          | errno == eINTR
            -> flock (Fd fd) exclusive block
          | otherwise -> throwErrno "flock"
  where
    modeOp = case exclusive of
      False -> #{const LOCK_SH}
      True -> #{const LOCK_EX}
    blockOp = case block of
      True -> 0
      False -> #{const LOCK_NB}
...

動作としては、modeOpで「共有ロック」か「排他ロック」を、blockOpが「LOCK_NB」フラグを追加するかどうかで、「LOCK_NB」が指定されない場合はブロックする可能性があるので「eINTR」に対応していて、その場合は再度ロックが取得できるまで繰り返し、「LOCK_NB」が指定された場合、ロックが取れなかったら素直にIO Falseを返す仕組みになっています。ここを、Solarisで動かしたいって言うことです。

Solarisで動かす


とりあえず全部のコードはgithubにあげて置きますの確認してくださいと言う事で...
https://github.com/calimakvo/filelock.git

flock構造体
Cで定義されているflock構造体をhaskell内で利用するため対応する型をdataで定義する
data CFLock = CFLock {
  l_type   :: !CInt,
  l_whence :: !CInt,
  l_start  :: !COff,
  l_len    :: !COff,
  l_pid    :: !CPid
} deriving(Eq, Ord, Show)

この定義だけでは使えませんので、Storableクラスのインスタンスに登録する、こうすることでghcがCFlock型とflock構造体を相互に変換することが可能になります。
instance Storable CFLock where
  sizeOf x = sizeOf (l_type x)
             + sizeOf (l_whence x)
             + sizeOf (l_start x)
             + sizeOf (l_len x)
             + sizeOf (l_pid x)
  alignment _ = alignment (undefined :: COff)
  peek ptr = CFLock <$> #{peek struct flock, l_type} ptr
                   <*> #{peek struct flock, l_whence} ptr
                   <*> #{peek struct flock, l_start} ptr
                   <*> #{peek struct flock, l_len} ptr
                   <*> #{peek struct flock, l_pid} ptr
  poke ptr (CFLock t w s l p) = do
      #{poke struct flock, l_type} ptr t'
      #{poke struct flock, l_whence} ptr w'
      #{poke struct flock, l_start} ptr s'
      #{poke struct flock, l_len} ptr l'
      #{poke struct flock, l_pid} ptr p'
    where
      t' = fromIntegral t :: CInt
      w' = fromIntegral w :: CInt
      s' = fromIntegral s :: COff
      l' = fromIntegral l :: COff
      p' = fromIntegral p :: CPid

flock関数を置き換える
書き換えた部分だけの抜粋ですが、「EINTR」は「blockOp = True」、「F_SETLKW」で呼んだときに受け取る可能性があるので注意するのと、「exclusive = False」の場合に「F_RDLCK」で呼ばれるので、openFd関数のOpenModeを「WriteRead」にする必要があること(処理を排他するためならちょっと微妙に感じるけど...)。
flock :: Fd -> Bool -> Bool -> IO Bool
flock (Fd fd) exclusive block = do
  flck <- new modeOp
  r <- c_fcntl fd blockOp flck
  if r /= -1
    then return True -- success
    else do
      errno <- getErrno
      case () of
        _ | (errno == Errno #{const EAGAIN} ||
             errno == Errno #{const EACCES})
            -> return False -- already taken
          |  errno == Errno #{const EINTR}
            -> flock (Fd fd) exclusive block
          | otherwise -> throwErrno $ "fcntl(" ++ show(errno) ++ ")"
  where
    modeOp = case exclusive of
      False -> CFLock #{const F_RDLCK} #{const SEEK_SET} 0 0 0
      True -> CFLock #{const F_WRLCK} #{const SEEK_SET} 0 0 0
    blockOp = case block of
      True -> #{const F_SETLKW}
      False -> #{const F_SETLK} -- #{const LOCK_NB}

foreign import ccall "fcntl.h fcntl"
  c_fcntl :: CInt -> CInt -> (Ptr CFLock) -> IO CInt

補足
fcntl関数のプロトタイプ宣言を見ると引数が可変長引数になっています。
int fcntl(int fd, int cmd, ... /* arg */ );

可変長引数をhaskellで表現するのは難しいと思ったので、第3引数がflock構造体を取得する関数に固定化して作ってあります。上手いやり方が見つかりませんでした、方法があったら教えてください。


ついでにhsc拡張子について


このコードはFFI(Foreign Function Interface)といってhaskellのコードから通常のCの関数を呼び出す仕組みになっているため、ちょっと変換が必要。
hsc2hsコマンドを使って普通のhsコードに変換できる、こんな感じ
cuomo@karky7 ~ $ hsc2hs Flock.hsc
ってやるとFlock.hsを作ってくれる、こうすると{#const LOCK_NB}とかが展開されてghciとかでloadできるようになるよ。


ちょっとまて、これがあったじゃないか


いろいろ調べて見たのですが、こういう奴もありました
Prelude> :m +System.Posix.IO
Prelude System.Posix.IO> :m +System.IO
Prelude System.Posix.IO System.IO> :m +System.Posix.Files
Prelude System.Posix.IO System.IO System.Posix.Files>:t setLock
setLock :: System.Posix.Types.Fd -> FileLock -> IO ()
Prelude System.Posix.IO System.IO System.Posix.Files> fd <- openFd "/tmp/lock" ReadWrite (Just stdFileMode) defaultFileFlags
Prelude System.Posix.IO System.IO System.Posix.Files> setLock fd (WriteLock, AbsoluteSeek, 0, 0)
Prelude System.Posix.IO System.IO System.Posix.Files>

こういうのもありです。

ただFFIでやってみたかっただけです、では


2016年7月6日水曜日

もう夏ですよ、年々弱ってます

最近、強風の大室山が綺麗でした


強風で晴天だった大室山を見にいきましたぁ...


 気分良く暑さにもまけ、いつものように飲みましたぁ...


 足元も緑で、虫も一杯です、ムヒバンザァーイ


トドメに、激辛ラーメン10合目でやられました... 屁が痛いです


2016年7月5日火曜日

で、fcntl関数

あの時のflock関数からfcntl関数へ


flock関数が使われているコードをSolarisにそのまま移植する場合は「fcntl関数」を使うようになる。Posix的にはfcntl関数が推奨されているのでこれからファイルロックを書きたいのならfcntl関数で書く方がいいかもね。




fcntl関数


file controlという関数でファイルディスクリプタへ対していろいろな属性や制御を設定できる関数、今回はファイルのロックに関する利用方法だけに絞って確認しています。
詳しい関数の説明はmanページを見てくださいということでサンプルはgithubへ置きましたのでcloneしてmakeしてください。

https://github.com/calimakvo/fcntl.git

cuomo@karky7 ~/fcntl $ tree
.
├── Makefile
├── README.md
├── fcntl_r.c
└── fcntl_rw.c

fcntl関数もアドバイザリロック


これはflock関数と同じです

fcntl関数をファイルロックで使う


fcntl関数とflock関数の大きな違いは、ロック対象のファイルの特定の領域をバイト単位でロックが設定できるところが違います。そのためロック領域を指定するflock構造体が定義されています。

Linuxだとこれ
struct flock
  {
      short int l_type;   /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK.  */
      short int l_whence; /* Where `l_start' is relative to (like `lseek').  */
#ifndef __USE_FILE_OFFSET64
      __off_t l_start;    /* Offset where the lock begins.  */
      __off_t l_len;      /* Size of the locked area; zero means until EOF.  */
#else
      __off64_t l_start;  /* Offset where the lock begins.  */
      __off64_t l_len;    /* Size of the locked area; zero means until EOF.  */
#endif
      __pid_t l_pid;      /* Process holding the lock.  */
  };


Solarisだとこれ
/* regular version, for both small and large file compilation environment */
typedef struct flock {
        short   l_type;
        short   l_whence;
        off_t   l_start;
        off_t   l_len;          /* len == 0 means until end of file */
        int     l_sysid;
        pid_t   l_pid;
        long    l_pad[4];               /* reserve area */
} flock_t;


l_typeメンバにはF_RDLCK(READロック)、F_WRLCK(書込ロック)、F_UNLCK(ロック解除)が指定できます。l_whenceはl_startで指定される位置がファイルのどこなのかを指定するフラグ、SEEK_SET(l_startで指定された位置から)、SEEK_CUR(現在位置)、 SEEK_END(ファイルの終わり)で指定可能です。flock関数のようにファイル全体をロックするなら、l_len = 0でEOFまでロックとして

    ...
    struct flock region;
    region.l_type = F_RDLCK;
    region.l_whence = SEEK_SET;
    region.l_start = 0;   /* ファイル全体をロック */
    region.l_len = 0;     /* l_len = 0でEOFまで指定 */
    ...
    fcntl(lockfd, F_SETLK, &region);
    ...

のような感じになります、これでflock関数と同じになります。

flock関数fcntl関数の挙動の違い


flock関数は「LOCK_NB」フラグを指定しなければロックの取得ができない時点でブロックしましたがfcntl関数は基本的にブロックしない事が特徴です、この時errnoに「EAGEIN」か「EACCES」(処理系に依存)をセットしますのでその場合は再度呼び出してやる必要があります。Posixで移植性を高めるのに両方のエラーを処理できるように書いた方が望ましいそうです。

F_SETLKWを使う


ディフォルトのflock関数と同じような動作にしたい場合は「F_SETLKW」をfcntl関数の呼び出しで指定する。
...
res = fcntl(lockfd, F_SETLKW, &region);
...

「F_SETLKW」フラグはロックが取得できなかった場合、ロックの取得ができるまでブロックするような動きになります、flock関数のディフォルトの動作(「LOCK_NB」を指定しない)と同じになります。

fcntl関数とsignal


ロックの取得ができない場合はfcntl関数呼び出しでブロックするため、「EINTR」(シグナル割込)に備える必要があります。
「fcntl_rw」がブロックする状況を作って別ターミナルから「SIGUSR1」シグナルを送ると「EINTR」で戻ります。
cuomo@karky7 ~ $ kill -USR1 7348

cuomo@karky7 ~/fcntl $ ./fcntl_rw
Get EINTR
Retry lock...
...

ちょっとした注意点


ファイルのオープンの時に、「O_RDONLY」フラグでオープンした際に。fcntl関数へ「F_WRLCK」を指定して呼び出したりすると、「Bad file descriptor」を返してくるのでダメな組み合わせで利用しないようにして下さい。当たり前って言えばそのとおりデスが。

fcntl関数とNFS


勉強不足によって不明、時間がとれたら調べようと思います、すみません。

今後...


やっと「Solaris来たじゃん」って言われそうですが、やっぱりいろんなOSで走るように書くのって難しいのねって感じますね、そもそもfcntl関数の使い方がちょっと違うような気もしますが...でほんとはこの問題の元ネタはhaskellのライブラリがもとでして、そこへつながってしまいます...


汚いコードですみません...


2016年7月3日日曜日

flock関数について調べてみた

いきなりステーキとflock関数


「いきなりステーキ」で、300gのステーキをモリンと食って、ビールをしこたま飲んだ挙句、尿酸値Full Maxな感じで倒れそうですが、flockで目が覚めた最近です。Solarisでゴニョゴニョやっているとちょいちょいflock関数でハマる、Solarisにはflock関数がない。面倒くさいからいつも逃げていたのですが今回はしっかり理解しようと思って、ちょっと調べてみた。だいたい、時間がたつとほぼ忘れますが...



flockはアドバイザリロック


ロックを取得するプロセスやスレッドが協力して動作するロック方式で、強制力のないロック方法です、ルールを守らないプロセスやスレッドが共有リソースへでたらめにアクセスした場合リソースは壊れる可能性があるので気をつけてください

Linuxのflock関数


詳しい関数の説明はmanページを見てくださいということでサンプルはgithubへ置きましたのでcloneしてmakeしてください。

https://github.com/calimakvo/flock.git

cuomo@karky7 ~/flock $ tree 
.
├── Makefile
├── flock.c      「共有ロック(LOCK_SH)」
├── flock_ex.c   「排他ロック(LOCK_EX)」
└── flock_nonblock.c 「ノンブロッキング排他ロック(LOCK_EX|LOCK_NB)」

ロックを確認する


「共有ロック」を使ったロック方式、シグナルをセットした後、flock関数を呼ぶ出すときに「LOCK_SH」を指定して呼び出す。ターミナルから複数起動しても直ぐにロックを取得できる、Read Lockで書き込みする奴が何もいなければ問題ない。
* 1つめ実行
cuomo@karky7 ~/flock $ ./flock
Lock success.
lock fd = 3
main loop..
main loop..
main loop..
..
* 2つめを別ターミナルから実行
cuomo@karky7 ~/flock $ ./flock
Lock success.
lock fd = 3
main loop..
main loop..
main loop..
..

「共有ロック」なので「共有ロック」同士のプロセスなのでロックはすぐとれる

次に2つの「共有ロック」プロセスが動いているところへ「排他ロック」なプロセスを起動してみる
cuomo@karky7 ~/flock $ ./flock_ex
...ロックがとれないのでflock関数でブロックしている

flock_exがflockでブロックしている状態のまま、最初の2つの「共有ロック」なプロセスをCtrl+Cで終了させると
cuomo@karky7 ~/flock $ ./flock_ex
Lock success.
lock fd = 3
main loop..
main loop..
main loop..
...

「排他ロック」のプロセスがロックを取得して実行し出す、その後「共有ロック」なプロセスを複数起動してから...
というような感じで交互に別ターミナルから実行すれば動作が掴めると思います。

LOCK_NBについて


flockで寝てもらいたくない場合に利用するフラグです。flock関数に(LOCK_NB)フラグをor演算子で追加指定して呼び出すと、ロックが取得できなくてもflock関数でブロックせず「EWOULDBLOCK」を返してくる呼び出し方法です。

flock関数とsignal


flock関数が「EINTR」を返すケースっていうのがあります、これはflock関数が呼び出されてブロックしている間にそのプロセスにシグナルが到着した場合、flock関数が中断されエラーで帰ってくる場合があるので、エラーでも「EINTR」の場合はもう一度呼び出してやる必要があります。
flock_exがブロックする状況を作って、別ターミナルからSIGUSR1をflock_exへ送ると、15661はflock_exのPIDです
cuomo@karky7 ~ $ kill -USR1 15661

ロックしているflock_exのターミナルへ「EINTR」を受け取って再度flock関数を呼び出したログが出力されます
cuomo@karky7 ~/flock $ ./flock_ex
get SIGUSR1
Retry get lock. 
..

この時のシグナル動作の注意点としては、通常のsignal関数でSIGUSR1をセットしただけでは「EINTR」で帰って来ないと言うことです(Linuxでの動作なのでBSDあたりだと確認とっていませんが...)、と言うことでPosix的なsigaction関数でシグナルをセットする必要があります。

flock関数とNFS


flock関数はNFS経由で利用した場合はしっかり動かないような処理系があるそうなのでご注意ください、ちなみにSolarisのNFSをLinuxでマウントして同じロック検証(ロックファイルはNFS上に作成)をやって見ましたが問題は起こりませんでした、Linuxのマウント設定とSolarisのNFS設定を確認してみます。

今後...


で「Solaris関係ないじゃん」って言われそうですが、これがfcntl関数へ続く予定です、暫くお待ちください...


汚いコードですみません..


2016年4月9日土曜日

謎のSUNWtooにハマる

謎のSUNWtooにハマる


香香飯店で飲んだ酒が体に合わず、小便の最中トイレを綺麗な女性に開けられた、体調不良を起こしている今日この頃、前から特定のspecだけpkgbuildの最後に
pkgbuild: Creating packages...
pkgbuild: pkg: Search performance is degraded.
pkgbuild: Run 'pkg rebuild-index' to improve search speed.
pkgbuild: pkg: Search performance is degraded.
pkgbuild: Run 'pkg rebuild-index' to improve search speed.
pkgbuild: pkg: Search performance is degraded.
pkgbuild: Run 'pkg rebuild-index' to improve search speed.
pkgbuild: pkg: Search performance is degraded.
pkgbuild: Run 'pkg rebuild-index' to improve search speed.
pkgbuild: PKGDB: Package library/ncurses is not installed, running a remote search for legacy actions
pkgbuild: pkg: Search performance is degraded.
pkgbuild: Run 'pkg rebuild-index' to improve search speed.
pkgbuild: pkg: Search performance is degraded.
pkgbuild: Run 'pkg rebuild-index' to improve search speed.
で固まる、どうやらCPUは1つ何やらやっている模様、気分が乗らないが調べたところ
  karky7  8721  8484   0   17:20:34 pts/2       0:03 /usr/bin/perl -I /usr/lib/pkgbuild-1.3.105 /usr/lib/pkgbuild-1.3.105/pkgbuild.p
  karky7  8482  8474   0   17:20:24 pts/2       0:00 /bin/ksh ../bin/specbuild.sh SFEcscope.spec
  karky7 11670  8721   1   17:21:30 pts/2       0:01 /usr/bin/python2.7 /usr/bin/pkg info -r pkg:/developer/linker@0.5.11,5.11-0.169
prstatで確認すると、「/usr/bin/python2.7 /usr/bin/pkg info -r pkg:/developer/linker@0.5.11,5.11-0.169」が生まれては、いなくなるをずっと繰り返す模様
pkgbuild.plをさっと見てはみるも、気力が追いつかず断念、しょうがないので「developer/link」確認すると
root@cbe113:~# pkg info -r SUNWtoo
          名前: SUNWtoo
      サマリー:
          状態: インストール済みでない (名前変更済み)
  変更後の名前: developer/linker@0.5.11-0.133
                  consolidation/osnet/osnet-incorporation
パブリッシャー: solaris
    バージョン: 0.5.11
ビルドリリース: 5.11
          分岐: 0.133
パッケージ化の日付: 2010年10月27日 18時55分42秒
        サイズ: 0.00 B
          FMRI: pkg://solaris/SUNWtoo@0.5.11,5.11-0.133:20101027T185542Z
root@cbe113:~#
なるほど、よく分からん、とりあえずこいつが臭いので、specから謎のSUNWtooを削除
Requires:            SUNWtoo
これでbuildは通ったが、いまいち分からない、なぜか、これがあるとダメなloopに陥る、

「osnet-incorporation」とか最近聞いたフレーズだったような気もするが...
もう静岡のServerspecな先生に聞くしかないようだ...

2016年3月6日日曜日

gentooでstackとyesodをやる

最近、yesod initが変わっちゃったみたい


最近、こうなる
cuomo@karky7 ~ $ yesod init
yesod: The init command has been removed. Please use 'stack new' instead
なんだよ、そうなっちゃってたの?

stackをいれる


stackってライブラリのバージョンセットを管理してくれるツール、便利だけど、gentoo-haskell使っている場合はあんまりうまくない。

Stackageはここ

karky7 ~ # emerge dev-haskell/stack

yesodのscaffoldを作成する


stackコマンドでそれぞれのテンプレートが作成出きるようになる
cuomo@karky7 ~ $ stack templates
chrisdone
franklinchen
ghcjs
ghcjs-old-base
hakyll-template
haskeleton
hspec
new-template
quickcheck-test-framework
rubik
scotty-hello-world
scotty-hspec-wai
servant
servant-docker
simple
simple-hpack
tasty-discover
tasty-travis
yesod-hello-world
yesod-minimal
yesod-mongo
yesod-mysql
yesod-postgres
yesod-postgres-fay
yesod-simple
yesod-sqlite
cuomo@karky7 ~ $ stack templates
ここからyesod-mysqlのテンプレートでalchuプロジェクトのscaffoldを作成する、ghcとかその他のyesodに関係するライブラリがはいっているので追加オプションでその辺を調整する。初回の実行はちょっと時間がかかるよ。
cuomo@karky7 ~/Code/yesod $ stack --system-ghc --no-install-ghc new alchu yesod-mysql
Downloading template "yesod-mysql" to create project "alchu" in alchu/ ...
Using cabal packages:
- alchu/alchu.cabal

Selecting the best among 3 snapshots...

Downloaded lts-5.5 build plan.
Caching build plan
Fetched package index.
Populated index cache.
* Selected lts-5.5

Initialising configuration using resolver: lts-5.5
Writing configuration to file: alchu/stack.yaml
All done.
cuomo@karky7 ~/Code/yesod $
mysqlを起動し、alchuを動かす
karky7 ~ # systemctl start mysqld
karky7 ~ # mysqladmin -u root create alchu
でdevelする
cuomo@karky7 ~ $ cd alchu/
cuomo@karky7 ~/alchu $ yesod devel
これで開発サーバーが起動する

stackとgentoo-haskell


gentoo-haskell使っているとstackを使ってインストールすることはあまりないと思いますが、gentoo-haskellにないライブラリ何かはstackで入れればいいとは思います。 hackportでebuild作っても簡単に入れられるので、どちらでもいいとは思いますが。
ちょっと機能的にかぶるので、ややこしい感は有りますが、バージョンセットを決めてくれたり、まえのcabalよりは統合されていて使いやすいですね。 ちなみに、~/.stackディレクトリに情報がはいっています。
.stack/
├── build-plan
│   └── lts-5.5.yaml
├── build-plan-cache
│   └── x86_64-linux
│       └── lts-5.5.cache
├── config.yaml
├── indices
│   └── Hackage
│       ├── 00-index.cache
│       ├── 00-index.tar
│       └── git-update
│           └── all-cabal-hashes
│               └── README.md
└── templates
    ├── yesod-mysql.hsfiles
        └── yesod-mysql.hsfiles.etag
stackでインストールした場合、この辺に実行プログラムとかがインストールされるようです。

でも、stackは非常に便利なので、みんなで使いましょう。

stackのオプション


こんなに覚えられるわけない...
cuomo@karky7 ~ $ stack --help
stack - The Haskell Tool Stack

Usage: stack [--help] [--version] [--numeric-version] [--docker*] [--nix*]
             ([--verbosity VERBOSITY] | [-v|--verbose]) [--work-dir WORK-DIR]
             [--[no-]system-ghc] [--[no-]install-ghc] [--arch ARCH] [--os OS]
             [--ghc-variant VARIANT] [-j|--jobs JOBS] [--extra-include-dirs DIR]
             [--extra-lib-dirs DIR] [--[no-]skip-ghc-check] [--[no-]skip-msys]
             [--local-bin-path DIR] [--[no-]modify-code-page]
             [--resolver RESOLVER] [--compiler COMPILER] [--[no-]terminal]
             [--stack-yaml STACK-YAML] COMMAND|FILE

Available options:
  --help                   Show this help text
  --version                Show version
  --numeric-version        Show only version number
  --docker*                Run 'stack --docker-help' for details
  --nix*                   Run 'stack --nix-help' for details
  --verbosity VERBOSITY    Verbosity: silent, error, warn, info, debug
  -v,--verbose             Enable verbose mode: verbosity level "debug"
  --work-dir WORK-DIR      Override work directory (default: .stack-work)
  --[no-]system-ghc        Enable/disable using the system installed GHC (on the
                           PATH) if available and a matching version
  --[no-]install-ghc       Enable/disable downloading and installing GHC if
                           necessary (can be done manually with stack setup)
  --arch ARCH              System architecture, e.g. i386, x86_64
  --os OS                  Operating system, e.g. linux, windows
  --ghc-variant VARIANT    Specialized GHC variant, e.g. integersimple (implies
                           --no-system-ghc)
  -j,--jobs JOBS           Number of concurrent jobs to run
  --extra-include-dirs DIR Extra directories to check for C header files
  --extra-lib-dirs DIR     Extra directories to check for libraries
  --[no-]skip-ghc-check    Enable/disable skipping the GHC version and
                           architecture check
  --[no-]skip-msys         Enable/disable skipping the local MSYS installation
                           (Windows only)
  --local-bin-path DIR     Install binaries to DIR
  --[no-]modify-code-page  Enable/disable setting the codepage to support UTF-8
                           (Windows only)
  --resolver RESOLVER      Override resolver in project file
  --compiler COMPILER      Use the specified compiler
  --[no-]terminal          Enable/disable overriding terminal detection in the
                           case of running in a false terminal
  --stack-yaml STACK-YAML  Override project stack.yaml file (overrides any
                           STACK_YAML environment variable)

Available commands:
  build                    Build the package(s) in this directory/configuration
  install                  Shortcut for 'build --copy-bins'
  uninstall                DEPRECATED: This command performs no actions, and is
                           present for documentation only
  test                     Shortcut for 'build --test'
  bench                    Shortcut for 'build --bench'
  haddock                  Shortcut for 'build --haddock'
  new                      Create a new project from a template. Run `stack
                           templates' to see available templates.
  templates                List the templates available for `stack new'.
  init                     Initialize a stack project based on one or more cabal
                           packages
  solver                   Use a dependency solver to try and determine missing
                           extra-deps
  setup                    Get the appropriate GHC for your project
  path                     Print out handy path information
  unpack                   Unpack one or more packages locally
  update                   Update the package index
  upgrade                  Upgrade to the latest stack (experimental)
  upload                   Upload a package to Hackage
  sdist                    Create source distribution tarballs
  dot                      Visualize your project's dependency graph using
                           Graphviz dot
  exec                     Execute a command
  ghc                      Run ghc
  ghci                     Run ghci in the context of package(s) (experimental)
  repl                     Run ghci in the context of package(s) (experimental)
                           (alias for 'ghci')
  runghc                   Run runghc
  runhaskell               Run runghc (alias for 'runghc')
  eval                     Evaluate some haskell code inline. Shortcut for
                           'stack exec ghc -- -e CODE'
  clean                    Clean the local packages
  list-dependencies        List the dependencies
  query                    Query general build information (experimental)
  ide                      IDE-specific commands
  docker                   Subcommands specific to Docker use
  config                   Subcommands specific to modifying stack.yaml files
  image                    Subcommands specific to imaging (EXPERIMENTAL)
  hpc                      Subcommands specific to Haskell Program Coverage
  sig                      Subcommands specific to package signatures
                           (EXPERIMENTAL)



2016年1月3日日曜日

Solaris11のvirtualboxでzfsとzvolであれをやってみた

SolarisのVirtualBoxで遊んでみた


zvolへいれるとzfsコマンドを色々使えてちょっと便利

zvolを作成する

ugui7 ~ # zfs create -V 128G rpool/centos7_vbox1
ugui7 ~ # chmod a+rw /dev/zvol/rdsk/rpool/centos7_vbox1

VirtualBox用のイメージを作成


cuomo@ugui7 ~ $ VBoxManage internalcommands createrawvmdk -filename ~/virtualbox/centos7/centos7.vmdk -rawdisk /dev/zvol/rdsk/rpool/centos7_vbox1
RAW host disk access VMDK file /export/home/cuomo/virtualbox/centos7/centos7.vmdk created successfully.

こうなっているのね

cuomo@ugui7 ~ $ cd virtualbox/centos7/
cuomo@ugui7 ~/virtualbox/centos7 $ cat centos7.vmdk 
# Disk DescriptorFile
version=1
CID=pokochin
parentCID=ffffffff
createType="fullDevice"

# Extent description
RW 268435456 FLAT "/dev/zvol/rdsk/rpool/centos7_vbox1" 0

# The disk Data Base 
#DDB

ddb.virtualHWVersion = "4"
ddb.adapterType="ide"
ddb.geometry.cylinders="16383"
ddb.geometry.heads="16"
ddb.geometry.sectors="63"
ddb.uuid.image="yyyyyyyy-poko-chin-poko-xxxxxxxxxxxx"
ddb.uuid.parent="00000000-0000-0000-0000-000000000000"
ddb.uuid.modification="00000000-0000-0000-0000-000000000000"
ddb.uuid.parentmodification="00000000-0000-0000-0000-000000000000"

centos7のインストール


後は普通にVirtualBoxでサーバーのストレージをさっき使ったvmdkを指定する




guest側をLVMで作っておけば拡張できるかなと、思いましたが、時間がないので今度にします。
まぁ、zfsに入っているとなにかと便利かも。