SVX日記

2004|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|12|
2020|01|02|03|04|05|06|07|08|09|10|11|12|
2021|01|02|03|04|05|06|07|08|09|10|11|12|
2022|01|02|03|04|05|06|07|08|09|10|11|12|
2023|01|02|03|04|05|06|07|08|09|10|11|12|
2024|01|02|03|04|05|06|07|08|09|10|11|12|
2025|01|02|03|04|05|06|

2004-12-21(Tue) マウス、ジャブジャブ

  とーとつだが、オイラはほんの少しだが料理する。ま、料理といっても概ね「1パスか2パス」で終わる程度のものがほとんどではある。うどんを「茹でる」とか、スパゲティを「茹でて、絡める」という程度だ。しかし、うどんやスパゲティはコシや歯ごたえが命。茹で加減には秒単位でコダわっている。反面、ツユや具にはぜ〜んぜんコダわらない。

  そんな私であるから、料理法は「ID野球」ならぬ「ID料理」を実践している。「Information & Data」つまり情報と事実に基づいた理論的な料理法である。そしてその適用の一例を以下の温泉タマゴで示そう。

  画像の説明

  温泉タマゴの理論とは「特定の温度では黄身は白身より早く凝固する」である。よって「特定の温度を与え続ける」必要があるわけだ。しかしそんなことはサーモスタットでも使わない限り難しい。最近ハード系に興味を持っているオイラにはうってつけのテーマではあるが、そんな面倒なコトせずに作りたい。よって「特定の温度を与続ける」を「特定の温度を作り出し、長時間保温する」という方法にスリかえ妥協するのである。

  ここで問題になるのが「特定の熱を作り出す」というトコロ。温度計で測るなんて面倒クセーのである。そこで1年を通じて簡単に作り出せる温度からその特定の温度を作り出すのだ。わかりやすくいうと「沸点である100度」と「冷蔵庫の温度」から作り出すのである。そしてその双温度を特定の温度に釣り合わせるためのパラメータは「タマゴの数と大きさ」「沸騰した湯の量」である。タマゴの大きさは概ね同じであり、数は3つだと固定すると「タマゴの固まり加減」は「沸騰した湯の量」との線形関係としてまとめることができるのである。

  あとは残りの「長時間保温する」という条件を整えるのだ。夏と冬では室温が異なるが、この影響を最小限にするため、木製のダイニングテーブルの上に木製の鍋敷きを置き、その上にプラスチック製の保温性能が高い容器を配置。朝にセッティングを決めて夜まで放置する。これでデキたのが上記の温泉タマゴである。完璧なデキだ。

  以上のことから我が家は「冷蔵庫から出したての3つのタマゴに沸騰した湯を750mlを注ぐ」というレシピを完成している。保温容器や周辺環境の違いは誤差となるため、マネする人は上記の計算方法を考慮の上、考慮の上、熟慮の上、試行錯誤して欲しい。できれば、タマゴの比熱から湯の量を求めたり、保温容器の熱抵抗を考慮するとよりアレゲである。

  最後に、直接タマゴに熱湯をかけるとヒビ割れを生じやすい、デキ上がった温泉タマゴは生タマゴと区別するためにキン肉マンの顔を書いておくとよい、温泉タマゴを食す際には醤油より原液の白ダシがよい、という重大な助言を与えておこう。ではまた。

  ……と、思わず温泉タマゴで終わってしまうところであったが、今日はもうひとつネタがあるのである。先日のキーボード洗いの続編ではないが、今度はマウスを洗うのである。

  このマウス、かなり以前にデスクトップ機を使っている時に愛用していたのだが、デスクノートであるジャンクメビウスを主力にしてから、ずーっと放りっぱなしであった。なにせ、レシーバがデカすぎてノートには不釣合いなのである。

  しかしながら、私の好みであるボールマウスであるし、なにせ当時7,000円近く出して購入した記憶があるLogitechブランドの高級マウスだ。先日のワイヤレスマウス修理の際に職場のデスクトップPCのマウスからホイールのエンコーダパーツを抜いてから使い勝手が悪くてかなわないので(←アタリマエだっつーの)このマウスを復活させるのである。

  お約束のバラしである。確かに7,000円するだけあって、スゴイ部品数だ。ホイールも光学エンコーダだし、安物のマウスによくある片持ち構造ではなく、しなやかに垂直に下りるバネ形式になっている。基板も3枚に分かれている。このヘンがボールマウスが敬遠されつつあり、光学マウスが主流になりつつある理由なのだろうな。ボールマウスだとマウスの形状からして1枚基板で作ることは難しいのだ。

  画像の説明 画像の説明

  両脇のゴムの部品には手垢がネッチョリと付いているので、CD-Rのスピンドルケースのフタに部品をまとめて突っ込んでボディソープでガラガラと洗う。ホテルYRPで温存しておいた安物の歯ブラシの出番だ。ガシガシとコスる。気の済むまでコスったら、キッチンペーパの上で乾かす。気の短いオイラはカメラに使うエアーブロワーで水気を吹っ飛ばす。気の長い人はちゃんと乾くまで待とう。

  画像の説明

  で、組み上げる。特に前述のホイール部分の構造は凝っているので、組み上げるのに試行錯誤してしまったが、無事完成した。散々バラして再組み立てして気づいたが、両脇のゴムパーツとの継ぎ目は接着と見まごうほど緻密だ。これだけの工作精度を確保すれば値段にハネかえって当然だよな。そんな高級品が新品同様のペッカペッカに復活した。あー、気持ちイイ。

  なお、今日は少し例の「Shaken you up!!」を進めたのだが、予期せず振動モーターが動いたのでマジに驚いて寝込んでしまった。うひゃぁ。おやすみ。


