カテゴリ "IT" のエントリ

PowerShell と bash で任意のコマンドの出力の全行頭にタイムスタンプを付ける

Tera Team でログを取るときの “タイムスタンプ” オプションみたいなことを、OS のネイティブの機能でやりたいシーンがあった。一時的な人力監視とか作業の証跡とかで。

以下、Windows の場合(PowerShell)と Linux の場合(bash)のそれぞれで。

Windows の場合(PowerShell)

ワンライナでやる

こうする。

<任意のコマンド> | foreach-object {(get-date -f "[yyyy/MM/dd HH:mm:ss.ff] ") + "$_"}

コマンドによっては表示が崩れるので、その場合は Out-String -Stream を通してやるとだいたいうまくいく。

<任意のコマンド> | out-string -stream | foreach-object {(get-date -f "[yyyy/MM/dd HH:mm:ss.ff] ") + "$_"}

結果、こうなる。

PS> ping 8.8.8.8 -t | foreach-object {(get-date -f "[yyyy/MM/dd HH:mm:ss.ff] ") + "$_"}
[2015/11/02 01:04:43.31]
[2015/11/02 01:04:43.32] 8.8.8.8 に ping を送信しています 32 バイトのデータ:
[2015/11/02 01:04:43.32] 8.8.8.8 からの応答: バイト数 =32 時間 =7ms TTL=56
[2015/11/02 01:04:44.32] 8.8.8.8 からの応答: バイト数 =32 時間 =9ms TTL=56
[2015/11/02 01:04:45.32] 8.8.8.8 からの応答: バイト数 =32 時間 =4ms TTL=56
[2015/11/02 01:04:46.32] 8.8.8.8 からの応答: バイト数 =32 時間 =12ms TTL=56

関数にする

関数にする場合は、例えばこんな感じ。

function add-timestamp {
	[cmdletbinding()]
	param (
		[parameter(valuefrompipeline = $true, mandatory = $true)][psobject] $object,
		[string] $format = "[yyyy/MM/dd HH:mm:ss.ff] ",
		[switch] $trim
	)
 
	process {
		$object | foreach-object {
			if ($trim) {
				(get-date -f $format) + "$_".trimend()
			} else {
				(get-date -f $format) + "$_"
			}
		}
	}
}

-format(-f でもよい)で任意のフォーマットを指定できる。何も指定しなければデフォルト(”[yyyy/MM/dd HH:mm:ss.ff] “)。

-trim(-t でもよい)は、行末の不要な空白を削除するオプション。なにかの結果を format-table してから add-timestamp に渡すと、行バッファがあふれて折り返されて、全行間に空行が入って見えることがあるので、これを見掛け上抑止するためのもの。

使うときはこんな感じ。ワンライナの場合と同様、場合によっては out-string -stream を噛ませた方がよさそう。

<任意のコマンド> | add-timestamp
<任意のコマンド> | add-timestamp -f "<HH:mm:ss> "
<任意のコマンド> | add-timestamp -t
<任意のコマンド> | out-string -stream | add-timestamp

結果、こうなる。

PS> ping 8.8.8.8 -t | add-timestamp
[2015/11/02 01:16:18.65]
[2015/11/02 01:16:18.65] 8.8.8.8 に ping を送信しています 32 バイトのデータ:
[2015/11/02 01:16:18.66] 8.8.8.8 からの応答: バイト数 =32 時間 =4ms TTL=56
[2015/11/02 01:16:19.66] 8.8.8.8 からの応答: バイト数 =32 時間 =4ms TTL=56
[2015/11/02 01:16:20.66] 8.8.8.8 からの応答: バイト数 =32 時間 =5ms TTL=56
[2015/11/02 01:16:21.66] 8.8.8.8 からの応答: バイト数 =32 時間 =8ms TTL=56

Linux の場合(bash)

ワンライナでやる

こうする。

