Dies Aliquanti

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

SSHをRubyで使う

連休の谷間を有休でうめたので、結構長い休みでしたが、それも今日で終わり。ず~っと部屋の片づけをしていたので、家内の不興を買うことになってしまった。


それはともかく、前にも書いたように、我が家のHauppauge HD-PVRの録画システムは、キャプチャそのものは、linuxで動くが、EPGやタイマー制御はWindowsXPという、サイコーにイケてる仕様で、この場合Windows→linuxの制御をなんとかしなければいけないわけです。

いままで、Windowsで動作する、sshクライアントとしてTeratermのマクロ機能版(ttpmacro)を使っていたのですが、これが(私には)いまいち。
マクロ言語を覚えるのがめんどー。所詮マクロなのでたいした量ではないが、オヤジには面倒。あと、時々プロセスがzonbi化し、CPUパワーを100%使う状態になってしまう。作者の方にはリポートしたいと思うのだが、まれな現象で、再現できていないのでどうししようもない状態。

で、前置きが長いが、「ひょっとしてRubyで使えるsshクライアント(のライブラリ)ってないのか?」と、思って探してみたら、あるんですねー、やっぱり。Ruby猿の私にはうれしい。

このページを参考に、まずライブラリをインストールします。Windowsのコマンドプロンプトから、

 

gem install net-ssh

 

で一発。

早速、先のページのサンプルを動かします。

 D:\Devel\ruby_ssh>ruby ssh_test.rb
HDPVR_REC
examples.desktop
繝?繧ヲ繝ウ繝ュ繝シ繝・
繝・Φ繝励Ξ繝シ繝・
繝・せ繧ッ繝医ャ繝・
繝峨く繝・繝。繝ウ繝・
繝薙ョ繧ェ
繝斐け繝√Ε
繝溘Η繝シ繧ク繝・け
蜈ャ髢・

orz... 漢字コードか…kconvをrequireして、結果をSJISに変換して、っと。

D:\Devel\ruby_ssh>ruby ssh_test.rb
HDPVR_REC
examples.desktop
ダウンロード
テンプレート
デスクトップ
ドキュメント
ビデオ
ピクチャ
ミュージック
公開

今度はうまくいきました。やりたいことは、linuxにログインして、コマンドを一発出すだけなので、これでできたも同然。このままだとパスワードを平文で扱わないといけないのが、ちと気になりますが、まあ家庭内LAN限定なのでよしとしましょう。ちなみに、先のページには公開鍵での認証のやり方もかいてあります。


// Original at http://webos-goodies.jp/archives/51357031.html 
require 'rubygems'
require 'net/ssh'
require 'kconv'
Net::SSH.start('host', 'user', :password => 'password') do |ssh|
print(Kconv.tosjis(ssh.exec!('ls ~')))
end

 

 



スポンサーサイト

sh ? bash ? dash ?

いやぁ、私だって

「自動車教習所に通っていた時から、免許を取得したら『カヴァリーノ・ランパンテ』のエンブレムがついている車に乗りたい♪ それ以外の車なら乗りたくないわ、と思っていました」。(大笑)

 (まだ、容疑者でもないのだが)所轄の異なる場所で、しかも手口を変えれば、殺人も結構捕まらないものなんだな… 睡眠導入薬(ハルシオンか?)+練炭火鉢が簡単で繰り返したのが運のつきか…サギのほうで逮捕されたとき、同棲していた男性の家の火災報知機がすべてはずされていた、なんて話を今朝のワイドショーでやっていたけど、命拾いだな。。さしずめ「逆青髭」


それはともかく、Hauppauge HD PVRを使ったPC録画のスクリプトがちょっとバグってるのがわかったので、手直ししようとおもいました。bashスクリプトですが、ん~、なんか完全に忘れてますね。 orz
メンテ性があまりに悪いのrubyで書き直してみますが、なぜかうまく日本語のファイルができません。いろいろ調べていくと、`~`やsystem()を実行する際にsh経由で呼び出しているのがわかりました。Ubuntu 8.10 Desktopのshって、bashだとばかり思っていたのですが、違うんだな。

$ ls -l `which sh`
lrwxrwxrwx 1 root root 4 2009-08-10 20:57 /bin/sh -> dash


orz. 同じことにハマッテいる方がいますね。こちらの方を見習って、

$ sudo dpkg-reconfigure dash

んで、

$ ls -l `which sh`
lrwxrwxrwx 1 root root 4 2009-03-27 21:44 /bin/sh -> bash

これで、スクリプトのほうもちゃんと動くようになりました。

 



Rubyで漢字コードの自動変換

 先週から、だらだらやっていた、録画スケジューラのプログラムの修正(Linuxベース化)だが、だいたい終わりました。Windowsでも動作するように書いているつもりですが果たしてどうですかね。
 いつもながら「漢字」コードの取り扱いが厄介です。RubyではKconvというモジュールを使って漢字コードの変換ができますが、インタプリタの漢字コードは$KCODEというグローバル変数に保持しています。そこで、$KCODEから、Kconvでの漢字コードの指定ができるように変換する関数を作りました。
 さらにStringクラスにkconvAuto()というメソッドを追加して、インタプリタの漢字コードに自動で変換するようにしてみました。こんなことって普通に必要だと思うのですが、実はなにかいい方法があったりするのでしょうか?