2005-12-21(Wed) Olimexから基板届く!!

  「郵便物お預かりのお知らせ」が入っていた。

  にしても、最近、ネタがなくてすまん。NTPサーバでもrubyで作ってみたい今日この頃であるが。


2009-12-21(Mon) 戦闘終了

  情報処理試験、ITサービスマネージャ区分に合格していた。

  試験の前日にムキーッ!!……っとかしてて、ほとんど勉強してなかったし、実際の試験でも、午後IIの論文にキレが出せなかったし、帰って添削したみたら、午前IIがスレスレだったりで、まったく受かる気がしなかったのだが……試験区分がハツモノだったことに乗じて受かったのかもしれん。

  なんにしてもうれしいことだ。会社から報奨金も出るし。でも、今回の合格は、ちょっと特別。なにが特別って、今回で引退だから。

  思い返せば、2000年の春。二種を受験して合格してからというもの、のべ10年間、18回受験して、10区分をゲットした。もう、さすがにゴールしてもいいと思うのだ。まだ、ITストラテジスト、システム監査、データベースが残ってはいるが、別に全ビットを立てる必要もない。これにて終了。もう、ぼくはつかれたんだよパトラッシュ。

  画像の説明

  つーわけで、祝杯。実は、グラスを買った帰りに、酒屋に寄って買ってきた、グレンファークラスの12年を開ける。たまには、違う種類のスコッチを、と思って選んだもの。

  あちこちでよく見るような、まったく役に立たないインプレッションを語るつもりはないが、確かにタリスカーとは違う。ちょっと人工的な味がする。悪くないが。どこかで呑んだことがあるような気がしつつ、Wikipediaを引いたら「シェリー樽にこだわった熟成」とあった。そういえば、グレンモーレンジのシェリーウッドフィニッシュがこんな感じだったような気もしてきた。

  で、荘厳な金色、を撮影してみた。

  画像の説明

  なんともいえない、いい色になる。

  見た目に近い画像を得ようとして、レタッチアプリなんかで、あれこれやってみた。あれこれできるようになると、デジカメで撮ったままの画像なんぞ、単なる素材に過ぎないことに気づく。んが、さらにもう少しできるようになると、結局、観る側の環境に依存することに気づいて、やる気がなくなるんだよねぇ……。


2017-12-21(Thu) マツダは予定をかなり繰り上げるつもりだ

  日めくりは元には戻らない。だがマツダなら進めることはできる。

  画像の説明


2021-12-21(Tue) dockerのコンテナ内でアレしたい

  というわけで、私はdockerが好きなのだが、どうにも使い勝手の悪い部分がある。コンテナの開発をしていると、docker execでコンテナ内に入ったり、docker logsでコンテナのログを見たりする機会が非常に多いのだが、その都度、対象となるコンテナ名をフルで入力しなければならない点だ。マウスでコピペとか、キーボードから手が離れるのは、かなりのストレスなんじゃ!

  コンテナ名の部分一致でマッチしてくれりゃいいのに……などと、ブツブツ文句をいうヒマがあるならば、ラッパースクリプトを作ってしまえばいいのである。で、作った。コンテナ名の一部を入力すればマッチしてくれる。便利。

