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|07|08|

2005-01-22(Sat) ARMADA-M300バッテリセル交換完了!!

  ピンポンの音で目を覚ます。目をこすりながら玄関を開けると届けものだ。おぅ!! これは先日注文したノートPC用のバッテリセル。届いたねぇ。うぴうぴ。

  画像の説明

  早速、中を開けると……おわ!? 横に4本つながっとるぞ? 注文は1本単位だったのに、こうやって送られてくるのもアリなんかい。「未使用ノート用バッテリーからの取り外し品」とは書いてあったが、まさにジャンク扱いである。上の写真ではキレイにしてしまったが、ムリにチョン切ったようなコードがくっ付いていたり、妙な接着剤のカスが付いていたりもした。しかし、この端子の状態はなんだ? 4本並列になっている。これだと3.6Vしか取れないと思うのだが、ホントにノートPCから取り外したのだろうか?

  軽くもう一眠りしてから遅い朝ご飯を終えると、カミさんが以前に使っていた風呂場用ラジオを出してきた。ラジオを聞きながらゆっくり風呂に入りたいと思ったのだが、音が鳴らないとのコト。んなもん、治しちゃる。ラジオなんてどうせ大した構造でもあるまい……。

  画像の説明 画像の説明

  ゲゲゲゲゲッ!! 開けてびっくり。ものすんごいキタナイ。まぁ、1年くらい風呂に置いてあったから当然といえば当然ではあるが、コレぜんぜん防水になってないやん。というか、厳密に言うと防沫だったかもしれんが。にしても、触る気にならないくらいキタナくなっている。あまりにキタナイので右の写真はモザイクをかけてみた。見たくない人はクリックしないコト。

  基本的には「スイッチ付きボリューム」がサビ付いているのが問題なのだろうコトはわかったが、あまりにキタナイので治す気が失せてしまった。一応、基板も外してはみたのだが、裏は白カビに覆われているし……下に敷いていたゴミ袋でグルっと巻いてゴミ箱へ。さようなら。キミのコトは忘れない。

  しばらくグダグダしたあと、今度はさっきのバッテリセルに手を出してみた。まずは4本をつないでいる電極を引き剥がす。スポット溶接というのかな? 電極ごとに線香で焼いたようにポツポツと4点ずつ溶接されている。そんな電極板を巻き取るようにラジオペンチで引き剥がす。結構キレイに取れた。あとは4本をつなげている黒いガム状の接着剤だが、つながっている電池を折るように力を加えたらペロンと剥がれる。あっさり4本はバラバラになった。

  画像の説明

  でもって、今度は先日バラしたPC側のバッテリを再びバラす。こちらはバッテリの制御基板から5本のリード線が出ている。どうやら4本のバッテリの端と間に接続されているようだ。リード線は電極にハンダ付けされ、その電極は電池にスポット溶接されているので、上記のようにラジオペンチで引き剥がす。

  画像の説明 画像の説明

  さぁ、後はバッテリケース内に新しいバッテリセルをセットすれば完了だ。んが、ここで困ったのが「基本的に電池はハンダ付け厳禁」という事実だ。電池を高温にすると「防爆弁」という破裂防止用の弁がムニッと開いて使用不可になるのだ。あくまで防爆弁は安全装置であるから、うまく働かない場合はマジで破裂する可能性さえある。なんでも、電極側にハンダを乗せて溶かした状態にし「そいやっ」とばかりに電池に押し当てることで、極端に電池の温度を上げることなくハンダ付けする方法もあるらしいのだが、それでも完全に安全ではないので最後の手段にしたい。

  で、どうするか。バッテリケース側の引き剥がした電極をラジオペンチでそれなりに整形し、単純にバッテリセルをハメ込んでみた……こんないい加減な方法でいいわけないよなぁ……て、あれ? ちゃんと電圧が出ちまったぞ。バッテリケースがギリギリのサイズであることが幸いし、ハメ込んだだけで各端子が十分に接触してしまったようだ。うひょー、安直この上ないが、ケースの両端をガムテープで巻いて工作完了である。

  画像の説明

  スグさまPCに取り付けて充電を開始。30分ほどでバッテリ本体のLEDインジケータは80%を示した。そこで起動して「電源オプションのプロパティ」を開いて少し待つ……が、70%以上に増えない。なんだか「調整」とかいうボタンが出ているのでそれを押しつつ、COMPAQのページでこの機種のマニュアルを確認すると、新しいバッテリを使う場合は調整ボタンを押して電源を落とさず数時間待てとある。なんでも完全充放電して、バッテリセルの能力を確認するらしい。

  結局、4〜5時間かかっただろうか? 無事にバッテリは充電100%を示し、調整は完了した模様だ……が、もう4時近いっす。寝るっす。


