2016-10-31

Animes in the 3rd quarter of 2016

アニメは IT エンジニアの必須科目です。

またタイムリープかと思ったのも束の間、序盤は神展開。その反動か中盤は糞展開。終盤に持ち直す感じ。あと意図的だとは思うが、主人公がやたらイラッとくる。あの軽薄さで引きニート設定は無理があるかと。

各キャラの掘り下げが上手いのが Key 作品の特徴なのだろうか。特に委員長のくだりはずるい。しかし終わらせ方はあれで良かったのか疑問。ひょっとして次は True End バージョンが来る?

今期の一番はこれ。主人公の知略はもちろんのこと、ヒロインとの厚い信頼関係が見ていてとても心地よい。早く続きを作って欲しいところだが、種田梨沙が休業ってそんなー。

一見、NHK 教育でやってそうな雰囲気の作品。いわゆる悪役っぽいのも出てくるが、最後はきっちり拾い上げるし、本当に NHK でやってもおかしくない内容だと思う。

初話を見てかなり強引だなと思いつつも、結局最後まで見てしまった。ばらかもんのスピンオフだと気付いたのは途中から。最初はパクリかと思った。でもやはり設定に無理があると思う。

今期コメディ枠の一番。とにかく、ヒロインと小澤亜李の親和性に尽きる。この手のキャラを演らせたら、彼女の右に出る者は居ない。個人的にはコレットさんもお気に入り。

今度はゲーム制作業界の話か、と思ったら、業界の具体的な描写はほぼ無し。もっと SHIROBAKO みたいなのを期待した。ただし作品自体は絵調や雰囲気など好みで、単に想像と違ったというだけ。

序盤こそ良感触だったが、中盤からどんどん安っぽくなっていく。特に最終話が酷かった。これで「次期もあるよ」とか言われても、面白くない予感しかしない。

この手の女子向けは基本スルーだが、志倉千代丸が企画ということで視聴。結果、他の女子向け作品と余り大差なかった。A&R という職種も謎。ただ、つばさちゃんはいい娘だと思います。

わざわざ新キャラにする意味が分からなかったが、結果から言えば 1st よりも楽しめたので、これで良かったのかも。しかし CG をそのままアニメに使うのは手抜き。その辺はアイマスを見習うべき。