#
## Kanji Helper
# (c)2009 BO
#
#
require 'kconv'
module KanjiHelper

  @@KCODE2KCONVCODE = { "EUC" => Kconv::EUC ,
        "SJIS" => Kconv::SJIS ,
        "UTF8" => Kconv::UTF8 ,
        "NONE" => Kconv::ASCII }

  def self.kcode2kconv( kcode = $KCODE )
    @@KCODE2KCONVCODE[ kcode ]
  end #def kcode2kconv( kcode = $KCODE )

end #module To_WinFileName

# adding to String class

class String
  include KanjiHelper

  def kconvAuto( out_code = KanjiHelper::kcode2kconv(), in_code = Kconv::AUTO )
    self.kconv( out_code, in_code )
  end # def kconvAuto( out_code = KanjiHelper::kcode2kconv(), in_code = Kcobv::AUTO )


end # class String




どうもまだ、mix-inとかが判ってない

Windows用に作った、Rubyで書いた録画スケジューラ(PVR)ですが、7月25以降快調に動作しています。実際の録画はlinux上で動いているので、windows→linuxの部分はteratermのマクロ機能で、自動ログインしたうえで録画プログラムを動作させるという、回りくどいことをしています。
どうも、teratermのバグっぽいのですが、時々1スレッドをteratermが思いっきり占有したままzonbi化するし障害がおきています。ということでスケジューラをlinux用にちょっと変更する作業をしています。具体的には、iEPG/iEPGDのファイルを読み込んだとき、文字コードをutf8に変更するのと、プログラム中に埋め込んだsjisの2バイト文字をutfに変更することで、とりあえずはいいことにしました。
動作プラットフォームがwindowsかlinuxかで文字コードを切り替えるようにしたいのですが、コード中に埋め込んでしまいたい多バイトコードの取り扱いはちょっと面倒。Rubyでは、kconvを使って多バイトコードを変換できますが、コードを指定する値が、システムの漢字コード$KCODEと無関係に決まってるみたい。orz
しょうがないので変換する関数をつくって見ました。グローバルな名前にするのはちょっと「品がない」気がして、module化してみたのですが、なぜかうまくmix-inできないです。むぅ~・・・なんで?


IniFile再び

まえに、iniFileを読むためのRubyのクラスを実装したのを書いたけれど、ちょっと直しました。以前のものは、指定した、セクション、キーが存在しない場合、""を返すようにしていたのですが、Rubyっぽく、nilを返すようにしました。

 iniH = IniFile.new( fileSpec)

でファイルから読み、

 hash = iniH[ section名 ]

でセクション全体をハッシュで返します。セクションがない場合、nilが返ります。
セクションの有無を確認の上、キーにアクセスするには、

 raise "NO section" if ! iniH[ セクション名 ]
 value = iniH[セクション名][キー名]

のようにします。
新たにセクション、キーを指定して値を追加する場合には、

 (iniH[ セクション名] || iniH[ セクション名] = Hash.new)[key名] = 値

みたいになります。ほとんどパズルみたいなので、[], []=を定義しなおしてみました。これで、

 val = iniH[ セクション名, キー名]

 と書くことができます。目的とするセクションや、キーがない場合はnilが返ります。
 また、

 iniH[ セクション名、 キー名 ] = value

という、書き方ができます。この場合、指定したセクションが存在しない場合は、新たにセクションを追加し、キーにvalueを関連付けます。

それよりも嵌ったのは、正規表現で、キーと値の抽出は、/(.*)=(.*)/ではなく、/(.*?)=(.*)/,つまり最短一致にしておかないとちょっと動作がまずそうです。

#
# (c)2009 BO
#   inifile
#
 
class IniFile < Hash
  @@ReComment = /^#/
  @@ReSection =/\[(.*)\]/
  @@ReKeyValue =/(.*?)=(.*)/
  def initialize( fileSpec = nil )
    if fileSpec
      File::open( fileSpec) {|f|
        sectionName = ""
        while line = f.gets
          if line =~ @@ReComment  # skip a line
          elsif line =~ @@ReSection
            sectionName = $1.strip
          elsif line =~ @@ReKeyValue
            self[ sectionName,  $1.strip] = $2.strip if sectionName != ""
          end
        end # while
      }
    end
  end #def initialize( fileSpec = nil )

  def write2File( fileSpec )
    fp = File.open( fileSpec ,'w')
    fp.print to_s()
    fp.close
  end #def write2File( filespec )

  def to_s
    str = String.new
    self.each_key{ |section|
      str += "[#{section}]\n"
      if self[section]
        self[section].each_key{|key|
          str += "#{key}=#{self[section][key]}\n" if self[section][key]
        }
      end
    }
    str
  end #def to_s

  def []( section, *rest)
    return super(section) if rest.length == 0
    key=rest[0]
    self[section] ? self[section][key]  : nil
  end # def []( section, *rest)

  def []=( section, *rest )
    if rest.length == 1
      hash = rest[0]
      return super( section, hash)
    elsif rest.length == 2
      key, val = rest[0], rest[1]
      return (self[section] || super(section, Hash.new))[ key ]= val
    else
      raise "invalid number of param"
    end
  end #def []=( section, *rest )
end # class IniFile



FC2Ad

まとめ

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。