<任意のコマンド> | awk '{print strftime("[%Y/%m/%d %I:%M:%S] ") $0}'

strftime() はミリ秒単位の表示ができないっぽい。date で代替もできなそう[1]だし、しかたない。

結果、こうなる。

[kuro@localhost ~]$ vmstat 1 | awk '{print strftime("[%Y/%m/%d %I:%M:%S] ") $0}'
[2015/11/01 05:04:04] procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----
[2015/11/01 05:04:04]  r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
[2015/11/01 05:04:04]  1  0      0 483204  23324 363936    0    0   145     2   32   44  0  1 99  0  0
[2015/11/01 05:04:05]  0  0      0 483172  23324 363960    0    0     0     0   26   36  0  0 100  0  0
[2015/11/01 05:04:06]  0  0      0 483172  23324 363960    0    0     0     0   26   36  0  0 100  0  0
[2015/11/01 05:04:07]  0  0      0 483172  23324 363960    0    0     0     0   27   42  0  0 100  0  0

関数にする

関数にする場合は、例えばこんな感じ。

#!/bin/bash
function add-timestamp () {
        f="[%Y/%m/%d %I:%M:%S] "
        for opt in "$@"; do
                case "$opt" in
                        '-f' | '-format' )
                                f="$2"
                                ;;
                esac
        done
        cat - | awk "{print strftime(\"$f\") \$0}"
}

-format(-f でもよい)で任意のフォーマットを指定できる。何も指定しなければデフォルト(”[%Y/%m/%d %I:%M:%S] “)。

こうやってつかう。

<任意のコマンド> | add-timestamp
<任意のコマンド> | add-timestamp -f "<%I:%M:%S> "

結果、こうなる。

[kuro@localhost ~]$ vmstat 1 | add-timestamp
[2015/11/01 05:18:48] procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----
[2015/11/01 05:18:48]  r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
[2015/11/01 05:18:48]  2  0      0 482800  23648 364060    0    0   110     2   30   42  0  0 99  0  0
[2015/11/01 05:18:49]  0  0      0 482768  23648 364060    0    0     0     0   33   46  0  1 99  0  0
[2015/11/01 05:18:50]  0  0      0 482768  23648 364060    0    0     0     0   27   38  0  0 100  0  0
[2015/11/01 05:18:51]  0  0      0 482768  23648 364060    0    0     0     0   23   37  0  0 100  0  0

どうにかしてミリ秒出せないかな、これ。


  1. やってみたら全行のタイムスタンプが同じ時刻になってダメだった []

自分が他校の何期生相当かすぐわかる、ギター合奏クラスタ用 Web サービス『多摩高期数変換機』をつくった

背景

ギター合奏界隈で集まってお互いに自己紹介するときに、『○○高校の△期の□□です』という言い方をよくします。ぼくでいえば、『多摩高校の 48 期の黒井です』といった具合ですね。

これ、同じ学校であればすぐにどの世代か理解できて自分との関係性も導き出せるのですが、当然ながら他校の数字で言われてもよくわかりません。それどころか、学校によっては、”期” ではなく定期演奏会の “回” で数えているところもあります。

もちろん、他校出身の友人がいるのであれば、そのひとを基準に計算することは容易いし、慣れてくれば自分の頭の中に対応表が出来上がってくるものです。最近では『多摩高校換算で××期相当』と自己紹介に最初から含めてくる強者もよく目にするようになりました。

とはいえ、そういうコミュニティの空気に慣れるまでは、それはなかなかできるものではありません。

相手の世代がわかることで、初対面でも、コンクールで弾いていた曲、交流会であったできごと、共通の先輩や後輩など、話題の幅がかんたんに広がります。とくに相手が自分に近い代である場合はなおさらで、思い出話に花を咲かせやすくなるというものです。

そんなわけで、初対面でも話のきっかけを増やせるかもしれない仕組みのひとつとして、これを作りました。