始まったと思ったら終わっていた。何を言っているか(ry。ていうか何故 4 話だけやろうと思ったのか。

最初は渋めでいい感じに始まるも、それ以降が盛り上がらなかった。復讐というには主人公の冷徹さが足りず、いろいろと中途半端だったように思う。

言い方は悪いのだろうが、夏目友人帳の明るめバージョン。他に言葉が見つからない。安倍晴明とか出てくるし、原作者はきっと女性とみた。

前期より視聴。ちょうどこの辺まで原作を読んでたっぽい。これから未知の領域へ、と思ったところで終わった。ちょっと短くないですかね。あとやっぱり絵が原作の雰囲気に合わないと思う。

歌と三角関係とバトル、というマクロスの三大要素はきっちり入っている。しかしフロンティアの壁は厚かった。超えられたのは楽曲だけだと思う。何だかんだでやっぱりシェリルは偉大。

シリーズ通して視聴。舞台が変わっても、バカやってるときは面白いがバトルになるとつまらなくなるのは変わらず。バカやってる間は文句なく面白いので、ずっとそうしてれば良いのに。

主人公がなかなか本気出さないので全然盛り上がらない。ようやく本気出したと思ったら一番いい所で終了。って何これ。流石にこれは評価できない。ノイタミナ枠でこんなひどいのは初めて見た。

最近は名前ばかりのガンダムが多いが、これは紛れもなくガンダム。冨野作と聞いても疑わないレベル。老人は見ておくべき。逆に、若者がこれをどれほど面白いと思えるのか興味がある。

2016-10-27

Windows batch: Multi-level variable expansion

この間 getopt.cmd を書いていて思ったこと。変数展開した結果を変数展開するにはどうすればいいんだろう?、と。言葉にすると説明が難しいが、要は C 言語でいうところの、ポインターのポインターから元データを参照する感じ。

call を使うのがいいようだ。call には変数展開後の文字列が引数として渡るので、どんなコマンドにも応用できる。call にこんな使い方があったとは。

test.bat:

@echo off
set hoge=HOGE
set r_hoge=hoge
set rr_hoge=r_hoge
echo %hoge%
call echo %%%r_hoge%%%               & rem run 'echo %hoge%'
call call echo %%%%%%%rr_hoge%%%%%%% & rem run 'call echo %%%r_hoge%%%'
>test.bat
HOGE
HOGE
HOGE

Windows バッチはこういう妙なところで懐が深かったりする。やろうと思えば大抵のことは(頑張りさえすれば)できるし。でもどんな良い面があっても、圧倒的マイナス面で ks 扱いされる Windows バッチさん。

2016-10-23

Windows batch: Getopt

Windows バッチが ks なことは今さら言うまでもないが、最もお手軽な手段であることも事実。特にユーザーに配布して実行させる場合、環境の差異を気にしないくて良いのは他の何にも勝る利点。同様の意味で WSH も素晴らしいが、結果が同じならシンプルな方を選びたい。

という訳で私はよくバッチも書くが、ちょっと凝ったバッチを書こうとしたとき、オプション処理にはいつも悩まされる。きちんとやろうとすると面倒だし、どうせならこの手の処理は共通化したい。誰か getopt みたいなやつ作ってねーのかよ、と偶にググってみても、これというものが見つかった試しがない。

まあ、もしバッチでできたらとっくに誰か作ってるよねー、と今まではあきらめていたが、今回ふと思って試してみた。

test.bat:

@echo off
setlocal
set opt=hoge
set opt_%opt%=HOGE
echo opt_hoge=%opt_hoge%
>test.bat
opt_hoge=HOGE

え!? set の左辺で変数展開できちゃうの?

そうか、set もコマンドだから、引数中の変数は展開されてから渡されるのか。ていうか、これ使えば getopt できるんじゃね?

getopt.cmd:

@echo off

if not "%~1"=="/?" goto :main
echo.Usage:
echo.  call %~nx0 [/OPTION[:VALUE]]...
echo.
echo.Description:
echo.  Parse options and define 'OPT_^<OPTION^>' variables, and set 'OPTIND' as
echo.  the number of processed arguments.
echo.
echo.Exsample:
echo.  When a batch file is invoked with arguments,
echo.
echo.    ^>example.bat /foo /bar:BAR /baz:"B A Z" arg1 arg2 ...
echo.
echo.  In the batch file, a typical usage is:
echo.
echo.    call %~nx0 %%*
echo.    for /L %%%%i in (1,1,%%OPTIND%%) do shift /1
echo.
echo.  Then a boolean option '/foo' can be tested as below.
echo.
echo.    if defined OPT_FOO ^(
echo.      echo /foo was given
echo.    ^) else ^(
echo.      echo /foo was not given
echo.    ^)
echo.
echo.  Other options have a value can be used as regular variable.
echo.
echo.    echo bar=%%OPT_BAR%%
echo.    echo baz=%%OPT_BAZ%%
echo.
echo.  Remaining arguments are referred through batch parameter.
echo.
echo.    echo args=%%1 %%2 %%3 %%4 %%5 %%6 %%7 %%8 %%9
echo.
echo.  Note that '%%*' batch parameter is never updated by 'shift'.
exit /b 1

:main
set OPTIND=0

:_loop_args
  set _getopt_arg=%1
  if defined _getopt_arg (
    call :parse_arg %_getopt_arg%
    if not errorlevel 1 (
      shift /1
      set /a OPTIND+=1
      goto :_loop_args
    )
  )
set _getopt_arg=
set _getopt_opt=
set _getopt_value=
set _getopt_bool=
exit /b 0

:parse_arg
set _getopt_opt=
set _getopt_value=%~1
set _getopt_bool=1
if not "%_getopt_value:~0,1%"=="/" goto :_parse_arg_ret
set _getopt_value=%_getopt_value:~1%
:_loop_arg_chars
  if not defined _getopt_value goto :_parse_arg_ret
  if "%_getopt_value:~0,1%"==":" (
    set _getopt_bool=
    set _getopt_value=%_getopt_value:~1%
    goto :_parse_arg_ret
  ) else (
    set _getopt_opt=%_getopt_opt%%_getopt_value:~0,1%
    set _getopt_value=%_getopt_value:~1%
  )
  goto :_loop_arg_chars
:_parse_arg_ret
if not defined _getopt_opt exit /b 1
if defined _getopt_bool (
  call :set_opt %_getopt_opt% %_getopt_bool%
) else (
  call :set_opt %_getopt_opt% %_getopt_value%
)
exit /b 0

:set_opt
set OPT_%1=%~2
exit /b 0

できちゃった :-D。使い方は次の通り。

test_getopt.bat:

@echo off
setlocal

call getopt.cmd %*
for /L %%i in (1,1,%optind%) do shift /1

if defined opt_hoge echo /hoge is given
if not defined opt_hage echo /hage is not given
echo /piyo=%opt_piyo%
echo /fuga=%opt_fuga%
echo /boke=%opt_boke%
echo %1 %2 %3 %4 %5 %6 %7 %8 %9
>test_getopt.bat /hoge /piyo:PIYO /fuga:"FU GA" /boke: arg1 arg2 ...
/hoge is given
/hage is not given
/piyo=PIYO
/fuga=FU GA
/boke=
arg1 arg2 ...

まだ改良の余地はあると思うが、私が使うには当面これで十分。

また今回の件で、Windows バッチは変数名に記号(どころか空白も!)を使えることを知ったが、ならば getopt.cmd に /? を渡せば opt_? を定義してくれそうに思う。しかしそれは叶わない。

>call getopt.cmd /?
バッチ プログラムを別のバッチ プログラムから呼び出します。

CALL [ドライブ:][パス]ファイル名 [バッチパラメーター]

  バッチパラメーター   バッチ プログラムで必要なコマンド ライン情報を指定します。

コマンド拡張機能を有効にすると、CALL は次のように変更されます:

<...snip...>

call が /? を奪い取る模様。やっぱ Windows バッチって ks だわ。

2016-10-11

Excel: Read write-locked file UTF-8 encoded

あるシステムのログの集計を、Excel マクロでやろうとしたときのこと。

ログは UTF-8 で書かれていたが、ググれば ADODB.Stream を使えば良いことは直ぐに分かる。ほどなくマクロは完成し、本番投入の直前、その問題は発覚した。

ADODB.Stream.LoadFromFile は、書き込みロックが掛かったファイルを読み込めない!

それはつまり、システムが開いている当日分のログを集計できないことを意味する。しかし、今回の要件としてそれは受け入れられない。何てこった。そんなこと Google 先生も教えてくれなかったよ。

Sub Test1()
    With CreateObject("ADODB.Stream")
        .Type = 2   ' 2=adTypeText
        .Charset = "UTF-8"
        .Open
        .LoadFromFile "WriteLocked.txt"
        ' ReadText...
        .Close
    End With
End Sub

ならば、アクセスモード(Stream.Mode)を読み取り専用(adModeRead)にすれば開けるはず。

Sub Test2()
    With CreateObject("ADODB.Stream")
        .Mode = 1   ' 1=adModeRead
        .Type = 2   ' 2=adTypeText
        .Charset = "UTF-8"
        .Open
        .LoadFromFile "WriteLocked.txt"
        ' ReadText...
        .Close
    End With
End Sub

どういうことなの。

恐らく、Stream が読み取り専用になったために、Stream への書き込みメソッドである LoadFromFile がブロックされたのだと思われる。確かに、動作的には間違ってはいない。しかし LoadFromFile にアクセスモードを指定する術がない以上、この方向での解決策は絶望的に思える。

ではファイルの読み込みは別の手段で行い、それを Stream に食わせたらどうか?

じゃそれ FileSystemObject で! と思ったら、FileSystemObject はバイナリ読み込みができないときた。それでも無理やり読み込ませてみたら、化け化けになった。泣きたい。

結局、最も基本的な方法で読み込ませることで上手くいった。

Sub Test3()
    Dim fd As Long, _
        buf() As Byte
    fd = FreeFile
    Open "WriteLocked.txt" For Binary As #fd
    ReDim buf(LOF(fd))
    Get #fd, , buf
    Close #fd

    With CreateObject("ADODB.Stream")
        .Type = 1   ' 1=adTypeBinary
        .Open
        .Write buf
        .Position = 0
        .Type = 2   ' 2=adTypeText
        .Charset = "UTF-8"
        ' ReadText...
        .Close
    End With
End Sub

この方法の欠点は、ファイル全体をメモリに読み込むこと。できれば 1 行ずつ読み込ませたいが、バッファリング制御とか大変そう過ぎて、やってみる気すら起きない。

2016-07-31

Animes in the 2nd quarter of 2016

アニメは IT エンジニアの必須科目です。

三輪士郎キャラ動画は初見だが、想像以上にアニメと相性が良かった。特に女子キャラは雰囲気があって良い。なのに、最後のヒロインの行動が訳ワカメだったのが残念。

前期より視聴。前期で広げた話にどう収拾をつけるか注目していたが、どうやら風呂敷を広げ過ぎた模様。加えて、視聴者の記憶力にももう少し配慮して欲しかった。

初見で女子向けか?と思ったらやっぱり少女マンガ原作。しかし女子キャラは男ウケしそうな感じで、男子が見ても十分イケる。反面、男子キャラは同性からみるとどれもイケてない。

前期より視聴。集英社は余程これを推したいらしいが、話の方はどんどん面白くなくなっていく。もはや進撃の対抗馬にすらならない。もう次回以降は見ないと断言できる。

作品自体はユニークで良く出来ていると思う。しかし声優がキャラに勝ちすぎて、見ていてずっと違和感が拭えなかった。この作品に限れば、特徴のある有名声優を使ったのは失敗だったと思う。

前期より視聴。前回のテンプレ対決を勝ち抜いただけあって、今回も王道の展開。つまりは意外性がなく退屈ということ。むしろこの流れで 3 期目をやることが最も意外だった。

絵を見て期待してなかったが、ヒロインがダメ可愛い。こんなん反則やろ。ネット上では最終話が炎上したっぽいけど、原作を知らないので気にしない。今回は日岡なつみを覚えた。

タイトルで煽る程にはヒロインが可愛くない。それよりも散りばめられたネトゲネタを楽しむのが正しい楽しみ方。つまり「しょうがないにゃあ」はもう一般用語ということでおk?

登場人物のキャラ付けが少し強引な気がしたが、慣れれば許容範囲。もう少し回を重ねると馴染んでくるような気がする。原作は長いようだし、次回もあるなら見るつもり。

登場時は万能感を感じさせる主人公だが、徐々にメッキが剥がれていく。それでも紅ルートを進めば挽回の余地もあったが、妹ルートに入ってしまい挽回することなく終了。

艦これ類似品と思いきや、むしろガルパンを彷彿とさせる良作。これ単発で終わらせるには惜しいように思う。ただ登場人物がやたら多く、私は最後までキャラ名を覚えられなかった。

とにかく最初から最後までほのぼのとした作品。決して悪くはないが、見るには少し退屈。ところで、ヒロインのキャラが「ずっと待ってる」の人にしか見えなくて困る。

最初はヒバリたんが可愛くて仕方なかったが、後半はヒビキがジワジワ来る。正直、コメディとしての面白さは微妙なので、誰かに属性が合うかどうかが全てだと思う。

主人公が八方美人でハイスペックという、私が今まで見たことがないタイプの BL。あっちの方も同性愛というより家族愛みたいな雰囲気。私も含めて、たぶん男には面白さが分からない。

最初は、腐女子が考えたような設定に「何だこりゃ」だったが、ジワジワと面白くなった。そして鏡花たんが出てからが本番。もう太宰とかいうアホはどうでもいいので、もっと鏡花たんを出してください。

和風ゾンビ物としては良いと思う。主人公のムサ苦しさもまた良し。しかしヒロインとその兄者、彼らのキャラと行動がテンプレート過ぎて、それが作品の完成度を下げていると思う。

2016-07-18

RHEL7: Virtual interface with NetworkManager

RHEL6 でインターフェイスに複数 IP アドレスを割り当てられるようになってからも、個人的には好んで仮想インターフェイスの方を使っている。

私自身、もう仮想インターフェイスはオワコン、とは思っていない。いくら ip addr で IP アドレスを自由に付け替えられるといっても、それでは余りに生々しすぎる。仮想インターフェイスは if{up,down} <ifname> という安全かつお手軽な UI が良いのだ。操作する度に IP アドレスとか打ちたくない。

という訳で、RHEL7 + NetworkManager で仮想インターフェイスが使えるかどうかは、私にとっては重要な問題。とりあえず早くに動くことだけは確認していたが、NetworkManager が仮想インターフェイスをどう扱っているのか良く分からず、暫く様子を見ていた。最近になって、ようやく安心して使っていけそうだと判断した。

まず、enp0s18 を親とする仮想インターフェイス enp0s18:1 を作ってみる。

# cat /etc/sysconfig/network-scripts/ifcfg-enp0s18
TYPE=Ethernet
BOOTPROTO=none
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
NAME=enp0s18
UUID=4fe308d7-c49f-4232-ba9b-fb8f635ea38c
DEVICE=enp0s18
ONBOOT=yes
IPADDR=192.168.0.1
PREFIX=24
IPV6_PEERDNS=yes
IPV6_PEERROUTES=yes
IPV6_PRIVACY=no

# cat /etc/sysconfig/network-scripts/ifcfg-enp0s18:1
NAME=enp0s18:1
DEVICE=enp0s18:1
BOOTPROTO=none
IPADDR=192.168.0.2
PREFIX=24

この状態で、NetworkManager はどのように認識するのか。(予め enp0s18 は停止している)

# cat /etc/redhat-release
Red Hat Enterprise Linux Server release 7.2 (Maipo)

# nmcli con reload

# nmcli con
NAME     UUID                                  TYPE            DEVICE
enp0s17  bd4f8279-8778-4032-86dc-900dce2a12ee  802-3-ethernet  enp0s17
enp0s18  4fe308d7-c49f-4232-ba9b-fb8f635ea38c  802-3-ethernet  --

NetworkManager は、親(enp0s18)だけを認識している。その内容は、

# nmcli con show enp0s18
connection.id:                          enp0s18
connection.uuid:                        4fe308d7-c49f-4232-ba9b-fb8f635ea38c
connection.interface-name:              enp0s18
connection.type:                        802-3-ethernet
connection.autoconnect:                 yes
connection.autoconnect-priority:        0
connection.timestamp:                   1467383289
connection.read-only:                   no
connection.permissions:
connection.zone:                        --
connection.master:                      --
connection.slave-type:                  --
connection.secondaries:
connection.gateway-ping-timeout:        0
802-3-ethernet.port:                    --
802-3-ethernet.speed:                   0
802-3-ethernet.duplex:                  --
802-3-ethernet.auto-negotiate:          yes
802-3-ethernet.mac-address:             --
802-3-ethernet.cloned-mac-address:      --
802-3-ethernet.mac-address-blacklist:
802-3-ethernet.mtu:                     auto
802-3-ethernet.s390-subchannels:
802-3-ethernet.s390-nettype:            --
802-3-ethernet.s390-options:
ipv4.method:                            manual
ipv4.dns:
ipv4.dns-search:
ipv4.addresses:                         192.168.0.1/24, 192.168.0.2/24
ipv4.gateway:                           --
ipv4.routes:
ipv4.route-metric:                      -1
ipv4.ignore-auto-routes:                no
ipv4.ignore-auto-dns:                   no
ipv4.dhcp-client-id:                    --
ipv4.dhcp-send-hostname:                yes
ipv4.dhcp-hostname:                     --
ipv4.never-default:                     no
ipv4.may-fail:                          yes
ipv6.method:                            auto
ipv6.dns:
ipv6.dns-search:
ipv6.addresses:
ipv6.gateway:                           --
ipv6.routes:
ipv6.route-metric:                      -1
ipv6.ignore-auto-routes:                no
ipv6.ignore-auto-dns:                   no
ipv6.never-default:                     no
ipv6.may-fail:                          yes
ipv6.ip6-privacy:                       0 (disabled)
ipv6.dhcp-send-hostname:                yes
ipv6.dhcp-hostname:                     --

注目すべきは、ipv4.addresses に、仮想インターフェイス(enp0s18:1)の IP アドレスも設定されていること。NetworkManager は仮想インターフェイスの情報を収集し、親インターフェイス側に集約するようだ。そして、仮想インターフェイスの方は無いことにされる。

# nmcli con show enp0s18:1 ; echo $?
Error: enp0s18:1 - no such connection profile.
10

この状態で enp0s18 を起動すると、両方の IP アドレスが起動する。

# ip addr show enp0s18
3: enp0s18: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:94:42:c7 brd ff:ff:ff:ff:ff:ff

# nmcli con up enp0s18
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/16)