# docker ps -a
CONTAINER ID        IMAGE                                COMMAND                  CREATED             STATUS              PORTS                                         NAMES
b41353b0f15e        docker.io/furutanian/maverick        "bash startup.sh"        11 days ago         Up 11 days          0.0.0.0:8081->80/tcp                          maverick-gamma
d474d17534d1        docker.io/furutanian/hyperestraier   "bash startup.sh"        4 months ago        Up 2 weeks          0.0.0.0:8091->80/tcp                          hyperestraier-gamma
54eef26064e9        docker.io/furutanian/pinchmail       "bash -c 'bash sta..."   4 months ago        Up 2 weeks          0.0.0.0:8025->25/tcp, 0.0.0.0:8110->110/tcp   pinchmail-alpha
# docker_exec pin
# INTO [pinchmail-alpha].
[root@54eef26064e9 /]# ls
Dockerfile  bin  boot  crontab.index  dev  etc  extract.sh  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  startup.sh  sys  tmp  usr  var
[root@54eef26064e9 /]# exit
exit
# docker_logs pin
# INTO [pinchmail-alpha].
startup.sh start.
TZ='Asia/Tokyo'
'/etc/localtime' -> '/usr/share/zoneinfo/Asia/Tokyo'
 :
MAILTO=""
* * * * * cd /root/pinchmail; ./pinchmail
#__END1__crontab.index__
startup.sh done.

  ちなみに、docker_logsはdocker_execのシンボリックリンクである。スクリプト内で自らのスクリプト名を見て処理を替えている。

  で、しばらくは心穏やかに幸せに暮らしていたのだが、そのうち既製のコンテナを使う状況で、コンテナ内でnetstat等が実行できないことにイラつき始めた。「docker netstat」とググると、同じようにイラついている人は多いようだ。しかし、あまりロクな解法は見当たらない。コンテナ内で「cat /proc/net/tcp」して結果をデコードすりゃいいだけじゃん。そうなりゃ、docker_execに乗っけるしかないでしょ。コマンド名はdocker_netstatだな。

  で、作り始めたら、容易には「PID/Program name」欄が出力できないことに気づいた。自分は「netstat」といえば「-anp」な人なので、それは出したい。しかし、それを実現するには大きくふたつの障害がある。(1)コンテナ内で使えるコマンドは非常に限定的、(2)「docker exec」を介するので、基本ワンライナーで情報を得る必要がある。というわけで、それをクリアする解法は「ls -lR /proc」なのであった。どうよ、この再現度。

# docker_netstat pin
# INTO [pinchmail-alpha].
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 127.0.0.11:39751        0.0.0.0:0               LISTEN      -
tcp        0      0 0.0.0.0:110             0.0.0.0:0               LISTEN      55/dovecot
tcp        0      0 0.0.0.0:143             0.0.0.0:0               LISTEN      55/dovecot
tcp        0      0 0.0.0.0:25              0.0.0.0:0               LISTEN      130/master
tcp        0      0 172.18.0.3:110          172.18.0.2:60954        TIME_WAIT   -
tcp6       0      0 :::110                  :::0                    LISTEN      55/dovecot
tcp6       0      0 :::143                  :::0                    LISTEN      55/dovecot
tcp6       0      0 :::25                   :::0                    LISTEN      130/master
tcp6       0      0 ::1:55838               ::1:110                 TIME_WAIT   -
udp        0      0 127.0.0.11:47826        0.0.0.0:0               CLOSE       -
# docker exec pinchmail-alpha netstat -anp
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 127.0.0.11:39751        0.0.0.0:*               LISTEN      -                   
tcp        0      0 0.0.0.0:110             0.0.0.0:*               LISTEN      55/dovecot          
tcp        0      0 0.0.0.0:143             0.0.0.0:*               LISTEN      55/dovecot          
tcp        0      0 0.0.0.0:25              0.0.0.0:*               LISTEN      130/master          
tcp        0      0 172.18.0.3:110          172.18.0.2:60954        TIME_WAIT   -                   
tcp6       0      0 :::110                  :::*                    LISTEN      55/dovecot          
tcp6       0      0 :::143                  :::*                    LISTEN      55/dovecot          
tcp6       0      0 :::25                   :::*                    LISTEN      130/master          
tcp6       0      0 ::1:55838               ::1:110                 TIME_WAIT   -                   
udp        0      0 127.0.0.11:47826        0.0.0.0:*                           -                   

  とかなんとかやっていると、普通にコンテナ内でpsが実行できてもいいじゃねぇか、ということになって、やっぱり、docker_execに乗っけて、docker_psの誕生である。例によって、基本ワンライナーで情報を得る必要がある、というところで、かなり首をひねったが、内部でシェル芸をかませば、なんでもできることに気がついたのであった。どうよ、この再現度。