2006-01-22(Sun) 巻き取り、先に立たず

  朝から、かなり強力な、吐くギリギリの二日酔い。オイラは吐くのとか、頭が痛いのとか好きじゃないので、ちょっと反省。反省しつつ、結局、昼までゴロゴロしてしまう。無駄な時間だ……。

  昼過ぎに起き出して、早速、昨日の巻き取り式イヤフォンをイジってみる……んが、動きがシブい。伸張はともかく、巻き取りがスムーズにいかない。まぁ、値段と見た目から、過度の期待はしてなかったが、これは返品モノだな……だが、オイラはこれをバラして、手持ちのステレオ延長コードを挟み込み、改造する予定なのだからして……

  「ビヨヨヨーン!!」

  画像の説明

  ……だーッ!! 昨日から、不安に思っていたのだが、やっぱり的中してしまった……こーゆーのって、バラすと、元には戻らないんだよねぇ。1時間くらい格闘してみたが、どうしても元に戻らない。バネを巻くだけでも大変なのに、同時にリールにコードを巻きつけつつ、さらに謎の玉をハサみ込まねばならないのだ……ム……ム……ムリィィィィィッ!! うまく改造できたら、ブログのネタにできたのに……どっちにしろブログのネタにはなったが……こんなことなら、あきばお〜で巻き取り式の延長コードも買っておけばよかった。後悔……とほほ。

  画像の説明

  しょんぼりしながら、もうひとつの獲物である、USBメモリを取り出した。こっちはたいして遊びのネタにはならないが、まぁ、小さいながらもたいした質感で、ちょっと所有欲を満たしてくれる。フラッシュメモリというと、書き換え回数が有限というのが、なんとなくハカナさを演出するので、どうにも心にひっかかり、どーしてもこのインモータルな感じのアルミの削り出しの外観とのミスマッチングを感じるのだが……まぁ、書き換え回数が有限とはいっても10万回オーバとかだろうから、気にするほどではないのだろうが……なんつーか……ねぇ……百万パケット以降は有料ってのと、完全に使い放題ってのとの気分の違いっていうか。

  なんかまとまりがないが、まぁ、そーゆーまとまりのないウダウダな昼下がりであった。ふみふみ。


2007-01-22(Mon) 続・フォネる

  あ、以下は、昨日の作業で出力させた起動ログである。結構フツーなカーネルメッセージだねぇ、ふんふん。

+PHY ID is 0022:5521
Ethernet eth0: MAC address 00:18:84:xx:xx:xx
IP: 0.0.0.0/255.255.255.255, Gateway: 0.0.0.0
Default server: 0.0.0.0
 
RedBoot(tm) bootstrap and debug environment [ROMRAM]
Non-certified release, version v1.3.0 - built 16:57:58, Aug  7 2006
 
Copyright (C) 2000, 2001, 2002, 2003, 2004 Red Hat, Inc.
 
Board: ap51 
RAM: 0x80000000-0x81000000, [0x80040450-0x80fe1000] available
FLASH: 0xa8000000 - 0xa87f0000, 128 blocks of 0x00010000 bytes each.
== Executing boot script in 1.000 seconds - enter ^C to abort
RedBoot> fis load -l vmlinux.bin.l7
Image loaded from 0x80041000-0x801ba000
RedBoot> exec
Now booting linux kernel:
 Base address 0x80030000 Entry 0x80041000
 Cmdline : 
