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|

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__

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


2023-01-28(Sat) 純正アルミホイールを購入

  ND型ロードスターの2型までのNR-Aグレードは、アルミホイールがシルバーである。たぶんクリアが乗せてあるだけの、着色していないアルミの色。自分はそれがすごく気に入っているのだが、現行モデルは暗色ばかりなので、ディスコンになってしまったら困るなぁ、と思っていた。モノタロウではマツダを含む自動車メーカ各社の純正パーツが買えるのだが、件の「9965-G3-6560」は「取扱終了」になってしまっているのだ。

  ところが、車検のついでにディーラーで聞いてみると、旧い仕様のパーツも減ってきたら増産するので、ずっと買えるのだという。改めて問い合わせてみると、品番が「9965-P2-6560」に変わっているが買えるとのこと。値段は定価で16,000円+税。社外品に比べるとエラく安い。ほんじゃ、買います、買います。

  というわけで、数日で届いた。やはり、キズが付かないようにオモテ面には薄いスポンジが載せてあるなど、丁寧に梱包されていた。コレだよコレ。美しいよなぁ。

  画像の説明

  画像の説明

  画像の説明

  ディーラーは気を利かせてゴムバルブも手配してくれていたが、そこはアルミのバルブを手配済みなので謝意だけ伝えると「予備用ですか? タイヤの組み込みとか、まさかご自分で?」と聞かれたので、そのまさかだと答えると驚かれてしまった。まぁ、物好きなものでw。

  画像の説明 画像の説明

  ついでに、P51N-13-172という部品も500円チョイで購入。これはそのうちちょっとした工作をするためのもの。うっしっし。


2023-01-29(Sun) タイヤの憂いを断つ

  というわけで自分でタイヤの組み込みをするために、もはや通い慣れた近所のレンタルピットに向かう。

  もうタイヤの組み込み作業も慣れたもの……といいたいところだが、久々にホイールバランサを使おうと思ったら、使い方を忘れてしまっていて、ホイールの中心付近に軽くキズを付けてしまった。

  前々々回の作業でも、タイヤを外す際に、タイヤのリムを載せるところを間違えてちょっとやらかしてしまったのだが、やらかし対象は違うとはいえ、どうも作業をやり始めると思い込みによる間違いに気づけずに強行気味に作業を進めてしまうのが悪いクセだ。

  もちろん各々の失敗からは学べるのだが、そもそも失敗しないやり方を学びたい。それは「気づかないことに気づけよ」みたいなムチャな話ではあるのだろうが、そういう思考のクセもきっとあると思うんだよな。

  で、タイヤの組み込みは一発でできたのだが、今度は軽点合わせを忘れてしまう……んー、まさにそういうとこなんだけどな。バランサで調べると外側に50g。んが、敢えてウェイトは貼らずに済ます。自分はほとんど高速走行をしないので、さほど必須でないことがわかったからだ。作業終了。

  画像の説明

  帰宅して、スローパンクチャを起こしているセットと交換。ついでに、4本とも外してタイヤの裏側もチェックし、コンパウンドでホイールのオモテ面を磨いた。5年経つが、キズらしいキズはほとんどない。よしよし。

  画像の説明

  半端に降った雪でマダラだったボディを洗車する。新しいホイールは水を弾くんだな。なんとも瑞々しい。そして近所を軽くドライブ。お気に入りの峠道には、ところどころ雪が残っていて、ちょっと危うかった。しかし、これで1年以上もゴタゴタしていたタイヤ問題も完全解決……のはず。来月に予定している超ロングドライブが楽しみである。