……もともとこういう変換機構は欲しいなあとは思ってはいたのですが、実装に着手したいちばん直接的な理由は、最近老害おじさん友人がこんなことをやっていたからです。

作ったもの

これです。

多摩高期数変換機

これは、中学や高校でギター合奏を行う部活動や同好会に所属している、または所属していた方々を対象にした、

  • 自分の学校名と期数』か『自分の学校名と引退時の定期演奏会の回数』か『自分の誕生年度』を入力すると
  • 自分がほかの学校では何期生に相当するのか、第何回の定期演奏会の代かがわかる

という機能をもつ Web サービスです。

つかいかた

スマートフォン世代の方々にはすぐ馴染めるようなインタフェイスにしたつもりです。

  1. 最上段のタブで変換方法を選びます
    • [期から] は、[学校] と [] を元に計算します
    • [定演から] は、[学校] と [引退時の定演] を元に計算します
    • [誕生年度から] は、[誕生年度] を元に計算に変換します
  2. 変換方法に応じた入力欄が表示されるので、すべての欄で適切な値を選択します
  3. 入力が完了すると、画面下部に結果が表示されます
  4. お好みで [結果をツイートする] ボタンでツイートします
使い方

使い方

また、右上の [設定] ボタンからは、いくつか挙動を任意で変更できます。設定は任意のタイミングで変更可能で、変更は即座に結果に反映されます。

設定

設定

[定演の回を表示する] のチェックを入れると、計算結果に期数だけでなく、その期の代が引退したときの定期演奏会の回数も併せて表示されます。デフォルトは無効です。なお、定期演奏会の回数はツイートには含まれません。

[マイナス表示を許可する] のチェックを入れると、”1 期” のひとつ上を “0 期”、もうひとつ上を “-1 期”…… とさかのぼって表示するようになります。デフォルトは無効で、”1 期” より上の代はすべて “-” と表示します。”1 期” のひとつ上を “0 期” にするべきか “-1 期” にするべきかは議論の余地がありますが、実装がラクなのでひとまず “0 期” にしています。

考えたことというか工夫というか

世代の区別の根拠は学校によって “期” だったり “回” だったりといろいろなので、そういった差を吸収するため、複数の変換方法を用意しました。

また、処理を JavaScript で完結させているので、サーバとの余計な通信は発生しません。

拡張しやすくするため、学校の情報はすべてひとつの連想配列にまとめました。結果の表示枠もすべてその配列から動的に生成させているので、配列に一行足すだけで学校が追加できます。

あとは結果が “-” になる学校の分はツイートに含めないとか、入力時に学校に応じて期の選択肢が変わるとか、細かなところは手を入れています。

未実装、あるいは検討の余地

あくまで機械的に算出しているため、『定期演奏会が必ず一年に一度だけ開催される』という暗黙の前提を置いています。この前提に従っていない歴史がある場合は、計算結果が狂います。

おくさまに見せたら、『Facebook か Twitter と紐付けて結果をデータベースに貯めて、誰と同期だとか誰が後輩で先輩だとかわかるようにしたら?』と言われました。さすが IT やさんです。

まとめ

本業のおしごとでは IT 系と言いつつ Web アプリケーション系のコードを書く機会がまるでないので、久々に趣味のプログラミングって感じでおもしろかったです。

jQuery Mobile、便利ですね。まともに使ったのは恥ずかしながら初めてだったんですが、好きになりました。

こういうのって、コードを GitHub に載せるとイイんでしょうか。最近のお作法ってどうなんだろう。

ちなみにこの勢いに乗って、実は Python + jQuery でそれなりに機能する CGI を作ったんですが、それはまた別のお話。一般公開はしていないです。


Roland の SC-88 をもらったので、21 世紀の今あらためて MIDI を聴く

SC-88 を友人からもらった。SC シリーズだと SC-88Pro っていう通称 “ハチプロ” が有名だけど、これはその 2 年前に発売された、88 系列の最初のモデル。