# ip addr show enp0s18
3: enp0s18: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:94:42:c7 brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.1/24 brd 192.168.0.255 scope global enp0s18
       valid_lft forever preferred_lft forever
    inet 192.168.0.2/24 brd 192.168.0.255 scope global secondary enp0s18:1
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe94:42c7/64 scope link
       valid_lft forever preferred_lft forever

その際、仮想インターフェイスの「ONBOOT」や「ONPARENT」という設定は無視されるようだ。少なくとも試した限りでは、これらをどう設定しても、仮想インターフェイス側の IP アドレスは自動的に起動した。

そして前述のように、NetworkManager は仮想インターフェイスを認識していないので、NetworkManager から up / down することはできない。

# nmcli con down enp0s18:1 ; echo $?
Error: 'enp0s18:1' is not an active connection.
Error: no active connection provided.
10

# nmcli con up enp0s18:1 ; echo $?
Error: Connection 'enp0s18:1' does not exist.
10

しかし、従来 ifup / ifdown ならそれが可能。

# ip addr show enp0s18
3: enp0s18: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:94:42:c7 brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.1/24 brd 192.168.0.255 scope global enp0s18
       valid_lft forever preferred_lft forever
    inet 192.168.0.2/24 brd 192.168.0.255 scope global secondary enp0s18:1
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe94:42c7/64 scope link
       valid_lft forever preferred_lft forever