CPU revision is: 00019064
Primary instruction cache 16kB, physically tagged, 4-way, linesize 16 bytes.
Primary data cache 16kB, 4-way, linesize 16 bytes.
Linux version 2.4.32 (iurgi@ropero) (gcc version 3.4.6 (OpenWrt-2.0)) #9 jue nov 23 12:11:45 UTC 2006
Determined physical RAM map:
 memory: 01000000 @ 00000000 (usable)
On node 0 totalpages: 4096
zone(0): 4096 pages.
zone(1): 0 pages.
zone(2): 0 pages.
Kernel command line: console=ttyS0,9600 rootfstype=squashfs,jffs2  
Using 92.000 MHz high precision timer.
Calibrating delay loop... 183.50 BogoMIPS
Memory: 14188k/16384k available (1327k kernel code, 2196k reserved, 92k data, 68k init, 0k highmem)
Dentry cache hash table entries: 2048 (order: 2, 16384 bytes)
Inode cache hash table entries: 1024 (order: 1, 8192 bytes)
Mount cache hash table entries: 512 (order: 0, 4096 bytes)
Buffer cache hash table entries: 1024 (order: 0, 4096 bytes)
Page-cache hash table entries: 4096 (order: 2, 16384 bytes)
Checking for 'wait' instruction...  available.
POSIX conformance testing by UNIFIX
Linux NET4.0 for Linux 2.4
Based upon Swansea University Computer Society NET3.039
Initializing RT netlink socket
Starting kswapd
devfs: v1.12c (20020818) Richard Gooch (rgooch@atnf.csiro.au)
devfs: boot_options: 0x1
JFFS2 version 2.1. (C) 2001 Red Hat, Inc., designed by Axis Communications AB.
squashfs: version 3.0 (2006/03/15) Phillip Lougher
pty: 256 Unix98 ptys configured
Serial driver version 5.05c (2001-07-08) with no serial options enabled
ttyS00 at 0xb1100003 (irq = 37) is a 16550A
eth0: Dropping NETIF_F_SG since no checksum feature.
eth0: Atheros AR2313: 00:18:84:xx:xx:xx, irq 4
MTD driver for SPI flash.
spiflash: Probing for Serial flash ...
spiflash: Found SPI serial Flash.
8388608: size
Creating 8 MTD partitions on "spiflash":
0x00000000-0x00030000 : "RedBoot"
0x00030000-0x00720000 : "rootfs"
eth0: Configuring MAC for full duplex
0x001b0000-0x00720000 : "rootfs1"
0x00720000-0x00730000 : "config"
0x00730000-0x007e0000 : "vmlinux.bin.l7"
0x007e0000-0x007ef000 : "FIS directory"
mtd: partition "FIS directory" doesn't end on an erase block -- force read-only
0x007ef000-0x007f0000 : "RedBoot config"
mtd: partition "RedBoot config" doesn't start on an erase block boundary -- force read-only
0x007f0000-0x00800000 : "board_config"
Initializing Cryptographic API
NET4: Linux TCP/IP 1.0 for NET4.0
IP Protocols: ICMP, UDP, TCP, IGMP
IP: routing cache hash table of 512 buckets, 4Kbytes
TCP: Hash tables configured (established 1024 bind 2048)
ip_conntrack version 2.1 (5953 buckets, 5953 max) - 328 bytes per conntrack
ip_tables: (C) 2000-2002 Netfilter core team
NET4: Unix domain sockets 1.0/SMP for Linux NET4.0.
NET4: Ethernet Bridge 008 for NET4.0
802.1Q VLAN Support v1.8 Ben Greear <greearb@candelatech.com>
All bugs added by David S. Miller <davem@redhat.com>
VFS: Mounted root (squashfs filesystem) readonly.
Mounted devfs on /dev
Freeing unused kernel memory: 68k freed
init started:  BusyBox v1.1.3 (2006.11.21-19:49+0000) multi-call binary
Algorithmics/MIPS FPU Emulator v1.5
 