# docker_ps pin
# INTO [pinchmail-alpha].
UID          PID    PPID  C STIME TTY          TIME CMD
root           1       0  0     - -               - /sbin/init 
root          43       1  0     - -               - /usr/lib/systemd/systemd-journald 
root          50       1  0     - -               - /usr/lib/systemd/systemd-homed 
root          53       1  0     - -               - /usr/sbin/crond -n 
root          55       1  0     - -               - /usr/sbin/dovecot -F 
dbus          56       1  0     - -               - /usr/bin/dbus-broker-launch --scope system --audit 
dbus          59      56  0     - -               - dbus-broker --log 4 --controller 9 --machine-id a2b06096cef94996b35ec906189d7873 --max-bytes 536870912 --max-fds 4096 --max-matches 16384 --audit 
dovecot       62      55  0     - -               - dovecot/anvil 
root          63      55  0     - -               - dovecot/log 
root          64      55  0     - -               - dovecot/config 
root         130       1  0     - -               - /usr/libexec/postfix/master -w 
postfix      132     130  0     - -               - qmgr -l -t unix -u 
dovecot      135      55  0     - -               - dovecot/stats 
root         146       1  0     - -               - /usr/lib/systemd/systemd-userdbd 
postfix    59937     130  0     - -               - tlsmgr -l -t unix -u 
dovecot   147675      55  0     - -               - dovecot/auth 
root      159689     146  0     - -               - systemd-userwork                  
root      159697     146  0     - -               - systemd-userwork                  
root      159706     146  0     - -               - systemd-userwork                  
postfix   159723     130  0     - -               - pickup -l -t unix -u 
root      159730      55  0     - -               - dovecot/auth -w 
root      159738      55  0     - -               - dovecot/auth -w 
root      159740       0  0     - -               - 
# docker exec pinchmail-alpha ps -ef 
UID          PID    PPID  C STIME TTY          TIME CMD
root           1       0  0 Dec02 ?        00:00:35 /sbin/init
root          43       1  0 Dec02 ?        00:01:15 /usr/lib/systemd/systemd-journald
root          50       1  0 Dec02 ?        00:00:29 /usr/lib/systemd/systemd-homed
root          53       1  0 Dec02 ?        00:00:08 /usr/sbin/crond -n
root          55       1  0 Dec02 ?        00:00:57 /usr/sbin/dovecot -F
dbus          56       1  0 Dec02 ?        00:00:04 /usr/bin/dbus-broker-launch --scope system --audit
dbus          59      56  0 Dec02 ?        00:00:11 dbus-broker --log 4 --controller 9 --machine-id a2b06096cef94996b35ec906189d7873 --max-bytes 536870912 --max-fds 4096 --max-matches 16384 --audit
dovecot       62      55  0 Dec02 ?        00:00:21 dovecot/anvil
root          63      55  0 Dec02 ?        00:00:23 dovecot/log
root          64      55  0 Dec02 ?        00:01:02 dovecot/config
root         130       1  0 Dec02 ?        00:00:04 /usr/libexec/postfix/master -w
postfix      132     130  0 Dec02 ?        00:00:00 qmgr -l -t unix -u
dovecot      135      55  0 Dec02 ?        00:00:35 dovecot/stats
root         146       1  0 Dec02 ?        00:00:05 /usr/lib/systemd/systemd-userdbd
postfix    59937     130  0 Dec10 ?        00:00:00 tlsmgr -l -t unix -u
dovecot   147675      55  0 08:29 ?        00:00:02 dovecot/auth
root      159689     146  0 23:26 ?        00:00:00 systemd-userwork
root      159697     146  0 23:27 ?        00:00:00 systemd-userwork
root      159706     146  0 23:28 ?        00:00:00 systemd-userwork
postfix   159723     130  0 23:30 ?        00:00:00 pickup -l -t unix -u
root      159730      55  0 23:31 ?        00:00:00 dovecot/auth -w
root      159738      55  0 23:32 ?        00:00:00 dovecot/auth -w
root      159820       0  0 23:32 ?        00:00:00 ps -ef

  で、以下がdocker_execのコードである。さっき作ったトコなんで、考慮不足も多いだろうが。まずは、バージョン0.1ということで。

#!/usr/bin/env ruby
# coding: utf-8
 
class String
    def to_ipaddr
        r = self.scan(/.{8}/).map {|h8|
            h8.scan(/../).map {|hh|
                hh.to_i(16)
            }.reverse
        }.join('.')
        self.size < 9 ? r : r.gsub(/(0\.){3,}0?/, '::')
    end
end
 
states = [
    '', 'ESTABLISHED', 'SYN_SENT', 'SYN_RECV', 'FIN_WAIT1', 'FIN_WAIT2',
    'TIME_WAIT', 'CLOSE', 'CLOSE_WAIT', 'LAST_ACK', 'LISTEN', 'CLOSING',
]
 