ミュージ郎の時代だ、ミュージ郎の。

今でこそ mp3 なんていう便利な PCM 音源が台頭しているけれど、インタネット聡明期のピーガガガ時代に、インタネットの “向こう側” からダウンロードできるほんの数十キロバイトの MIDI ファイルに、いったいどれだけのヒトがどれだけのユメをみたことか!!

スピーカをオンにしたままネットサーフィン(死語)をしていたら MIDI ファイルが自動再生されるページを踏んでしまって爆音にびっくりするとか、巧妙に埋め込まれた MIDI ファイルをどうにかダウンロードしようとソースコードから JavaScript まで追いかけるとか、そういう時代。

当時の JavaScript は、右クリックを禁止したりステータスバーにメッセージを流したりページを開くと『ようこそくろいさん! 11 回目の訪問です! 夕焼けがきれいな時間帯ですね!』って出てきたりページ遷移にきらびやかなエフェクトをつけたりマウスカーソルにオリジナルキャラクタが常にくっついてきたりクリックすると花火が上がったり、そういう技術だった気もする。

それはいいとして、とりあえずこの SC-88 を鳴らしてみたいので、セットアップ。

接続とリセットと初期設定

本体の [COMPUTER] スイッチを [MIDI] にして、使っているオーディオインタフェイスの MIDI 出力を SC-88 の [MIDI IN A] に MIDI ケーブルでつなぐ。

ヘッドホンで聴くだけでいいならこれで終わり。必要があれば RCA な [OUTPUT] をオーディオインタフェイスの入力に戻してやる。

電源を入れて、謎な設定が残っているかもしれないので、ファクトリリセットする。

  1. [SELECT] を押しながら [INSTRUMENT] の [←] と [→] を同時押し
  2. 確認が出るので [ALL] で承認
  3. 処理が終わったら電源を入れなおして完了

デフォルトでは SC-55 互換音色マップが有効になった。そういうものらしい。

MIDI 出力デバイスが選べるプレイヤならここまででひとまず音は出る。Windows の標準出力を変えたい場合は、Windows 7 なら Putzlowitschs Vista-MIDIMapper(声に出して読めない)などを突っ込んでよしなに設定してやる。

肝心の音はどうなの

Windows に昔からもともと入っている C:\Windows\Media\town.mid で比較。

最初に Windows 7 の標準の、Microsoft GS Wavetable Synth。

次に今回もらった SC-88。55 互換はオフで、88 ネイティブな状態。Muted Gtr が弱いけど全体的な雰囲気はこれが好き。

SC-88 で 55 互換を有効にするとこうなる。

実を言うと VSC3(Virtual Sound Canvas 3)のライセンスは持っているので、これでも鳴らすとこうなった。88Pro 互換モードに設定。SC-88 の 55 互換モードとよく似ている。VSC は x64 環境だと動いてくれないので普段使いには厳しい。VSTi 版は持っていない。

VSC あるならハードウェアいらないのではっていうのも理解はできるのだけれど、でも物理的なモノってやっぱり好きなのよね。

オマケで、TiMidity 版。SGM-V2.01 っていうサウンドフォントを丸ごと突っ込んである。

TiMidity、高校時代にカスタマイズにハマっていた記憶が。

SFC の AO 入学生向けの入学前レポートで、当時のぼくがネタとして取り上げてもいた。今みたら、

このように、それぞれの楽器ごとにサウンドフォントを割り当てることで、MIDI 再生時に TiMidity++ が該当するサウンドフォントを参照し発音する。サウンドフォントごとにバラバラである音量などのパラメータも、ユーザ側で任意に調整できるようにされており、この例のように音量(amp)、パン(pan)など、他にもピッチやオフセット等の調整用パラメータが用意されている。

とか、