Please press Enter to activate this console. Registering mini_fo version $Id$
mini_fo: using base directory: /
mini_fo: using storage directory: /jffs
jffs2.bbc: SIZE compression mode activated.
wlan: 0.8.4.2 (0.9.0)
ath_hal: 0.9.17.1 (AR5212, AR5312, RF5112, RF2316, RF2317, TX_DESC_SWAP)
wlan: mac acl policy registered
ath_rate_sample: 1.2 (0.9.0)
ath_ahb: 0.9.4.5 (0.9.0)
ath_pci: switching rfkill capability off
wifi0: 11b rates: 1Mbps 2Mbps 5.5Mbps 11Mbps
wifi0: 11g rates: 1Mbps 2Mbps 5.5Mbps 11Mbps 6Mbps 9Mbps 12Mbps 18Mbps 24Mbps 36Mbps 48Mbps 54Mbps
wifi0: H/W encryption support: WEP AES AES_CCM TKIP
wifi0: mac 11.0 phy 4.8 radio 7.0
wifi0: Use hw queue 1 for WME_AC_BE traffic
wifi0: Use hw queue 0 for WME_AC_BK traffic
wifi0: Use hw queue 2 for WME_AC_VI traffic
wifi0: Use hw queue 3 for WME_AC_VO traffic
wifi0: Use hw queue 8 for CAB traffic
wifi0: Use hw queue 9 for beacons
wifi0: Atheros 2315 WiSoC: mem=0xb0000000, irq=3
Universal TUN/TAP device driver 1.5 (C)1999-2002 Maxim Krasnyansky
device eth0 entered promiscuous mode
 
 
 
BusyBox v1.1.3 (2006.11.21-19:49+0000) Built-in shell (ash)
Enter 'help' for a list of built-in commands.
 
 _______  _______  _______ 
|   ____||       ||   _   |
|   ____||   -   ||  | |  |
|   |    |_______||__| |__|
|___|
 
 Fonera Firmware (Version 0.7.1 rev 2) -------------
  * 
  * Based on OpenWrt - http://openwrt.org
  * Powered by FON - http://www.fon.com
 ---------------------------------------------------
root@OpenWrt:/# cat /proc/cpuinfo
system type		: Atheros AR531X_COBRA
processor		: 0
cpu model		: MIPS 4KEc V6.4
BogoMIPS		: 183.50
wait instruction	: yes
microsecond timers	: yes
tlb_entries		: 16
extra interrupt vector	: yes
hardware watchpoint	: no
VCED exceptions		: not available
VCEI exceptions		: not available
root@OpenWrt:/# ps -ef
  PID  Uid     VmSize Stat Command
    1 root        396 S   init       
    2 root            SW  [keventd]
    3 root            SWN [ksoftirqd_CPU0]
    4 root            SW  [kswapd]
    5 root            SW  [bdflush]
    6 root            SW  [kupdated]
    8 root            SW  [mtdblockd]
   16 root        392 S   syslogd -C 16 
   17 root        444 S   /bin/sh /etc/init.d/rcS 
   18 root        380 S   logger -s -p 6 -t  
   20 root        488 S   /bin/ash --login 
   22 root        360 S   klogd 
   49 root            SWN [jffs2_gcd_mtd2]
  113 root        284 S   lock /var/run/network-connection 
  115 root        284 S   lock /var/run/restart-services 
  221 root        448 S   hostapd -B /tmp/hostapd.conf 
  253 nobody      412 S   dnsmasq -C /etc/dnsmasq.conf --dhcp-range=192.168.10.
  265 root        388 S   udhcpc -i eth0 -R 
  399 root        420 S   httpd -p 80 -h /www -r OpenWrt 
  441 root        424 S   crond -c /etc/crontabs 
  456 root        424 S   /usr/sbin/httpd -R /cgi-bin/splash.sh -H 192.168.10.1
  460 root        328 S   watchdog -t 5 /dev/misc/watchdog 
  461 root        328 D   watchdog -t 5 /dev/misc/watchdog 
  462 root        276 S   lock -w /var/run/network-connection 
  468 root        368 R   ps -ef 