# ifdown enp0s18:1 ; echo $?
0

# ip addr show enp0s18
3: enp0s18: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:94:42:c7 brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.1/24 brd 192.168.0.255 scope global enp0s18
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe94:42c7/64 scope link
       valid_lft forever preferred_lft forever

# ifup enp0s18:1 ; echo $?
0

# ip addr show enp0s18
3: enp0s18: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:94:42:c7 brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.1/24 brd 192.168.0.255 scope global enp0s18
       valid_lft forever preferred_lft forever
    inet 192.168.0.2/24 brd 192.168.0.255 scope global secondary enp0s18:1
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe94:42c7/64 scope link
       valid_lft forever preferred_lft forever

ifup / ifdown は、NetworkManager が管理しているインターフェイスについては NetworkManager に処理を丸投げするが、そうでない場合、従来と同様に自身が処理を行う。よって仮想インターフェイスについても、ifup / ifdown が従来通り処理を行う。

・・・のはずなのだが、実は RHEL7.1 以前には不具合があって、仮想インターフェイスを ifup することができない。

# cat /etc/redhat-release
Red Hat Enterprise Linux Server release 7.1 (Maipo)

# ifdown enp0s18:1 ; echo $?
0

# ifup enp0s18:1 ; echo $?
Error: no device found for connection 'enp0s18:1'.
4