インターネット上にあるサウンドフォントは玉石混合であり、納得のいく音色を持つサウンドフォントを探すのは非常に難しいことであるが、この玉石混合から『玉』を探し出すのがこのカスタマイズの醍醐味でもある。また、インターネットの一部ではユーザがカスタマイズした設定ファイルが公開されていることもあり、これを使用すれば比較的簡単に高音質再生環境を実現することが可能である。

とか書いてあった。なつかしい。

使い道

正直何も考えていないのだけれど、実家に MIDI キーボードを置いてきているのでそれを持ってくればいろいろ遊べそうだなーとか考えている。

既成の MIDI ファイルを綺麗に鳴らすためのハードウェアってわけではないので、本来の使い道としてはその方が正しいのだけれど。


Kindle for Android でフォントに “明朝” が選べなくなったときの対処

Android 端末(Xperia A)が修理から戻ってきたからアプリケーションをせこせこと入れなおしていたら、Kindle for Android の本文のフォントが “ゴシック” しか選べなくなっていたことに気が付いた。

もともと本は紙で読むひとだったので、これまではずっと紙の本に合わせて明朝体で読んでいたのだけれど。

ためしにゴシック体のまま読んでみたら違和感がすごくて気持ち悪い。直したい。

いろいろ調べてもいろいろ試してもよくわからないので、やむなくサポートセンタに問い合わせ。

チャット窓口ですぐに解決策が出てくるかと思いきや、詳細調査になって、結局返事が来るまで数日かかったけれど、最終的には直った。

直し方

カスタマサービスのひとに教えてもらった方法は二つ。

一つめは、『吾輩は猫である(Kindle 版)』をダウンロードしてみよ、というもの。

  1. Kindle for Android を開いて、右上のショッピングカートボタンをタップ
  2. 検索するなどして『吾輩は猫である(Kindle 版)』のページに行き、購入する
  3. 端末にダウンロードする
  4. 『吾輩は猫である(Kindle 版)』を開く
  5. フォントの選択肢を確認する

え、これだけ? と思ってやってみたら案の定直らなかった。

結局、教えてもらった二つめの方法で直った。英中辞書をダウンロードする方法。

  1. 英語が含まれている Kindle 本を開く
  2. どれでもいいので英単語を長押し
  3. 表示されるボックスの右上の本のマークをタップ
  4. [英語 – 中文] をタップして [ダウンロード]
  5. ダウンロード終了後、[全文表示] をタップ
  6. 端末の [戻る] ボタンで全文表示を終了
  7. 再度、どれでもいいので英単語を長押し
  8. 表示されるボックスの右上の本のマークをタップ
  9. [英語 – 日本語] をタップ
  10. フォントの選択肢を確認する

手順 7 から 9 はたぶん設定をもとに戻すためだけのもので、実質は手順 5 あたりで始まる外字フォントのダウンロードが効いているっぽい。

解決。

切り分け

問い合わせる前にこっち側で調べたのは以下。

  • 別の Android 端末では “明朝” が選べる
    • アプリケーションのバージョンは同一(4.5.1.6)
    • Android のバージョンがちがう(Xperia A は 4.2.2、こっちは 4.1)のでその所為?
    • もしくは機種に依存?
  • 特定の本に限らずどの本でも同じ症状である
  • アプリケーションをアンインストールして再度インストールしなおしても変わらない

原因

不明。

上の方法で直したあと、再現性を確認しようとしていちどアンインストールしてから再度インストールしたら、最初から “明朝” が表示されてしまった。再現性なし、という残念な結果に。直る前は数回入れなおしてもだめなままだったのに……。

あれかな、バンドルされていた辞書を全部消した状態で端末が修理で初期化されたから必要なコンポーネントがダウンロードされないままだったのかな。修理前の端末では上でいう外字フォントっぽいものが辞書にくっついて記憶のないままにダウンロードされていたのかもしれない。謎。

たぶんこの状態で端末を初期化したらきっと再現するだろうなあと思いながらも、そこまで深追いする意味もないのでここまで。