root@OpenWrt:/# iptables -L
Chain INPUT (policy DROP)
target     prot opt source               destination         
DROP       tcp  --  anywhere             anywhere            tcp dpt:80 
INPUT_CFG  all  --  anywhere             anywhere            
NET_ACCESS  all  --  anywhere             anywhere            
DROP       all  --  anywhere             anywhere            state INVALID 
ACCEPT     all  --  anywhere             anywhere            state RELATED,ESTABLISHED 
DROP       tcp  --  anywhere             anywhere            tcp option=!2 flags:SYN/SYN 
input_rule  all  --  anywhere             anywhere            
ACCEPT     all  --  169.254.0.0/16       anywhere            
ACCEPT     all  --  anywhere             anywhere            
ACCEPT     icmp --  anywhere             anywhere            
ACCEPT     gre  --  anywhere             anywhere            
REJECT     tcp  --  anywhere             anywhere            reject-with tcp-reset 
REJECT     all  --  anywhere             anywhere            reject-with icmp-port-unreachable 
 
Chain FORWARD (policy DROP)
target     prot opt source               destination         
DROP       all  --  anywhere             anywhere            state INVALID 
TCPMSS     tcp  --  anywhere             anywhere            tcp flags:SYN,RST/SYN TCPMSS clamp to PMTU 
ACCEPT     all  --  anywhere             anywhere            state RELATED,ESTABLISHED 
forwarding_rule  all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere            
 
Chain OUTPUT (policy DROP)
target     prot opt source               destination         
DROP       all  --  anywhere             anywhere            state INVALID 
ACCEPT     all  --  anywhere             anywhere            state RELATED,ESTABLISHED 
output_rule  all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere            
REJECT     tcp  --  anywhere             anywhere            reject-with tcp-reset 
REJECT     all  --  anywhere             anywhere            reject-with icmp-port-unreachable 
 
Chain INPUT_CFG (3 references)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere            
 
Chain NET_ACCESS (3 references)
target     prot opt source               destination         
ACCEPT     tcp  --  anywhere             anywhere            tcp dpt:3990 
ACCEPT     udp  --  anywhere             anywhere            udp dpt:53 
ACCEPT     tcp  --  anywhere             anywhere            tcp dpt:53 
WAN_HOOK   all  --  anywhere             anywhere            
DROP       all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere            
DROP       all  --  anywhere             anywhere            
 
Chain WAN_HOOK (1 references)
target     prot opt source               destination         
DROP       all  --  anywhere             169.254.0.0/16      
 
Chain forwarding_rule (1 references)
target     prot opt source               destination         
INPUT_CFG  all  --  anywhere             anywhere            
INPUT_CFG  all  --  anywhere             anywhere            
NET_ACCESS  all  --  anywhere             anywhere            
NET_ACCESS  all  --  anywhere             anywhere            
 
Chain input_rule (1 references)
target     prot opt source               destination         
 
Chain output_rule (1 references)
target     prot opt source               destination         
root@OpenWrt:/# reboot
root@OpenWrt:/# The system is going down NOW !!
Sending SIGTERM to all processes.
Please stand by while rebooting the system.
Restarting system.

2023-01-22(Sun) dockerのコンテナ内でもっとアレしたい

  年末に「今年のまとめ」としてアレコレ書きたかったのだが、ほかにもヤリたいことだらけで、まとめられないまま1月も下旬になってしまった。まぁ、反省や抱負も大事だが、ヤリたいことがあるうちは、それをヤルことが優先である。反省や抱負は一段落してからにしよう。

  去年から今年にかけてプログラムをする機会が多い。公私ともに。仕事環境は劣化の一途でいっそヤメたろうかとまで思っているが、割と好きなことをできているので、まさにイタしカユしである。

  最近は、コンテナで動かすことを前提にしたプログラムをすることが多く、ちょうど1年前くらいに作ったdockerのコンテナ内でアレしたいのツール群が大活躍中なのであるが、活躍しているからこそ、先に面倒だから実装を省いた「プロセスの起動時間やCPU時間」が見たくなってきてしまった。

  というわけでサクッと実装である。