$0 =~ /docker_(.+)/ and subcmd = $1
 
ps = `docker ps`
targets = []; ps.split(/\n/)[1..-1].each {|l|
    (it = l.split(/\s+/).last) =~ /#{ARGV.last}/ and targets << it
}
 
if(targets.size == 0)
    puts('# NOT MATCH...')
 
elsif(targets.size == 1)
 
    def get_ps(target)
        uids = {}; progs = {}; sockets = {}
        IO.popen(['docker', 'exec', target, 'ls', '-lR', '/proc'], :err => [:child, :out]) {|io|
            pid = nil; io.each {|line|
                if(!pid and line =~ /^d.*?(\d+)$/)
                    uids[$1] = line.split(/\s+/)[2]
                end
                if(line =~ /^\/proc\/(\d+):/)
                    pid = $1
                end
                if(line =~ / exe -> (.+)/)
                    progs[pid] ||= []
                    progs[pid] << $1
                end
                if(line =~ / -> socket:\[(\d+)\]/)
                    sockets[$1] ||= []
                    sockets[$1] << pid
                end
            }
        }
        [uids, progs, sockets]
    end
 
    def get_ps2(target)
        ppids = {}; cmdlines = {}
        IO.popen(['docker', 'exec', target, '/bin/bash', '-c',
            'ls /proc | grep -e "^[1-9]" | sed "s/\(.*\)/cat \/proc\/\\1\/status/" | sh 2>/dev/null'], :err => [:child, :out]) {|io|
            pid = nil; io.each {|line|
                line =~ /^Pid:\s*(\d+)/ and pid = $1
                line =~ /^PPid:\s*(\d+)/ and ppids[pid] = $1
            }
        }
        IO.popen(['docker', 'exec', target, '/bin/bash', '-c',
            'ls /proc | grep -e "^[1-9]" | sed "s/\(.*\)/echo -n \\1:; cat \/proc\/\\1\/cmdline; echo/" | sh 2>/dev/null'], :err => [:child, :out]) {|io|
            io.each {|line|
                line =~ /^(\d+):(.*)/ and cmdlines[$1] = $2.gsub(/\u0000/, ' ')
            }
        }
        [ppids, cmdlines]
    end
 
    puts('# INTO [%s].' % targets[0])
    if(subcmd == 'exec')
        # TODO
        system('docker exec -it %s %s /bin/bash' % [ARGV[0..-2].join(' '), targets[0]])
 
    elsif(subcmd == 'ps')
        uids, progs, sockets = get_ps(targets[0])
        ppids, cmdlines = get_ps2(targets[0])
        puts('UID          PID    PPID  C STIME TTY          TIME CMD')
        progs.keys.sort {|a, b|
            a.to_i <=> b.to_i
        }.each {|pid|
            puts('%-8s %7d %7d %2d %5s %-8s %8s %s' % [uids[pid], pid, ppids[pid] || 0, 0, '-', '-', '-', cmdlines[pid]])
        }
 
    elsif(subcmd == 'netstat')
        uids, progs, sockets = get_ps(targets[0])
        puts('Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name')
        ['tcp', 'tcp6', 'udp', 'udp6'].each {|prot|
            IO.popen(['docker', 'exec', targets[0], 'cat', '/proc/net/' + prot]) {|io|
                io.each {|line|
                    ls = line.split(/[:\s]+/)
                    ls[1] =~ /^\d/ or next
                    laddr = ls[2].to_ipaddr + ':' + ls[3].to_i(16).to_s
                    faddr = ls[4].to_ipaddr + ':' + ls[5].to_i(16).to_s
                    prog = '-'; (it = sockets[ls[14]]) and prog = '%s/%s' % [it[0], progs[it[0]][0].split('/').last]
                    puts('%-5s %6d %6d %-23s %-23s %-11s %-s' % [prot, ls[8].to_i(16), ls[7].to_i(16), laddr, faddr, states[ls[6].to_i(16)], prog])
                }
            }
            (it = $?.exitstatus and it == 0) or raise 'failed.'
        }
 
    else
        system('docker %s %s %s' % [subcmd, ARGV[0..-2].join(' '), targets[0]])
    end
 
else
    puts('# MULTIPLE MATCH...')
    puts(targets.join("\n"))
end
 
__END__

  というわけで、自画自賛するようではあるが、ちょっと今回のこれは、え!? いったい、どうやってんの!? と思わせるような、魔術的なコードになったのではないかと思う。ふはははは。