はじめに
本題に至るまでに疲れて脱落者が出そうなので、はじめにお断りです。
Rubyでの\$stdinや\$stdoutの使い方の話ですよ!
では、始めましょう。
背景
最近Macを更新しました。接続規格が大幅に変わっているので、周辺機器が軒並み繋がらないのは覚悟していたのですが、「流石にこれは大丈夫ではないか」と思っていたバーコードリーダーも使えなくなってしまいました。バーコードリーダーはキーボードの振りをするのですが、最近のMacでは「そんな怪しいキーボードは使わせない」ということなのか接続されたことは認識するもののそれ以上は進みません。(おそらくセキュリティ強化のためなのでしょう。そういう時代ですよね、、、)
そこで「パンがなければお菓子を食べればいい」ということで、以下のように回避することにしました。
- バーコードリーダーをFreeBSD(GhostBSD)に接続1。FreeBSDはUSBキーボードだと思ってくれるので、問題なく動作します。
- FreeBSDで入力された値をネットワーク経由でMacに送信。
- Macで受信したデータを標準出力に表示。
- 今までコンソールで受け取っていたものの代わりに標準出力に表示されたものをデータとして受け取るように。
バーコードリーダーやFreeBSD(GhostBSD)は逸般の誤家庭にあるものをお使いください。
ネットワーク通信(受信)の準備
ネットワークでデータを受信するプログラムはこんな感じでしょう。
(抜粋です)
gs = TCPServer.open(port)
s = gs.accept
while a = s.gets
print a
end
s.close
注意!!!
背景の内容から推測はつくと思いますが、データの送信側も受信側も自分の目の前にある(当然自分の目が行き届いている)というのが前提です。これを何も考えずにインターネット上でやって問題が起きても責任は負えません。
本題
ようやく本題です。以前は以下のようなプログラムでバーコードリーダーからのデータを受け取っていました。
(抜粋です)
f = IO::console
print "ISBN: "
until f.eof
t_isbn = f.readline.chomp
(以下略)
さて、receiver.rbを単体で動かすと「Macで受信したデータを標準出力に表示」ができていることが確認できました。
ruby receiver.rb | ruby input.rb
で期待通り動作するといいですね。実際にやってみます。
、、、???input.rbがずっと入力待ちのままです。
(半分)解決
そう言えば
f = IO::console
とコンソールから明示的に入力を受け付けるように書いてましたね。これでは動かないはずです。以下のように書き換えます。(もっと良い方法があるかも知れませんが、既存のスクリプトの書き換えが一番少なそうな方法なので、これで。)
f = $stdin
再挑戦します。データは確かに届きます。届くのですが、実際にバーコードリーダーを使っている時には何もデータは来なくて、FreeBSD側でネットワークを切断するとドドドっと来ます。
、、、そうじゃない!!!今までMacにバーコードリーダーを直接接続していた時みたいに動いてほしいんです。
(残り半分)解決
解決に至るまで紆余曲折がありましたが、結果だけ書きます。
receiver.rbの初めの方で
$stdout.sync = true
と書けばよいです。
Rubyで標準出力を利用する機能は、標準出力先が「普通の」標準出力なのかそうでない(パイプとかリダイレクトとか)のかを把握して、それに応じて動作を変えているようです。上の設定は、「そういうのは気にしなくていいから、同期的に動いてね」という意味でしょう。
ruby receiver.rb | ruby input.rb
で期待通り動作しました。
おまけ
データの入力自体はうまくいっているのですが、バーコードリーダーが読み取った値はFreeBSD側の画面に表示されているだけで、Mac側には"ISBN: "とかの表示だけが流れていくだけです。これで妥協してもよかったのですが、「あとちょっとの労力」ということでMacでも表示されるようにしました。具体的には以下の2行目を追加です。
t_isbn = f.readline.chomp
puts t_isbn if not $stdin.tty?
これで画面表示も含めてそっくりになりました。めでたし、めでたし。
おことわりなど
恒例のお断りですが、この文章の内容は、筆者が所属している会社・団体とは一切関わりがありません。いわゆる「自主的な研究の成果の発表」というものです。
え、タイトルが「リダイレクト」なのに書いてある内容は「パイプ」なのでは?ですか。その通りですけど、こまけぇこたぁいいんだよ!!
-
ちょっとここは省略し過ぎたのかもしれませんが「FreeBSDは仮想マシン上で動作しているのですか」と聞かれました。うーん、そういう時代なのかもしれませんね。だがしかし、だーかーらー、そもそもMacがハードウェアを認識しないのだから、Mac上の仮想マシンでOSを変わったのを使ったところで無駄でしょ!逸般の誤家庭なら当然実機です。 ↩