# docker_ps ldap-
# INTO [ldap-alpha].
UID          PID    PPID  C STIME TTY          TIME CMD
root           1       0  0 11:44 -        00:00:00 /sbin/init 
root          26       1  0 11:44 -        00:00:00 /usr/lib/systemd/systemd-journald 
root          36       1  0 11:44 -        00:00:00 /usr/lib/systemd/systemd-homed 
dbus          44       1  0 11:44 -        00:00:00 /usr/bin/dbus-broker-launch --scope system --audit 
dbus          53      44  0 11:44 -        00:00:00 dbus-broker --log 4 --controller 9 --machine-id a6cd51e94fd74eb98afdf11c55965591 --max-bytes 536870912 --max-fds 4096 --max-matches 16384 --audit 
ldap          54       1  0 11:44 -        00:00:00 /usr/sbin/slapd -u ldap -h ldap:/// ldaps:/// ldapi:/// 
root        1287       0  0       -                 
# docker exec ldap-alpha ps -efww
UID          PID    PPID  C STIME TTY          TIME CMD
root           1       0  0 11:44 ?        00:00:00 /sbin/init
root          26       1  0 11:44 ?        00:00:00 /usr/lib/systemd/systemd-journald
root          36       1  0 11:44 ?        00:00:00 /usr/lib/systemd/systemd-homed
dbus          44       1  0 11:44 ?        00:00:00 /usr/bin/dbus-broker-launch --scope system --audit
dbus          53      44  0 11:44 ?        00:00:00 dbus-broker --log 4 --controller 9 --machine-id a6cd51e94fd74eb98afdf11c55965591 --max-bytes 536870912 --max-fds 4096 --max-matches 16384 --audit
ldap          54       1  0 11:44 ?        00:00:00 /usr/sbin/slapd -u ldap -h ldap:/// ldaps:/// ldapi:///
root        1356       0  0 12:07 ?        00:00:00 ps -efww

  で、以下がdocker_execのコードである。

#!/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+):/)
					progs[pid = $1] ||= []
				end
				if(line =~ / exe -> (.+)/)
					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
 
	def get_ps3(target)
		start_times = {}; cpu_times = {}
		btime = nil
		IO.popen(['/bin/bash', '-c', 'cat /proc/stat'], :err => [:child, :out]) {|io|
			io.each {|line|
				line =~ /^btime\s+(\d+)/ and btime = $1.to_i and break
			}
		}
		now_a = Time.now.to_a
		IO.popen(['docker', 'exec', target, '/bin/bash', '-c',
			'ls /proc | grep -e "^[1-9]" | sed "s/\(.*\)/cat \/proc\/\\1\/stat/" | sh 2>/dev/null'], :err => [:child, :out]) {|io|
			io.each {|line|
				if(line =~ /(\d+)\s+\([^)]+\)\s+(.+)/)
					pid = $1
					stats = $2.split(/\s/)
					cpu_time = (stats[11].to_i + stats[12].to_i) / 100	# 11:utime + 12:stime
					days = cpu_time / 86400
					cpu_times[pid] = (days > 0 ? '%2d-' % days : '') + Time.at(cpu_time).utc.strftime('%H:%M:%S')
					start_time = Time.at(btime + stats[19].to_i / 100)	# 19:start_time
					start_time_a = start_time.to_a
					if(now_a[5] != start_time_a[5])
						start_times[pid] = '%5d' % start_time.year
					elsif(now_a[7] != start_time_a[7])
						start_times[pid] = start_time.strftime('%b%d')
					else
						start_times[pid] = start_time.strftime('%H:%M')
					end
				end
			}
		}
		[start_times, cpu_times]
	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])
		start_times, cpu_times = get_ps3(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, start_times[pid], '-', cpu_times[pid], 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__

  結局、去年書いたコードに特段のバグは見つからず、ほぼ純粋に処理を追加しただけで実装できた。こういうのが、なんとも気分がいいんだよなぁ。