部活の古い録音、レガシィな記録媒体のお話

高校のころ所属していた部活 の古い録音の山が、講師の先生のところに眠っているらしい。何年も前にそんな話を聴いてから、いつか全部きちんとデジタル化して後世に残していきたいなあとながいこと思っていたのだけれど、最近ようやくこれに着手した。

部活の公式 Web ページの中の “ギタサン史” によれば、ぼくらのルーツは 1972 年の秋に発足した同好会。今が 2013 年だから、もう 41 年を数えることになる。ぼくの生まれが 1987 年だから、それよりもずっと前。

40 年を越える歴史があるというのに、さて、ぼくらが “過去の演奏” を聴こうと思ったときに聴けるのは、せいぜいここ 10 年分くらい。最近の部員の中では比較的長くぎたさんに関わっていると思われるぼくでさえ、手元にきちんとした形で持っているのは 2001 年度以降のデータだけ。

世の中に録音が存在しないなら別だけど、物理的に残っているのであれば、それが聴けなくなる前に、聴ける状態にしておきたかった。

経年劣化は避けられない。はやくどうにかしないといけない、このまま何もしないでいたら、ぼくらは膨大な何かを失うことになると、そういうぼんやりとした危機感があった。

残っている記録媒体は、たいがいは何らかのテープ。危機感の根源は、テープの寿命ではなく、テープを再生する機械の寿命である。

テープは強い。コンパクトカセットだろうが DAT だろうが miniDV だろうが Hi8 だろうが VHS だろうが VHS-C だろうが beta だろうが、とにかくテープは強い。信じられないくらいに強い。耐久性でいえば CD-R や DVD-R や HDD よりも何倍も何十倍も強い。今までの数十年も平気で品質を保ってきたし、多分この先の数十年も同じように品質を保ってくれるはず。

だから別に今やらなくてもいいのではないかと思わないこともないのだけど、現実的にはたぶん、テープより先にそのテープを再生できる機械がなくなる。かつて一世を風靡したカセットデッキも、もはやまともな新品は TEAC のくらいしか手に入らない。DAT デッキなんてもうどこも作っていない。

今あるデッキだっていつかは壊れるし、ガタがくるとテープが入ったまま取り出せなくなるとか中で絡まるとか切れるとか、そんなことも起こりうる。そんな現実をよそに、メーカの保守パーツの保管期限もどんどん切れてくるから、オーバホールはおろか修理さえも年々難しくなってくる。

だからやっぱり、今、できるひとがやっておかなければいけない気がする。

第一に、テープの中のデータを保全すること。第二に、保全したデータをリマスタリングして再利用性を高めること。第三以降は、考えていない。

何年かかるかわからない。まずは音から。そのあとは映像。終わったら部活ではない別の団体の分。なんせ 500 本ちかくある。先は長い。いまは 50 本くらい終わったところ。

そんなわけで、最近はレガシィな記録媒体と仲良く暮らしている。ぼくが生まれる前に記録されたメタルテープ[1] が想像をはるかに上回る音のよさでびっくりしたりとか、180 分の DAT をデッキに入れるときにちょっと緊張したり[2] とか、そんな毎日。

しかしこういうことをやっていると、五十年後にこのデータは誰がどう管理しているんだろうなあとか、そもそも五十年後って部活どうなってるのかなあとか、高校っていうシステムがその時まで残っているのかなあとか、いろいろ考えてしまいますね。

はてさて 75 歳のぼくは何を思うのでしょう。そもそも生きているかもわからない。


  1. コンパクトカセットは磁性体の違いでノーマルとハイポジション(クロム)とフェリクロムとメタルがあって、メタルがいちばん音がよい。家電量販店で今でもたまにコンパクトカセットを見るけど、もう劣悪なノーマルしか置いていない []
  2. 180 分の DAT はほかの時間のよりもテープそのものが薄いので、デッキの中で絡まったり切れたりしやすい []