正直、この不具合のお陰でずっと NetworkManager と仮想インターフェイスとの関係に悩んでいたと言っても過言ではない。:-(

以上をまとめると、

  • RHEL7 でも仮想インターフェイスは従来通り使用できる。
    • 但し、「ONBOOT」や「ONPARENT」は設定できない。(常に自動起動する)
  • 仮想インターフェイスを ifup / ifdown したいなら、RHEL7.2 以上が必須。

個人的には、仮想インターフェイスはずっと残しておいて欲しいと願っている。きっと RHEL8 でも動いてくれる・・・よね?

2016-05-31

Slony-I 2.0: `cleanupEvent' causes deadlock

Slony-I 2.0.6 + patch を使うようになって以降、割かし平穏な日々を過ごしてきたが、

実は一つだけ問題がある。Slony-I 2.0 系は、deadlock を起こすことがある。

いつか直らないかと気には掛けていたが、一向にその気配もなく今に至る。そうしているうちに何年かぶりに再発したため、今更ながら調べることにした。

面倒いので該当ソース箇所は省略。まず発生条件は、slon が 10 分毎に実行する clenaupEvent 処理と、slonik の実行が衝突すること。slonik を使わない、または slonik 実行時に slon が停止していれば発生しない。(たぶん)

deadlock の原因は、当たり前だが、それぞれの処理でロックの取得順が異なるため。それぞれのロック取得順は下記のようになる。

  • slonik コマンド: sl_config_lock -> sl_event (一部のコマンドを除く)
  • slon cleanupEvent: sl_event -> sl_config_lock

分かってしまえば解決は造作もない。ロック順を合わせてやれば良い。今回の場合、cleanupEvent の最初で sl_config_lock を取得してしまうのが簡単。

--- slony1-2.0.6/src/backend/slony1_funcs.sql.orig	2010-12-08 01:44:09.000000000 +0900
+++ slony1-2.0.6/src/backend/slony1_funcs.sql	2016-05-31 17:35:22.000000000 +0900
@@ -4478,6 +4478,11 @@
 	v_rc            int8;
 begin
 	-- ----
+	-- Grab the central configuration lock
+	-- ----
+	lock table @NAMESPACE@.sl_config_lock;
+
+	-- ----
 	-- First remove all confirmations where origin/receiver no longer exist
 	-- ----
 	delete from @NAMESPACE@.sl_confirm

本当にこの修正で良いのか不安もあるが、そもそも発生することが稀なため、確認するのも容易でない。正直、「直ったらラッキー」程度に考えている。

ちなみに Slony-I 2.1 以降はロック機構がガラリと変わっているため、以上は該当しない。(deadlock が起こらないかは知らない)

2016-04-30

Animes in the 1st quarter of 2016

アニメは IT エンジニアの必須科目です。

最初こそ「面白いかも」との期待もあったが、程なくマンネリ感が漂い、ちょっと出来のいい作品に落ち着いた。主人公を好みかどうかで評価が分かれる気がする。ちな私は好みでない。

前期より視聴。ヒロインがラブラブになるほどつまらないのは相変わらず。むしろラジ王子と絡んでいる方がよっぽど面白かった。第三期があっても見ないと思う。

最弱無敗の主人公、チョロいヒロイン等。これは是非とも前クールで落第騎士、アスタリスクと三つ巴の争いをやって欲しかった。個人的にはクルルシファーがツボったので満足。

原作は半既読。アニメ化に伴い、ヒロインの魅力が半減。色っぽくないし、何より(私の想像と)声が違う! 対してサヤ氏は魅力 50% 増。サヤ氏推しは見ておいて損はない。

  • プリンス・オブ・ストライド オルタナティブ http://pos-a.jp/

「ストライド」とかいう、限界まで格好つけた障害物競争は見ていて滑稽。女子向けメディアミックスのアニメ作品らしく、安定の中身の薄っぺさ。男子は見る必要なし。

前シーズンより視聴。声優の割り当ては相変わらず適当だが、全体的には綺麗に纏まった感じ。あといい加減、主要キャラに怪我を負わせて試練と称する少年誌の悪癖はやめるべき。

シリーズ通し視聴。正直、やっと終わってくれた、というのが本音。これだけ引き延ばしておいて、幕引きは余りに呆気ない。これなら「起」と最終回だけ見とけば十分。

クラリオンがかわいい、に尽きる。あと「ロボットだからエロくないもん」というのは、これから流行るかも知れない。しかし原作が士郎正宗だったことに一番驚いた。

女子向けなので男子スルー安定と思いきや、ヒロイン除く女子二名が意外に可愛くて、結構楽しめてしまった。話も女子向けには珍しい設定だが、1 クールでは消化不足な感。

原作の評価は高かったみたいだが、アニメになってしまうと普通。しかし絵が綺麗でオリジナリティもあるのは認める。お気に入りの女子キャラが居ればまた違ったと思う。

雨宮天の新境地。こんな演技ができるとは思わなかった。めぐみんもいいキャラで、この二人と主人公との絡みが面白い。ただ一人、ダクネスの魅力が分からない。第二期では彼女の躍進に期待。

まず吹奏楽は全くの飾りで、実は推理物な件。しかし本作の要は、推理ではなくヒロイン。彼女なくしてこの作品は成り立たない。個人的には、一クールで終わらせるには惜しい作品。

コンビニでジャンプが立ち読みできなくなって以降、こんなことになっていたとは。果たしてこれは銀魂なのか。とてもファンが望んだ方向とは思えない。楽しかった銀魂よ、帰ってきておくれ。

2016-03-31

Gnus: Always `Message-ID' in Article buffer

メールをコピペするとき、エンジニア的には Message-ID を含めておきたい。Gnus の標準設定は Message-ID 非表示なので、今までは t キー(gnus-summary-toggle-header)を押して都度 Message-ID をコピペしていたが、いい加減それが面倒になった。(そりゃそうだ)

gnus-visible-headers なる変数は直ぐに見つかるので簡単と思いきや、この変数は、

  • 「正規表現」「正規表現のリスト」のどちらでも設定可能で、前者の初期値を持つ。
  • gnus-art ロード時に定義される。(それまでは未定義)

これらの要因により、きちんと設定するのは思ったより面倒。私がやりたいのは、gnus-visible-headers の初期値に設定を追加すること。将来のバージョンで初期値が変わることも考慮したい。

;; visible headers in article buffer
(setq my-gnus-visible-headers '("^Message-ID:"))
(eval-after-load "gnus-art"
  '(progn
     (when (stringp gnus-visible-headers)
       (setq gnus-visible-headers
	     (split-string gnus-visible-headers "\\\\|")))
     (dolist (header my-gnus-visible-headers)
       (add-to-list 'gnus-visible-headers header))))

ググると、他の人は gnus-visible-headers に concat するパターンが多いようだ。しかしそれだと、二回目以降の Gnus 起動で設定が重複するのが気持ち悪いし、個人的には重複チェックを add-to-list に任せられるリストの方が好み。しかし、やりたいことに対して設定が冗長になった感は否めない。

2016-02-03

ActiveDirectory DDNS + dhclient

開発者にとって、Linux 仮想マシンは必要不可欠なものだが、IP アドレスをどうするかは悩ましい問題だ。例えば次のような状況は多いはず。

  • 社内は ActiveDirectory DNS/DHCP 環境。
  • 勝手に固定 IP アドレスを使えない。
  • 社内ネットワークから仮想マシンを参照させたい。

このような場合は DHCP を使うことになるが、暫く起動しないと IP アドレスが変わって接続する際に一手間かかって面倒くさい。個人的にはこういう場合、Samba (の nmbd)を使っている。サービスを起動しておくだけで Windows PC からホスト名(NetBIOS 名)でアクセスできるので、何かと便利。

しかし最近、ActiveDirectory のドメインに参加せずとも、DHCP で DNS レコードを登録できることを知った。少なくとも ActiveDirectory の DNS/DHCP にはそういう機能があり、そして私の社内ではそれが有効になっている。

そうすると後は DHCP クライアント側の話。RHEL では、次の設定でそれができる。(詳細は man dhclient.conf)

RHEL6: /etc/dhcp/dhclient.conf:

send fqdn.fqdn "myhost.example.local.";
send fqdn.server-update off;

RHEL5 ではファイルの場所が /etc/dhclient.conf となる。RHEL4 以前は知らない。

ネット上には、同じく dhclient.conf の host-name や ifcfg-* の DHCP_HOSTNAME でできるよ、みたいな情報も見つかる。しかし BIND ではそれで動くのかも知れない(未検証)が、社内の ActiveDirectory では動かなかった。

なお、dhclient.conf はデバイス毎に設定が可能で、その場合はグローバルな dhclient.conf は無視されるので注意。この辺はソースを見た方が理解が早い。

RHEL5.11: /etc/sysconfig/network-scripts/ifup-eth:

    # allow users to use generic '/etc/dhclient.conf' (as documented in manpage!)
    # if per-device file doesn't exist or is empty
    if [ -s /etc/dhclient-${DEVICE}.conf ]; then
       DHCLIENTCONF="-cf /etc/dhclient-${DEVICE}.conf";
    else
       DHCLIENTCONF='';
    fi;

RHEL6.7: /etc/sysconfig/network-scripts/network-functions:

generate_config_file_name () {
        local ver=$1
        if [ -s /etc/dhcp/dhclient$ver-${DEVICE}.conf ]; then
                DHCLIENTCONF="-cf /etc/dhcp/dhclient$ver-${DEVICE}.conf";
        elif [ -s /etc/dhclient$ver-${DEVICE}.conf ]; then
                DHCLIENTCONF="-cf /etc/dhclient$ver-${DEVICE}.conf";
        else
                DHCLIENTCONF='';
        fi
}

例えば私の環境では、RHEL5.11 のインストール直後に /etc/dhclient-eth0.conf が存在したので、この場合は /etc/dhclient.conf に書いた設定は使用されない。

これで私の環境でも DNS に登録できた。ただ個人的には、Windows PC からアクセスするだけなら nmbd の方を奨めたい。わざわざ DNS レコードをゴニョゴニョせずに済むなら、それに越したことはない。

以上、これで話が終われば幸せだった・・・。というか、こうして本エントリを書く必要すらなかった。残念ながら、これらは RHEL6 までの話。RHEL7 では話が変わる。:-(

周知の通り、RHEL7 では NetworkManager が幅を利かせていて、NetworkManager は従来の処理を使わずに自前で処理を行う。(ただし従来の処理自体は存在していて、それらは NetworkManager が無効の時に使われる)

まず dhclient.conf が未設定の状態で、どうなるのか確認してみる。

[rhel7]# cat /etc/redhat-release
Red Hat Enterprise Linux Server release 7.2 (Maipo)

[rhel7]# rpm -q NetworkManager
NetworkManager-1.0.6-27.el7.x86_64

[rhel7]# cat /etc/dhcp/dhclient.conf
cat: /etc/dhcp/dhclient.conf: No such file or directory

このときデバイスの dhclient 設定は、デバイス起動時に下記の場所に生成される。

[rhel7]# cat /var/lib/NetworkManager/dhclient-enp0s17.conf
# NetworkManager で作成されています

send host-name "rhel7"; # added by NetworkManager

option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;
option ms-classless-static-routes code 249 = array of unsigned integer 8;
option wpad code 252 = string;

also request rfc3442-classless-static-routes;
also request ms-classless-static-routes;
also request static-routes;
also request wpad;
also request ntp-servers;

dhclient.conf を作ってデバイスを再起動すると、上記が再生成される。しかし・・・、

[rhel7]# cat /etc/dhcp/dhclient.conf
send fqdn.fqdn "rhel7.example.local.";
send fqdn.server-update off;

[rhel7]# systemctl restart network

[rhel7]# cat /var/lib/NetworkManager/dhclient-enp0s17.conf
# NetworkManager で作成されています
# /etc/dhcp/dhclient.conf からマージされています

send fqdn.server-update off;
send host-name "rhel7"; # added by NetworkManager

option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;
option ms-classless-static-routes code 249 = array of unsigned integer 8;
option wpad code 252 = string;

also request rfc3442-classless-static-routes;
also request ms-classless-static-routes;
also request static-routes;
also request wpad;
also request ntp-servers;

fqdn.fqdn がマージされていない!

ソースコードを確認してみる。

#define HOSTNAME4_TAG    "send host-name"
#define HOSTNAME4_FORMAT HOSTNAME4_TAG " \"%s\"; # added by NetworkManager"

#define FQDN_TAG    "send fqdn.fqdn"
#define FQDN_FORMAT FQDN_TAG " \"%s\"; # added by NetworkManager"

/* ...snip... */

char *
nm_dhcp_dhclient_create_config (const char *interface,
                                gboolean is_ip6,
                                GBytes *client_id,
                                const char *anycast_addr,
                                const char *hostname,
                                const char *orig_path,
                                const char *orig_contents,
                                GBytes **out_new_client_id)
{
	/* ...snip... */

			/* Override config file hostname and use one from the connection */
			if (hostname) {
				if (strncmp (p, HOSTNAME4_TAG, strlen (HOSTNAME4_TAG)) == 0)
					continue;
				if (strncmp (p, FQDN_TAG, strlen (FQDN_TAG)) == 0)
					continue;
			}

fqdn.fqdn をスキップしている。かといって fqdn.fqdn が常に抹殺される訳でもなくて、

static void
add_hostname4 (GString *str, const char *format, const char *hostname)
{
	char *plain_hostname, *dot;

	if (hostname) {
		plain_hostname = g_strdup (hostname);
		dot = strchr (plain_hostname, '.');
		/* get rid of the domain */
		if (dot)
			*dot = '\0';

		g_string_append_printf (str, format, plain_hostname);
		g_free (plain_hostname);
	}
}

/* ...snip... */

static void
add_hostname6 (GString *str, const char *hostname)
{
	/* dhclient only supports the fqdn.fqdn for DHCPv6 and requires a fully-
	 * qualified name for this option, so we must require one here too.
	 */
	if (hostname && strchr (hostname, '.')) {
		g_string_append_printf (str, FQDN_FORMAT "\n", hostname);
		g_string_append (str,
		                 "send fqdn.encoded on;\n"
		                 "send fqdn.server-update on;\n");
		g_string_append_c (str, '\n');
	}
}

何故か IPv6 では fqdn.fqdn を設定している。IPv6 での動作は未確認だが、このコードだと IPv4 で fqdn.fqdn を送る術がないように見える。

もう NetworkManager ってほんと ks だわ、と思っていたら、

どうやら NetworkManager の設定項目に ipv4.dhcp-fqdn が増える模様。果たしてこれは RHEL7.3 に入ってくれるのだろうか。


2018-09-25 追記

あれから 2 年半、現段階の私の結論を記しておく。

まず、前述の修正は RHEL7.3 に入った。しかし私の環境では、状況は全く変わらなかった。これ以上はパケットキャプチャとか更なるソースコード解読とかが必要になるし、面倒いのでずっと放置していた。

そのうち、今度は dhclient のフックを使う方法を知った。

これは dhclient.conf に FQDN を書くよりスマートな方法に思える。FQDN は hostname コマンドから引っ張ってこれるので、ハードコードが不要になるからだ。

しかし、これも動かなかった。orz

NetworkManager は dhclient のフックを呼ばないらしい。あれもダメ、これもダメ、いったい何だったら動くというのか。NetworkManager 的には、「dispatcher を使え」とのこと。

/etc/NetworkManager/dispatcher.d/90-nsupdate:

#!/bin/bash

[ -n "$DHCP4_IP_ADDRESS" ] \
    && [ "$HOSTNAME" != "${HOSTNAME/./}" ] \
    || exit 0

nsupdate <<EOF
update delete $HOSTNAME a
update add $HOSTNAME 3600 a $DHCP4_IP_ADDRESS
send
EOF

/etc/NetworkManager/dispatcher.d/pre-down.d/90-nsupdate:

#!/bin/bash

[ "$HOSTNAME" != "${HOSTNAME/./}" ] \
    || exit 0

nsupdate <<EOF
update delete $HOSTNAME a
send
EOF

後者(pre-down)の処理は、対称性という観点で作ったものの、無くても問題ない。何故なら、pre-down はシャットダウン時に呼ばれないから。でもネットワーク再起動(systemctl restart network)では呼ばれる。ほんと、これを作った奴らはタヒんでいいよ。

あと、dispatcher 内でどの環境変数が利用できるかは、man を見てもいまいち明確でない。なので自作する場合は、まず set コマンドの出力をロギングする dispatcher を作って、action 毎に利用可能な環境変数を確認することをお勧めする。

結論: やっぱ NetworkManager は ks。

2016-01-31

Animes in the 4th quarter of 2015

アニメは IT エンジニアの必須科目です。

アクエリオンでなければ許せたが、アクエリオンの冠つけておいてこれは無いわ。よく 2 クールもやったもんだと逆の意味で感心する。ていうか、これ作った奴はクビじゃね?

絵が好みでないのもあるが、ヒロインが魅力に乏しい。騎士が仕える姫としては、単なる可愛らしさ以外の個性が欲しい。次回予告のノリは、個人的にはアリだった。

前期より視聴。相変わらず絵は綺麗だが、話が普通すぎる。親友との再会シーンは幾らでも面白くできただろうに、ピークがこれならこの先の盛り上がりも程度が知れる。

もうこの二つは一緒でいいよね。というかセットで見るべき。現在のテンプレというものが分かる。もういっそ、このテンプレート縛りでどこまで面白い作品が作れるのか競わせるのも面白い。個人的な評価は後者が上。その辺は、次回に続くか否か、という結果に表れている模様。

これも↑に入り込みそうだったが、辛うじてセーフ。しかしヒロイン達がチョロいのは変わらず。キャラは粒揃いだったと思うが、粒のまま終わってしまった感じで残念。

主役二人に魅力がないのが致命的。エロである理由も感じられない。最後の方を見ていて唐突に、「これ女版の聖闘士星矢にしたら面白かったんじゃね?」と思ったくらい。

キャラ絵が前世紀っぽくて逆に新鮮。話も独特で良いが、時間が飛ぶ展開には頭が付いていかなかった。ともあれ、次回どう収束させるのか期待。あと、アースちゃんは正義。

これも女子の理想が詰まったテンプレート。加えてミュージカルは歌の上手い・下手以前に、歌詞が圧倒的にダサい。それでもせめて歌の上手さで声優を選ぶべきだった。

この人の作るキャラは本当に個性的で、ただ感心する。最近の物語シリーズでは一番楽しめたと思う。ただ流石に、前回からの伏線回収を最後にブッ込まれても、もう覚えてないよ。

前期は未視聴だが、勉強のため視聴。正直、キャラデザは好みでないのだが、程なく皆がピョンピョンする理由が分かった。機会があればぜひ前期も見てみたい。

主人公のキャラデザを見てどうなることかと思ったら、これはこれでアリだった。設定上どうしても話が淡泊になりがちなので、ここからどう展開するのか興味深い。

シリーズも長いせいか、それぞれキャラも固まってきて安定してきた感じ。少なくとも以前のように必死なだけで見ていて寒いギャグが減った。今後は安心して見られそう。

分類はミステリー作品なのだろうが、謎解きに面白さが感じられず、ヒロインにも入れ込めず。今回に限っては、伊藤静のキャスティングは失敗だったような気がする。

前期に続き視聴。本作を見ても、何が面白いのかさっぱり分からない。エロも変わらずエロくないし。むしろ各キャラに焦点が当たっていた分、一期目の方がまだ見られた。

見る前はミステリーとは予想もしなかったが、結果、十分に楽しめた。今さら 16bit かよ、という突っ込みも、原作が 20 年前ならば納得。今回は種崎敦美の演技と甲斐田裕子の英語を褒めたい。

第 1 クールと合わせて視聴。十年以上前の作品(第一期)を、復習なしで平然と続けることに驚き。にもかかわらず、かなり真剣に見てしまった。これは第一期より相当面白くなった気がする。(もう覚えてないけど)