2021-06-16

formula のないソフトウェアを Homebrew でインストールする

formula のないソフトウェアを Homebrew を用いてインストールするには,Adding Software to Homebrew in Homebrew Documentation に従って formula を書く. brew create https://.../...tar.gz で雛形がつくられ (formula の名前は自動で決まる),$EDITOR が開くので,formula を書く.brew install --build-from-source formula 名 によりインストールされる.

以前は,brew install formula の URL でインストールできたが,これはできなかった.

2020-08-18

IEC 61162-1 and NMEA 0183

Versions

References

2017-05-19

Real-Time Linux

CONFIG_PREEMPT_RT を試すべく,kernel をコンパイルするなどの回り道をしたのち,Ubuntu の kernel が「CONFIG_PREEMPT_RT」パッチの成果である「force threaded irq-handler」が取り込まれたものであることを知り,Ubuntu Desktop 16.04.2 と lowlatency kernel (パッケージ) とを用いることにした.cyclictest (パッケージ) の結果は以下だった.

$ uname -r ; uname -v
4.4.0-77-lowlatency
#98-Ubuntu SMP PREEMPT Wed Apr 26 09:25:21 UTC 2017

$ sudo cyclictest -t 5 -i 5000 -d 5000 -c CLOCK_REALTIME -D 1m -q
# /dev/cpu_dma_latency set to 0us
T: 0 ( 1524) P: 0 I:5000 C:  12000 Min:      4 Act:   46 Avg:    5 Max:    4003
T: 1 ( 1525) P: 0 I:10000 C:   6000 Min:      4 Act:   47 Avg:    7 Max:    4008
T: 2 ( 1526) P: 0 I:15000 C:   4000 Min:      4 Act:   55 Avg:    8 Max:    4025
T: 3 ( 1527) P: 0 I:20000 C:   3000 Min:      4 Act:   53 Avg:    7 Max:    4030
T: 4 ( 1528) P: 0 I:25000 C:   2400 Min:      4 Act:    6 Avg:    6 Max:    3052

$ sudo cyclictest -t 5 -n -i 5000 -d 5000 -c CLOCK_REALTIME -D 1m -q
# /dev/cpu_dma_latency set to 0us
T: 0 ( 1588) P: 0 I:5000 C:  12000 Min:     17 Act:  117 Avg:   51 Max:     117
T: 1 ( 1589) P: 0 I:10000 C:   6000 Min:     18 Act:  110 Avg:   52 Max:     110
T: 2 ( 1590) P: 0 I:15000 C:   4000 Min:     23 Act:  103 Avg:   54 Max:     103
T: 3 ( 1591) P: 0 I:20000 C:   3000 Min:     27 Act:   91 Avg:   55 Max:      91
T: 4 ( 1592) P: 0 I:25000 C:   2400 Min:     33 Act:   58 Avg:   56 Max:      62

$ sudo cyclictest -t 5 -p 99 -i 5000 -d 5000 -c CLOCK_REALTIME -D 1m -q
# /dev/cpu_dma_latency set to 0us
T: 0 ( 1598) P:99 I:5000 C:  12000 Min:      4 Act:    4 Avg:    4 Max:      41
T: 1 ( 1599) P:99 I:10000 C:   6000 Min:      4 Act:    5 Avg:    4 Max:       8
T: 2 ( 1600) P:99 I:15000 C:   4000 Min:      4 Act:    5 Avg:    4 Max:       9
T: 3 ( 1601) P:99 I:20000 C:   3000 Min:      4 Act:    5 Avg:    4 Max:       8
T: 4 ( 1602) P:99 I:25000 C:   2400 Min:      4 Act:    4 Avg:    4 Max:      10

$ sudo cyclictest -t 5 -n -p 99 -i 5000 -d 5000 -c CLOCK_REALTIME -D 1m -q
# /dev/cpu_dma_latency set to 0us
T: 0 ( 1609) P:99 I:5000 C:  12000 Min:      2 Act:    3 Avg:    3 Max:       9
T: 1 ( 1610) P:99 I:10000 C:   6000 Min:      2 Act:    3 Avg:    3 Max:       5
T: 2 ( 1611) P:99 I:15000 C:   4000 Min:      2 Act:    3 Avg:    2 Max:       5
T: 3 ( 1612) P:99 I:20000 C:   3000 Min:      2 Act:    2 Avg:    2 Max:       4
T: 4 ( 1613) P:99 I:25000 C:   2400 Min:      2 Act:    5 Avg:    2 Max:       5

この間,以下を実行していた.CPU 数は 4.

$ for cpu in 1 2 3 4; do ( while true; do true; done; ) & done

2017-04-16

real-time operating system (RTOS)

MATLAB での Modbus 通信

2016-11-25

MATLAB

2016-03-13

PROFIBUS DP スレーブとの通信

ある PROFIBUS DP スレーブと通信するためにマスタに設定しなければならない値は以下だった.

  • マスタアドレス
  • スレーブアドレス
  • Ident_Number.スレーブ機器の GSD ファイルにあり
  • Parameters.一般名詞ではない.スレーブ機器の GSD ファイルにあり
  • Configuration.一般名詞ではない.スレーブが modular device のばあい (別はスレーブ機器の GSD ファイルにあり),slots それぞれにどの module (定義はスレーブ機器の GSD ファイルにあり) を配置するか

Mac での RS-422 通信

Mac で RS-422 通信をするために FTDI 社の USB RS422 Cables を同社の Virtual COM Port Drivers で用いた.この製品に至るまでの参考は以下:

ちなみに,ループバックテストには次を参照した:シリアルループバックテストの実行方法 - National Instruments

さらにちなみに,RS-422 のピンアサイン規定はないとのこと (serial - Standard pinout for RS-422? - Electrical Engineering Stack Exchange).実際,用いた機器のピンアサインに従って接続した.

2013-09-12

Ruby の CSV#<< が Encoding::compatible? を呼んでいるため遅い

Ruby 1.9.3 の CSV で行数の多い CSV を作っていたところ,長い時間がかかった.

ruby-prof で測定したところ,#<< から呼ばれる Encoding::compatible? が大部分を占めていた.

$ cat large-csv.rb 
require 'csv'
require 'stringio'
file = StringIO.new
csv = CSV.new(file)
100_000.times do
  csv << Array.new(10,'a'*20)
end
p file.length
$ ruby-prof -f before.html -p call_stack large-csv.rb
21000000
ruby-prof result

この部分のコードを以下に引用する.

https://github.com/ruby/ruby/blob/v1_9_3_392/lib/csv.rb#L1730-1732
    if @io.is_a?(StringIO)             and
       output.encoding != raw_encoding and
       (compatible_encoding = Encoding.compatible?(@io.string, output))

最初の 2 条件が満たされると,Encoding.compatible? が呼ばれてしまう.

第 1 条件:以下引用するコードによると,::new の第一引数に String あるいは StringIO を与えると @ioStringIO となる.

https://github.com/ruby/ruby/blob/v1_9_3_392/lib/csv.rb#L1563-1568
  def initialize(data, options = Hash.new)
    # build the options for this read/write
    options = DEFAULT_OPTIONS.merge(options)

    # create the IO object we will read from
    @io       = data.is_a?(String) ? StringIO.new(data) : data

第 2 条件左辺:以下引用するコードによると,::new の第二引数の :encoding オプションに与えた値と #<< に与えた Array 中の String#encoding によって output.encoding は決定される.

https://github.com/ruby/ruby/blob/v1_9_3_392/lib/csv.rb#L1729
    output = row.map(&@quote).join(@col_sep) + @row_sep  # quote and separate
https://github.com/ruby/ruby/blob/v1_9_3_392/lib/csv.rb#L2090-2116
    @force_quotes   = options.delete(:force_quotes)
    do_quote        = lambda do |field|
      field         = String(field)
      encoded_quote = @quote_char.encode(field.encoding)
      encoded_quote                                +
      field.gsub(encoded_quote, encoded_quote * 2) +
      encoded_quote
    end
    quotable_chars = encode_str("\r\n", @col_sep, @quote_char)
    @quote         = if @force_quotes
      do_quote
    else
      lambda do |field|
        if field.nil?  # represent +nil+ fields as empty unquoted fields
          ""
        else
          field = String(field)  # Stringify fields
          # represent empty fields as empty quoted fields
          if field.empty? or
             field.count(quotable_chars).nonzero?
            do_quote.call(field)
          else
            field  # unquoted field
          end
        end
      end
    end
https://github.com/ruby/ruby/blob/v1_9_3_392/lib/csv.rb#L2023-2025
    @col_sep    = options.delete(:col_sep).to_s.encode(@encoding)
    @row_sep    = options.delete(:row_sep)  # encode after resolving :auto
    @quote_char = options.delete(:quote_char).to_s.encode(@encoding)

第 2 条件右辺:いっぽう,以下引用するコードによると,raw_encoding は,@io のそれとなる.

https://github.com/ruby/ruby/blob/v1_9_3_392/lib/csv.rb#L2326-2328
  def raw_encoding(default = Encoding::ASCII_8BIT)
    if @io.respond_to? :internal_encoding
      @io.internal_encoding || @io.external_encoding

StringIO#set_encoding でこれを指定することができる.

以上に従って,次のようにして CSV を作成した.

$ cat large-csv-modified.rb
require 'csv'
require 'stringio'
file = StringIO.new
file.set_encoding(Encoding::UTF_8)
csv = CSV.new(file, {:encoding => Encoding::UTF_8})
100_000.times do
  csv << Array.new(10,('a'*20).encode(Encoding::UTF_8))
end
p file.length
$ ruby-prof -f after.html -p call_stack large-csv-modified.rb
21000000
ruby-prof result

時間のかかっていた Encoding::compatible? が呼ばれなくなった.

2013-04-27

mod_proxy モジュールによるリバースプロキシ:URL 中のセミコロンやカンマの扱い

    ProxyPass / http://localhost:9292/
    ProxyPassReverse / http://localhost:9292/

上のようにして Apache にリバースプロキシを設定したところ,クライアント側から要求した URL にセミコロン ; を URL エンコードした %3B が含まれるとき,オリジンサーバ (localhost:9292) に要求される URL はセミコロンの前だけになってしまった.また,カンマ , をエンコードした%2C が含まれるときはこれをデコードした , に置き換えられた URL がオリジンサーバに要求された.

検索により記事『mod_proxyを経由するとURIが勝手にデコードされる - 脱線こそ本道』を見つけた.次のように nocanon を与えて解決した.

    ProxyPass / http://localhost:9292/ nocanon

http://httpd.apache.org/docs/2.2/mod/mod_proxy.html によれば (日本語:http://httpd.apache.org/docs/2.2/ja/mod/mod_proxy.html),no canonicalization の意.http://en.wikipedia.org/wiki/Canonicalization によれば canonicalization は standardization or normalization の意.また,abbreviated c14n, where 14 represents the number of letters between the C and the Nhttp://en.wiktionary.org/wiki/canonicalize によると語源は canonical + -izeNew Oxford American Dictionary によると canonical は according to or ordered by canon lawaccepted as being accurate and authoritativerelating to a general rule or standard formulahttps://ja.wikipedia.org/wiki/%E6%95%99%E4%BC%9A%E6%B3%95 (英語:https://en.wikipedia.org/wiki/Canon_law) によると canon law は 教会法

2013-02-16

zip を作りながら順次送信する

Sinatra では Sinatra::Streaming (Sinatra API Documentation) を用いてレスポンスボディをちょっとずつ返す (Sinatra 1.3.0 & Padrino 0.10.3 がリリースされました。ざっくり紹介(1)。 « blog.udzura.jp) ことができる.

テキストコンテンツではうまく動いた.次の例に web ブラウザから接続すると順次表示されていく.

require 'sinatra/streaming'
helpers Sinatra::Streaming
get '/stream-text' do
  stream do |out|
    0.upto( 1000 ) do |i|
      out << i
      out.flush
      sleep 1
    end
  end
end

archive-zipCreate a new archive which will be written to a pipe することができる.ところがこの stream にはうまく出力できない.次の例では,壊れた zip がダウンロードされる.

require 'rubygems'
require 'archive/zip'
require 'archive/zip/entry'
require 'sinatra/streaming'
helpers Sinatra::Streaming
get '/stream.zip' do
  content_type 'application/zip'
  stream do |out|
    Archive::Zip.open( out, :w ) do |zip|
      0.upto( 1000 ) do |i|
        zip.add_entry( Archive::Zip::Entry.from_file( $0, :zip_path => "#{i}" ) )
      end
    end
    out.close
  end
end
$ zip -T stream.zip 
 zip warning: local and central headers differ for (null)
 zip warning:  offset 10--local = 00, central = 48
 zip warning:  offset 11--local = 00, central = 8b
 zip warning:  offset 12--local = 00, central = fd
 zip warning:  offset 13--local = 00, central = 01
 zip warning:  offset 14--local = 00, central = 31
 zip warning:  offset 15--local = 00, central = 01
 zip warning:  offset 18--local = 00, central = d7
 zip warning:  offset 19--local = 00, central = 01

zip error: Zip file structure invalid (stream-direct.zip)

次のように間に IO::pipe を入れるとうまくいく.追及していない.

require 'rubygems'
require 'archive/zip'
require 'archive/zip/entry'
require 'sinatra/streaming'
helpers Sinatra::Streaming
get '/stream-pipe.zip' do
  content_type 'application/zip'
  stream do |out|
    reader, writer = IO.pipe
    write_t = Thread.new do
      Thread.pass
      Archive::Zip.open( writer, :w ) do |zip|
        0.upto( 1000 ) do |i|
          zip.add_entry( Archive::Zip::Entry.from_file( $0, :zip_path => "#{i}" ) )
        end
      end
      writer.close
    end
    until reader.eof?
      out << reader.readpartial( 4 ) # optimize it                                                  
    end
  end
end
$ zip -T stream-pipe.zip 
test of stream-pipe.zip OK

(2013-09-21 追記) IO#readpartial を用いるととても遅い.IO#sysread も同様.IO#read(十分に大きい値) ならばずっと速いが,ブロックしてしまうので,あまり大きな値を引数に与えると未完了でも HTTP サーバが接続を切ってしまう.結局,うまい方法は見出せていない.

2013-01-25

HTTP リソースをキャッシュ可能にする

サーブする動的コンテンツをキャッシュ可能にさせるためにはサーバはどう動けばいいのか調べた.

Last-Modified

ウェブサイトが動的なコンテンツの場合Last-Modifiedは無視される傾向にあります。むしろ、Last-Modifiedをきちんと送ってくるケースは非常に稀です (Last-Modifiedについて | Torisugariの日記 | スラッシュドット・ジャパン).

ハイパーテキスト転送プロトコル -- HTTP/1.1 (RFC2616) を見る.キャッシュサーバがもっているキャッシュエントリとオリジンサーバが返すものが同じとき,キャッシュサーバはキャッシュエントリをクライアントに返す (13.1.1 キャッシュの正当性). その判断は,Last-modified の時刻と ETag ヘッダ値による (13.3.1 Last-modified の日付,13.3.2 エンティティタグのキャッシュバリディタ).

オリジンサーバにとってより望まれる動作とは強いエンティティタグと Last-Modified 値の両方を送る事である (「強いエンティティタグ」とは ETag ヘッダ値を指す;13.3.4 エンティティタグや Last-Modified の日付を使う場合の規定). しかしここでは ETag ヘッダ値についてはこれ以上触れないことにする.キャッシュサーバを含むクライアントは,Last-Modified 値のみがオリジンサーバによって提供されていたら、非サブレンジキャッシュ条件付きリクエスト内で (If-Modified-Since を使って) この値を使うべきである (13.3.4)

(この段落にはあまり自信がない) ある種の動的コンテンツについて ETag ヘッダ値を返すのは不適切と思う.強いエンティティタグは関連するエンティティ値にどんな点においての変化があっても変わらなければならない (13.3.4) ので,例えばあるデータを表形式で示す動的コンテンツにおいて,状況によって行の順序が変化するばあいデータが変わらなくても異なる ETag ヘッダ値を返さねばならないが,これは無駄と思う.

Last-modified 時刻による判断には次の制限がある.エンティティの更新時間は、リソースを1秒以内に2度更新する事は可能なので、もしそれが秒解像度に相当するなら弱いバリディタである (13.3.3 弱いバリディタと強いバリディタ).このため,キャッシュエントリが、オリジンサーバが元々のレスポンスを送った時の時刻を与える Date 値を含み、与えられた Last-Modified 時刻は、その Date 値から最低 60 秒前である (13.3.3) ことが必要とされる.オリジンサーバはこれに合うように Last-modified 時刻を返さなければならない.

Last-Modified 時刻 (例えば If-Modified-Since や If-Unmodified-Since 各ヘッダフィールド内で) と一つ以上のエンティティタグ (例えば If-Match, If-None-Match, If-Range 各ヘッダフィールド内で) をキャッシュバリディタとして含む条件付きリクエストを受信した HTTP/1.1 オリジンサーバは、その行いがそのリクエスト内の条件付きヘッダフィールドのすべてに一致しているのでなければ 304 (Not Modified) ステータスを返してはならない (13.3.4). ここで扱っているサーバは ETag ヘッダ値を返してはいないのだから,If-Match, If-None-Match, If-Range ヘッダを含まずに If-Modified-SinceIf-Unmodified-Since ヘッダを含む要求に対して 304 (not modified)412 (Precondition Failed) を正しく返せばいいことになる (14.25 If-Modified-Since,14.28 If-Unmodified-Since).

Cache-Control

Cache-Control 一般ヘッダフィールドは、リクエスト/レスポンス連鎖上のすべてのキャッシングメカニズムが従わなければならない指示を記述するために使用される (14.9 Cache-Control).

オリジンサーバは,キャッシュ可能でないコンテンツには private あるいは no-cache 指示子を付して返答しなければならない (14.9.1 キャッシュ可能とは何か).private は例えばユーザ認証を経て配布したコンテンツに対して付す.no-cacheno-store 指示子 (14.9.2 キャッシュによって保存できるものは何か) については,例えば caching - Why both no-cache and no-store should be used in HTTP response? - Stack Overflow にあるように理解し辛い.web browser による動作の違いもあるようだ.また,HTTP — The Varnish Book によれば no-store は store-but-do-no-serve-from-cache-without-revalidation の意とある.

max-ages-maxage 指示子,あるいは Expires ヘッダによってコンテンツの有効期限を示すことができる (14.9.3 基本的な期限のメカニズムの修正).ここでは示さないことにして,これ以上触れない.

must-revalidateproxy-revalidate 指示子は 例えば黙って履行されていない財務的処理のように、エンティティの再検証が失敗する事でリクエストが不適当な操作というような結果になる場合にのみ、サーバは must-revalidate 指示子を送るべきである (14.9.4).ここではこれ以上触れない.

no-transform 指示子によって Content-EncodingContent-RangeContent-Type ヘッダを変更してはならない.これらのヘッダによって指定されたエンティティボディの、エンティティボディ自身の値を含め、いかなる部分も変更してはならない 事を意味する (14.9.5 no-transform 指示子;13.5.2 修正できないヘッダ).

Vary

Vary フィールド値は、そのレスポンスが新鮮である{fresh} 間、キャッシュが再検証無しにそれに続くリクエストに対するレスポンスとして使ってよいかどうかを、完全に決定するためのリクエストヘッダフィールドのセットを示す (14.44 Vary).例えば,The most common usage of Vary is to use Vary: Accept-Encoding, which tells caches (Varnish included) that the content might look different depending on the Accept-Encoding-header the client sends. In other words: The page can be delivered compressed or uncompressed depending on the client (HTTP — The Varnish Book).

2012-10-28

Ruby の Float#round

PHPの新しいround関数を読み解く (2)pre-roundingの意味 - hnwの日記 を読んだ.次のようにして確かめてみた.

$ uname -mrs
Darwin 9.8.0 i386
$ ruby -v
ruby 1.8.6 (2009-06-08 patchlevel 369) [universal-darwin9.0]
$ irb
>> 1.255
=> 1.255
>> 1.255 * 10**2
=> 125.5
>> ( 1.255 * 10**2 ).round.quo( 10**2 )
=> 1.25
>> 125.5.round
=> 126
>> sprintf( '%.17e', 1.255 )
=> "1.25499999999999989e+00"
>> sprintf( '%.17e', 1.255 * 10**2 )
=> "1.25499999999999986e+02"
>> sprintf( '%.17e', 125.5 )
=> "1.25500000000000000e+02"

上で引用した記事より:

まず、1.255のような場合への対策が必要かどうかについての議論があるでしょう。これは僕も非常に疑問ではありますが、「小数点以下n位への丸めを行う引数を提供している時点で、小数が10進で格納されているかのような振る舞いをすべきだ」という考えは理解できます。整数以外の桁への丸めを導入したこと自体が関数設計レベルの失敗であり*3、今さらこの引数を撤回できない以上、この実装も必要だということで僕個人は納得しています。

Ruby 1.8.7 の Float#round は,このような丸める位を指定する引数を取らない.1.255 を 1.26 に丸めるには,BigDecimal を使うのが正解ということになるか.

>> require 'bigdecimal'
=> true
> BigDecimal( 1.255.to_s )
=> #<BigDecimal:586ec,'0.1255E1',8(8)>
>> BigDecimal( 1.255.to_s ).round( 2 )
=> #<BigDecimal:50758,'0.126E1',8(16)>

Ruby 1.9.3 の Float#round は,丸める位を指定する引数を取る.この動きはまだ見ていない.

2012-08-03

Google Fusion Tables

Google Fusion Tables を少し触ってみた.

  • 列の型には,number, text, date/time, location がある
  • location 型を使うと map 上に点を打ったりできる
  • 緯度と経度を別の列に number で入れ,それらを合わせて location 値とできる
  • formula 列を作れる.各行で,ほかの列の値を式中で使える.
  • RDBMS と違い,not null, unique, check 制約などはかけられない
  • relation もない.ある table に別の table を merge して別の名前を付けて保存できる.merge するには行を照合するための列を 1 つ指定する.複数の列による merge はできない.the first table dictates what rows appear in the merged table. (Database buffs will recognize this as a left-outer join.)
  • merge して作った table の列名は変えられる.列順は変えられない.列の追加もできない
  • merge して作った table をさらに別の table と merge できるようだ.行を照合するための列の指定は変えられない
  • table から一部の列だけを選んで view を作れる.filter や aggregate をした結果の view は作れない.filter と aggregate はいっしょに使える
  • 作った table の所有者は自分になる.ほかの人に譲渡できる
  • 所有者は,table を private にするか誰でも読めるようにするか選べる.private にすると許可した人々にしか読めない.誰でも読める,にはさらに public on the web と anyone with the link の 2 つがある.検索可能かどうかが違うとのこと (試していない)
  • table を読める人々のほか,所有者は table を編集できる人々を追加できる
  • 所有者と編集者との権限の違いはこれらアクセス権の設定ができるかどうかだけのようだ
  • table の定義を変更できずに table 内容の編集だけができるような人々を設定したいが,できないようだ

Fusion Tables API を使ってアプリケーションから tables を操作できる.

こんなときにいい (こうじゃないときはだめ) と思える.

  • アクセス権を細かく設定しなくていい
  • 全く更新しない
  • 滅多に更新しない.ある程度の時間正しくない (整合性のない) データが入っていてもいい.更新する (した) ときにチェックして直せばいい
  • いつも正しいデータが入っていてほしい table は (頻繁に更新する table とか),正しいデータしか入れられないアプリケーションを用いて更新し,Fusion Tables の web ではやらない.そして,ユーザがそのように言うことを聞いてくれる
  • 関連する複数の tables が両方とも頻繁に更新されるということはない

Credit card fraud

クレジットカードの明細書に覚えのない請求があった.利用店・内容には「MA 0570010670 HONG KONG」とあり,通貨は日本円で額は数千円.
2011/06/26 にカード会社に連絡した.その内容は次.丸括弧内は私.

  • この請求を止めるには現カードの停止,新カードの再発行が必要となる.つまり,毎月の支払いなどに使用していると,それらの店に連絡する手間が生じる.
  • 停止する前に,この番号「0570010670」が店の電話番号なので私から店に照会しろ.(→まったく覚えがないので返金の手続きを取ってもらった)
  • カードはこの電話で無効となるので,鋏を入れて破棄せよ.
  • (この時点までのカードの使用に何か問題が生じるか)→生じない.
  • この請求はいったん銀行口座から引き落される.翌月に返金される.
  • 意義申立書フォームを送るので記入して返送せよ.
  • 意義申立書に従って調査をする.ばあいによっては (どんなばあいかは不明だった) 私とこの請求者との間で交渉する必要がある.それもあるので,カード停止前に私から照会することを勧める.(→同上)
  • (ポイントは新カードに引き継がれるか)→引き継がれる.

検索してみたところ,まったく同じ番号 (0570010670) の事例がみつかった.http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1358085518 (Yahoo!知恵袋.質問日時:2011/3/19 23:00:00) によると,ご利用先はMA0570010670 UNITED KINGDO 47250000 換算レート/1000円 で請求金額47250円です。使用にまったく記憶ありませんが、クレジットの明細には2月22日使用 とあった.

2011/06/30 に新しいカードが届いた.2011/07/01 には異議申立書 (CARDHOLDER'S DISPUTE FORM) のフォームが届いた.7/2 に異議申立書投函.2011/07/26 に届いた翌月の利用明細には返金が計上されていた.

2011/08/03,最初に連絡した時に伝えた電話にカード会社から連絡あり.

  • 「加盟店」によると,この「利用」はインターネットでのもので,旅券あるいは海洋調査に関するもの.(ずいぶんとかけ離れた二つだ.どんな「加盟店」なのだろう)
  • それ以上の詳しい内容は私から「加盟店」に直接連絡しないと回答されない.連絡するか.(→したくないと回答)
  • 「加盟店」の番号 (0570010670) に覚えがないか.(→最初に連絡した時に伝えた通り,覚えはない)

2011-08-12

Google Visualization Data Source Library

web で公開されている CSV ファイル中のデータを Google Chart Tools で図にするためには,それらデータが「datasource」としてアクセスできる必要がある.Google Visualization Data Source Librarygoogle-visualization-java は,makes it easy to implement a Visualization data source so that you can easily chart or visualize your data from any of your data stores. インストラクション「Getting Started」に沿って作業した.

使用したのは RHEL5 x86_64.Tomcat は,rpm パッケージで導入./etc/init.d/tomcat5 start によって出たエラーメッセージを検索し,パッケージ xml-commons-apis を追加で入れた.これは依存関係からは入らなかった.

/etc/tomcat5/tomcat5.conf によると,CATALINA_HOME="/usr/share/tomcat5" だった./usr/share/tomcat5/webapps/ 下に myWebApp/WEB-INF/web.xml をコピー,/usr/share/tomcat5/webapps/myWebApp/WEB-INF/lib/ 下に jar files をコピーした.Tomcat を起動したところ,/usr/share/tomcat5/logs/catalina.out に次のエラーが出た.

SEVERE: Parse error in application web.xml file at jndi:/localhost/myWebApp/WEB-INF/web.xml
java.lang.IllegalArgumentException: Servlet mapping specifies an unknown servlet name graph

web.xml を編集し,以下を削除した.

    <servlet-mapping>
      <servlet-name>graph</servlet-name>
      <url-pattern>/graph</url-pattern>
    </servlet-mapping>

Tomcat 起動.次のエラーが出た.

SEVERE: Servlet /myWebApp threw load() exception
java.lang.ClassNotFoundException: com.mycompany.mypackage.ControllerServlet

web.xml を編集し,以下を削除した.

    <servlet>
      <servlet-name>controller</servlet-name>
      (略)
    </servlet>

Tomcat 起動.

続いて,インストラクション「Using an External Data Store」 に従って作業.web で公開されている CSV ファイルを datasource としてサービスできた.

しかし,この例示されているサーブレットでは,CSV 中すべての列の type が string として処理されてしまう.このため,例えば google.visualization.ScatterChart での描図ができない.CsvDataSourceServlet.java 中にも以下のコメントがあった.これを話題にしているフォーラムもあった.

      // Note: We assume that all the columns in the CSV file are text columns. In cases where the
      // column types are known in advance, this behavior can be overridden by passing a list of
      // ColumnDescription objects specifying the column types. See CsvDataSourceHelper.read() for
      // more details.
      dataTable = CsvDataSourceHelper.read(reader, null, true, requestLocale);

このコメントに従って ColumnDescription を渡すのを試すため,書きかえてみた.diff 結果は以下.

20,21d19
< import com.google.visualization.datasource.datatable.ColumnDescription;
< import com.google.visualization.datasource.datatable.value.ValueType;
40,42d37
< import au.com.bytecode.opencsv.CSVReader;
< import java.util.Arrays;
< 
91,99c86,90
< 	CSVReader csvReader = new CSVReader(reader);
< 	reader.mark((Integer.MAX_VALUE >>> 8));
< 	String[] headers = csvReader.readNext();
< 	reader.reset();
< 	ColumnDescription[] columnDescriptions = new ColumnDescription[headers.length];
< 	for(int i = 0 ; i < headers.length; i++) {
< 	    columnDescriptions[i] = new ColumnDescription(Integer.toString(i), ValueType.NUMBER, headers[i]);
< 	}
< 	dataTable = CsvDataSourceHelper.read(reader, Arrays.asList(columnDescriptions), true, requestLocale);
---
>       // Note: We assume that all the columns in the CSV file are text columns. In cases where the
>       // column types are known in advance, this behavior can be overridden by passing a list of
>       // ColumnDescription objects specifying the column types. See CsvDataSourceHelper.read() for
>       // more details.
>       dataTable = CsvDataSourceHelper.read(reader, null, true, requestLocale);

とりあえず,すべての列の type を number としてみた.BufferedReader の mark(), reset() は,これをしないと出るエラーへの対処.また,mark() への引数は適切ではない.javac -cp visualization-datasource-1.1.1/visualization-datasource-1.1.1.jar:visualization-datasource-1.1.1/lib/icu4j-4_0_1.jar:visualization-datasource-1.1.1/lib/commons-lang-2.4.jar:visualization-datasource-1.1.1/lib/commons-logging-1.1.1.jar:/usr/share/tomcat5/common/lib/\[servlet\].jar:visualization-datasource-1.1.1/lib/opencsv-1.8.jar CsvDataSourceServlet.java によりバイトコードを作成.jar を作成して配備,Tomcat を起動して確認した.

2011-04-23

Java7

OracleとApple、OpenJDK Project for Mac OS X を発表Oracle and Apple Announce OpenJDK Project for Mac OS X との発表が 2010 年 11 月 12 日に Apple 社からあった. OpenJDK は,The place to collaborate on an open-source implementation of the Java Platform, Standard Edition, and related projects. OpejJDK for Mac OS X - doldukeの日記では,Mac OS X Port - OpenJDK - wikis.sun.com をビルドしている.この版はまだ X11 を使っている。 今までの Apple Java というよりは BSD port に近い。早く Cocoa 対応した物を見てみたい。 Building Java 7 on Mac OS X « Infernus でも Java 7 をビルドしている.

また,Java SE 6 が Mac OS X Snow Leopard® 用および次期リリースのMac OS X Lion 用に今後も提供することを確認しました。Mac OS X 用の Java SE 7 と将来のバージョンの Java は、Oracle が提供することになります。とのこと. 現在のところ,Java™ Platform, Standard Edition 7 Binary Snapshot Releases には Mac OS X 用のものはない.

逆に,Installing Java 1.5 back into Snow Leopard | David Orriss Jr – The Delusion That People Care About What I Think では,OS X 10.6 で Java 1.5 を使用できるようにしている.

留守番電話

10 年くらい前には PC を留守番電話にすることは割と一般的だったようだ. 例えば,Click Magazine-マックユーザの部屋-モデムで留守番電話がしたい で示されているソフトウェアもあったようだし, CentOS5 + USB モデムで 留守電/FAX サーバ - パソコン・メモメモ備忘録 という実装もある.The Linux Modem-HOWTO の日付は 4 January 2000 だ. これには,通常のモデムではなくボイスモデム (PCで留守電 | OKWave) が必要なのだが,1990年代後半に製造されていたが、2000年代に入りほとんど製造されていない。 (Wikipedia).

モデムではなく,電話回線の受話アダプター(録音アダプターともいう)を使用して、コンピュータのマイク入力に接続 してのボイスメールの実現が,ボイスメール(上巻) (株式会社ユアネーム) で示されている.

Mac 用の現行製品では,PhoneValet Message CenterOvolab - Phlink がある.PhoneValet には Parliant USB telephone adapterUSB and telephone cablesDual Telephone Jack (splitter) が,Phlink には The Phlink Telephone Adapter is a small USB device that plugs into one of your Mac's USB ports on one side, and to an analog telephone cable on the other side. が同梱され,これらを用いて電話に接続する. 発信電話番号の取得については,PhoneValet may not be compatible with telephone lines in some countries, or may not support advanced services such as Caller ID. Please contact us for more information about your country. (PhoneValet).Q: Does Ovolab Phlink recognize japanese caller ID (JCLID)? A: Currently, no. (Phlink).

新規の電話番号でいいのなら,Message+ のように,ボイスメールは音声メール(音声データ)として管理するサービスも販売されている. また,How to Save Voicemail Forever on Your Mac | Richard K Miller もできるようだ.

発信電話番号

上記株式会社ユアネームのサイトでは,ほかにも第十回 発信者番号通知(Caller ID)取得の実装を示している.オーディオ系の処理は SoX というプログラムを利用している.

ほかにも,モデムを用いたCaller ID - 発信電話番号表示ソフトウェアが公開されている. さらに,ナンバーディスプレイと疑似交換機の作成例も示されている. 『相手の番号を表示する「ナンバーディスプレイ」』( 電話の仕組み(5) - IP電話ONLINE:ITpro) で解説されている.

電話は奥が深い.ダイアモンドアプリコット電話研究所を久々に見てみた.

人口音声

Mac OS X では,AquesTalk - テキスト音声合成ミドルウェアを用いたSayKotoeri2 - Hemus -Macアプリと OS の say(1) Mac OS X Manual Page を組み合わせて実用できる.以下は Ruby でのコード断片.

until text.empty?
    _, ascii, non_ascii, text = */^ *([\ -\~]*)([^\ -\~]*)(.*)$/.match( text )
    system( 'say', ascii ) unless ascii.empty?
    system( 'SayKotoeri2', non_ascii ) unless non_ascii.empty?
end

ところで,音声合成ソフトウェア VoiceText の自然さはすごい.

2011-03-27

被曝線量率観測値を公開している web サイト

被曝線量率観測値を公開している web サイトのリスト.

以下はそのような web サイトのリストのリスト.

2011-02-24

青い画面で時間がかかり Mac がなかなか起動しない

Mac (1.83GHz Mac mini (MB138J/A)) の起動に時間がかかるようになった.起動音,中央に Apple マークの灰色の画面のあと,青い画面の中央にスピナが出るのだが,このスピナが回ったまま数分待たされる.

/var/log/system.log を見たところ,次のように Found a transaction past the completion deadline on bus 0xfd, timing out! (Addr: 5, EP: 3) で時間がかかっていた.

Feb 24 22:41:17 hostname configd[37]: setting hostname to "hostname"
Feb 24 22:41:21 hostname kernel[0]: USBF:     24.325  AppleUSBEHCI[0x2bfb800]::Found a transaction past the completion deadline on bus 0xfd, timing out! (Addr: 5, EP: 3)
Feb 24 22:41:21 hostname configd[37]: AppleTalk startup complete
Feb 24 22:41:33 hostname kernel[0]: USBF:     35.325  AppleUSBEHCI[0x2bfb800]::Found a transaction past the completion deadline on bus 0xfd, timing out! (Addr: 5, EP: 3)
Feb 24 22:41:42 hostname kextd[10]: IOKitWaitQuiet() timed out waiting to write kernel symbols
Feb 24 22:41:44 hostname kernel[0]: USBF:     46.325  AppleUSBEHCI[0x2bfb800]::Found a transaction past the completion deadline on bus 0xfd, timing out! (Addr: 5, EP: 3)
Feb 24 22:41:52 hostname kextd[10]: writing kernel link data to /var/run/mach.sym
Feb 24 22:41:55 hostname kernel[0]: USBF:     57.326  AppleUSBEHCI[0x2bfb800]::Found a transaction past the completion deadline on bus 0xfd, timing out! (Addr: 5, EP: 3)
Feb 24 22:42:06 hostname kernel[0]: USBF:     68.326  AppleUSBEHCI[0x2bfb800]::Found a transaction past the completion deadline on bus 0xfd, timing out! (Addr: 5, EP: 3)
Feb 24 22:42:10 hostname configd[37]: InterfaceNamer: timed out waiting for IOKit to quiesce
Feb 24 22:42:10 hostname configd[37]: InterfaceNamer: Busy services :
Feb 24 22:42:10 hostname configd[37]: InterfaceNamer:   Macmini2,1 [1]
Feb 24 22:42:10 hostname configd[37]: InterfaceNamer:   Macmini2,1/AppleACPIPlatformExpert [1]
Feb 24 22:42:10 hostname configd[37]: InterfaceNamer:   Macmini2,1/AppleACPIPlatformExpert/PCI0@0 [1]
Feb 24 22:42:10 hostname configd[37]: InterfaceNamer:   Macmini2,1/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI [1]
Feb 24 22:42:10 hostname configd[37]: InterfaceNamer:   Macmini2,1/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/USB7@1D,7 [1]
Feb 24 22:42:10 hostname configd[37]: InterfaceNamer:   Macmini2,1/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/USB7@1D,7/AppleUSBEHCI [1]
Feb 24 22:42:10 hostname configd[37]: InterfaceNamer:   Macmini2,1/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/USB7@1D,7/AppleUSBEHCI/iPod@fd630000 [2]
Feb 24 22:42:10 hostname configd[37]: InterfaceNamer:   Macmini2,1/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/USB7@1D,7/AppleUSBEHCI/iPod@fd630000/IOUSBInterface@0 [1]
Feb 24 22:42:10 hostname configd[37]: InterfaceNamer:   Macmini2,1/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/USB7@1D,7/AppleUSBEHCI/iPod@fd630000/IOUSBInterface@0/IOUSBMassStorageClass [1]
Feb 24 22:42:14 hostname kernel[0]: display: Not usable
Feb 24 22:42:17 hostname kernel[0]: USBF:     79.327  AppleUSBEHCI[0x2bfb800]::Found a transaction past the completion deadline on bus 0xfd, timing out! (Addr: 5, EP: 3)
Feb 24 22:42:29 hostname kernel[0]: USBF:     91.327  AppleUSBEHCI[0x2bfb800]::Found a transaction past the completion deadline on bus 0xfd, timing out! (Addr: 5, EP: 3)
Feb 24 22:42:40 hostname kernel[0]: USBF:     102.328 AppleUSBEHCI[0x2bfb800]::Found a transaction past the completion deadline on bus 0xfd, timing out! (Addr: 5, EP: 3)
Feb 24 22:42:52 hostname kernel[0]: USBF:     114.328 AppleUSBEHCI[0x2bfb800]::Found a transaction past the completion deadline on bus 0xfd, timing out! (Addr: 5, EP: 3)
Feb 24 22:43:03 hostname kernel[0]: USBF:     125.328 AppleUSBEHCI[0x2bfb800]::Found a transaction past the completion deadline on bus 0xfd, timing out! (Addr: 5, EP: 3)
Feb 24 22:43:15 hostname kernel[0]: USBF:     137.329 AppleUSBEHCI[0x2bfb800]::Found a transaction past the completion deadline on bus 0xfd, timing out! (Addr: 5, EP: 3)
Feb 24 22:43:26 hostname kernel[0]: USBF:     148.329 AppleUSBEHCI[0x2bfb800]::Found a transaction past the completion deadline on bus 0xfd, timing out! (Addr: 5, EP: 3)
Feb 24 22:43:38 hostname kernel[0]: USBF:     160.330 AppleUSBEHCI[0x2bfb800]::Found a transaction past the completion deadline on bus 0xfd, timing out! (Addr: 5, EP: 3)
Feb 24 22:43:49 hostname kernel[0]: USBF:     171.330 AppleUSBEHCI[0x2bfb800]::Found a transaction past the completion deadline on bus 0xfd, timing out! (Addr: 5, EP: 3)
Feb 24 22:44:01 hostname kernel[0]: USBF:     183.331 AppleUSBEHCI[0x2bfb800]::Found a transaction past the completion deadline on bus 0xfd, timing out! (Addr: 5, EP: 3)
Feb 24 22:44:12 hostname kernel[0]: USBF:     194.331 AppleUSBEHCI[0x2bfb800]::Found a transaction past the completion deadline on bus 0xfd, timing out! (Addr: 5, EP: 3)
Feb 24 22:44:24 hostname kernel[0]: USBF:     206.331 AppleUSBEHCI[0x2bfb800]::Found a transaction past the completion deadline on bus 0xfd, timing out! (Addr: 5, EP: 3)
Feb 24 22:44:35 hostname kernel[0]: USBF:     217.332 AppleUSBEHCI[0x2bfb800]::Found a transaction past the completion deadline on bus 0xfd, timing out! (Addr: 5, EP: 3)
Feb 24 22:44:47 hostname kernel[0]: USBF:     229.332 AppleUSBEHCI[0x2bfb800]::Found a transaction past the completion deadline on bus 0xfd, timing out! (Addr: 5, EP: 3)
Feb 24 22:44:58 hostname kernel[0]: USBF:     240.333 AppleUSBEHCI[0x2bfb800]::Found a transaction past the completion deadline on bus 0xfd, timing out! (Addr: 5, EP: 3)
Feb 24 22:45:10 hostname kernel[0]: USBF:     252.333 AppleUSBEHCI[0x2bfb800]::Found a transaction past the completion deadline on bus 0xfd, timing out! (Addr: 5, EP: 3)
Feb 24 22:45:21 hostname kernel[0]: USBF:     263.333 AppleUSBEHCI[0x2bfb800]::Found a transaction past the completion deadline on bus 0xfd, timing out! (Addr: 5, EP: 3)
Feb 24 22:45:32 hostname kernel[0]: USBF:     274.334 AppleUSBEHCI[0x2bfb800]::Found a transaction past the completion deadline on bus 0xfd, timing out! (Addr: 5, EP: 3)
Feb 24 22:45:43 hostname kernel[0]: USBF:     285.334 AppleUSBEHCI[0x2bfb800]::Found a transaction past the completion deadline on bus 0xfd, timing out! (Addr: 5, EP: 3)
Feb 24 22:45:54 hostname kernel[0]: USBF:     296.335 AppleUSBEHCI[0x2bfb800]::Found a transaction past the completion deadline on bus 0xfd, timing out! (Addr: 5, EP: 3)
Feb 24 22:46:05 hostname kernel[0]: USBF:     307.335 AppleUSBEHCI[0x2bfb800]::Found a transaction past the completion deadline on bus 0xfd, timing out! (Addr: 5, EP: 3)
Feb 24 22:46:14 hostname /usr/libexec/hidd[28]: Timeout waiting for IOKit to be quiet 
Feb 24 22:46:14 hostname /usr/libexec/hidd[28]: IOHIDEventQueueCreate: Unable to allocate queue memory from IOHIDSystem. (0x10000003)

System Profiler で見たところ,本体の USB ポートのうち 1 つが Bus Number: 0xfd だった.これが上のログで言われている bus だろう.このポートには USB ハブをもつディスプレイを接続している.ディスプレイには iPod と携帯電話を接続していた.ログメッセージ中にある Addr: 5, EP: 3 がデバイスを示しているとも思えるが,不明.上のログにあるように iPod には Busy services とのメッセージが出ている.携帯電話には Mac 用のドライバなどが提供されていないため,ただ充電するために接続している.

とりあえず,iPod と携帯電話をディスプレイから外して起動するようにして,様子を見ることにした.もし解決したら次は片方ずつ接続して原因を突き止めようと思う.もし解決しなかったらディスプレイから本体への USB は外し,ディスプレイの USB ハブは諦める.

つづく.

2011-02-22

Terminal.app 中の範囲選択をキーボードで

Mac OS X の Terminal.app 中で範囲を選択してクリップボードにコピーする操作をキーボードだけでできないか?と思い調べた. Apple - Support - Discussions - keyboard selection in Leopard Terminal で話題となっていた. Keyboard text selection in Terminal | Software | Mac OS X Hints | Macworld によると,10.4 の Terminal.app では「Keyboard Selection」ができたようだ. osx - Select text from Terminal.app using the keyboard in OS X - Super User では Terminal.app の代替として iterm2 を紹介している.

ネットワークの伝送効率と遅延を ping を用いて測定する

localhost とある host との間の伝送効率と遅延を ping を用いて測定した.ping を使うアイデアは,pingでネットワークの速度を調査する - @IT にて示されている.以下の bash プログラムでは,大きさの異なるパケットを指定された host に対して ping し,往復にかかった時間を測る.これらパケットサイズと往復にかかった時間との関係に一次関数を仮定し,フィッティングして得た傾きと切片をそれぞれ伝送効率と遅延とする.最小二乗フィッティングには gnuplot を使った.その後一定時間の休みを挟み,測定を繰り返す.各繰り返しでは,その繰り返しで測定した結果だけではなく,それまでに測定した結果をすべてフィッティング対象にする.

#!/bin/bash

readonly counts=1
readonly maxsize=1472
readonly sleepsecond=600

remote="${1}"
shift
if [ "x${remote}" = 'x' ]; then
    echo "Usage: ${0} remote_host" >&2
    exit 1
fi

resultfile=$( mktemp )
trap "rm -r ${resultfile}" EXIT

countsprev=0
for (( i=1;; i++ ))
do
    s=${maxsize}
    while true
    do
        if [ ! ${s} -gt 0 ]; then
            break
        fi

        unset pattern
        while [ "x${pattern}" = 'x' ]
        do
            pattern=$(hexdump -e '/2 "%02x"' -n "${s}" /dev/urandom)
        done
        
        ping -c "${counts}" -p "${pattern}" -s "${s}" "${remote}" \
            | awk '$2 == "bytes" && $3 == "from" && $4 = "'"${remote}"':" { print $1, $7 }' \
            | while read size time
        do
            if [ "x${size}" = 'x' ]; then
                continue
            fi
            if [ "x${time}" = 'x' ]; then
                exit 128
            fi
            time_ms="${time#time=}"
            echo "${size} ${time_ms}" >> "${resultfile}"
        done
        if [ $? -eq 128 ]; then
            break
        fi
        if [ $? -ne 0 ]; then
            echo "Failed: ping -c ${counts} -p ${pattern} -s ${s} ${remote}" >&2
        fi

        s=$( echo "scale=0; ${s}/1.41421356" | bc )
    done

    echo "data [${i}]:"
    tail -$( expr $( wc -l < "${resultfile}" ) - ${countsprev} ) ${resultfile}
    countsprev=$( wc -l < "${resultfile}" )
    echo "data [${i}] end: ${countsprev}"

    gnuplot -persist <(echo \
"fit a*x+b '${resultfile}' using 1:2 via a, b
print \"transport rate: \", 1000/a/1024/1024*2, \" Mbytes/s\"
print \"      overhead: \", b, \" ms\"
plot a*x+b, '${resultfile}' using 1:2") 2>&1 \
    | sed -n '/^After [1-9][0-9]* iterations the fit converged\. *$/,$ p'

    sleep "${sleepsecond}"
done

2011-01-22

リモートのテープを用いた tar

リモートのテープに tar を出力するには,tar -cf - files | rsh remote dd of=/dev/tape obs=size のように以前は dd を用いていた (http://download.oracle.com/docs/cd/E19963-01/821-1459/6nmem32ee/).Solaris の man には例も載っていたように思う.

調べたところ,GNU tar では rmt(8) を用いることになっている (GNU tar 1.25: 9.2 Remote Tape Server).例えば,tar -c --rsh-command=/usr/bin/ssh -vf user@remote:/dev/tape files のように実行する (GNU tar 1.25: 9.1 Device Selection and Switching).この例では rsh ではなく ssh を使っている.私の環境では必要なかったが,オプション --rmt-command=cmd Notifies tar that it should use cmd instead of the default

2010-12-02

Ruby on Rails Tips

参考とすべき文献

2010-12-01

Ruby on Rails における論理削除

Ruby on Rails の model において論理削除を可能にする方法を調べた.

論理削除された行であることを示す列による

Plugin acts_as_paranoidRuby on Rails ステップアップ講座 - 大場寧子 (2007-11-26) により紹介されていた.私は試験していない.acts_as_paranoid とした model の表に列 deleted_at を追加し,この列が null でなく論理削除した時刻がある行は論理削除されているとする.

作者は i quit using acts_as_paranoid long ago. i tend to use `hidden` and `visible` scopes for my models (Feb 23rd, 2009) と述べている.scope を用いたやりかたについては後で述べる.

別のやりかた:削除して別の表に入れておく

Plugin acts_as_trashable では migrate に ActsAsTrashable::TrashRecord.create_table を追加することにより,表 trash_records が追加される.なお,追加に対応してこの表を削除するようなメソッドは提供されていない.論理削除した行は,表から削除されて表 trash_records に格納される.このやりかたを採った理由について,Another method of solving the issue that this plugin addresses is to add a status flag on your model and consider records with the flag set to be deleted (for example see ActsAsParanoid[http://ar-paranoid.rubyforge.org/]). This is definitely a safer method of keeping the records since the data is never actually deleted. However, it presents a more complicated solution and you'll need to guard against ever accidentally showing a deleted record. The best method to use will depend on your application. と述べている (README).複数の models を acts_as_trashable としたばあい,論理削除された行はすべて表 trash_records に格納される.

また,Finally, this plugin has a companion plugin ActsAsRevisionable[http://actsasrevisions.rubyforge.org/] which allows you to keep a history of revisions to records each time they get updated. Using both together gives you a more robust restoration system. They are not packaged together because some applications may not have a use for the revisioning but do need the protection against accidental deletion. とあるように (README),改訂履歴の保持を可能にする別の Plugin acts_as_revisionable と併用できる.

Plugin acts_as_soft_deletable も私は試験していない.README によれば,acts_as_soft_deletable とした model の表の論理削除行を格納する別の表を作成する点は acts_as_trashable と同様.違いは,複数の models の表それぞれの論理削除行を格納するためにそれぞれ別の表を用意する点にある.

Acts_as_paranoid の問題点を Acts_as_paranoid takes the approach of using a deleted_at flag in the models table. If the deleted_at column has a value, the row is considered 'deleted'. The problem with this approach is that all finds on the model have to exclude 'deleted' rows. This turns out be be a challenge. Acts_as_paranoid patches the ActiveRecord internals to accomplish this, but it is fragile and could break with future changes to ActiveRecord. Also, some of the more exotic finds currently don't work (has_many :through with polymorphism as of March 2008) and supporting them means running on an upgrade treadmill to keep up with the evolution of ActiveRecord. と述べている (README).

また,Before using this with a new Rails 2.3 app, you may want to consider using the new default_scope feature (or named_scopes) with a deleted_at flag. See http://ryandaigle.com/articles/2008/11/18/what-s-new-in-edge-rails-default-scoping for a discussion about this. と,default_scope について言及している.

ふたたび,論理削除された行であることを示す列による--- scope を用いて

default_scope を用いたやりかたについては,Ryan's Scraps: What's New in Edge Rails: Default Scoping (November 18, 2008;コメント),with_scope with scope — err.the_blog (November 28, 2006;コメント) で議論されている.最大の問題 (と私が考えたの) は Killing is_paranoid (2009/10/13;Plugin is_paranoidUsing default_scope to recreate acts_as_paranoid [2009/03/22] にて発表された) で指摘されたもので,About default_scope not being default-enough for is_paranoid: Imagine you have a product model with a default scope that specifies that only products with in_stock = true should be selected (we don’t want to show out-of-stock products by default). Cool, that works on simple finds. Now let’s imagine we have categories which have many products. Category.find(:first, :include => :products) works, but it doesn’t respect the default_scope on the eager-loading of products so you get out-of-stock items. ほか (引用した例では Category) から参照されている行 (引用した例では Product) を論理削除したばあいの挙動がおかしいということで,物理削除ならば null とされるべき参照が該当する.コンポジション関係であれば親を論理削除したときに子も同時に論理削除できるので,このような問題は生じない.

Easy « paranoid  with Rails 3 and state_machine « Slainer68's Blog (25/08/2010) は state_machine と併用したやりかたを示している.前述の問題を解決しているかは不明 (I know there were some problems with default_scoping on Rails 2, don’t know if all these problems have been fixed on Rails 3.).Rail Spikes: Using acts_as_archive instead of soft delete (February 26, 2010) とこれに対するコメントはそれぞれ Plugins acts_as_archive ならびに acts_as_archival を紹介している.acts_as_archival は,親の "archive" によって子も "archive" する.また,destroy ほか ActiveRecord メソッドのオーバーライドはしないため,acts_as_archival とされた表がほかから参照されていたとき,Category.find(:first, :include => :products) のような問い合わせに対して archived な行も unarchived な行も区別しないのは変わらないが,Product.find() の結果とは矛盾しない.acts_as_archive は削除行を別の表に入れる.

とりあえずの結論

コンポジション関係しかない表の親子には Plugin is_paranoid のような方法が適当と思う.このやりかたの plugin で現在もメンテされているものが見つからないのが問題である.Plugin acts_as_archival では,表がこれにあたるか調べてから必要に応じて archived な行と unarchived な行を区別しなければならない.しかし,コンポジション関係でない参照では,これよりほかにやりかたがないように思える.

削除して別の表に入れておくやりかたは「なんとなく」好きになれない.理由を追及できたら追記したいと思う.

2010-11-14

/etc/init.d/thttpd の修正

thttpdを Debian パッケージ thttpd_2.23beta1-5_powerpc.deb で導入したのだが,/etc/init.d/thttpd に問題があり stop ができなかった.if ps ax | grep -q "^$PID"; thenif ps ax | grep -q "^ *$PID "; then に換えた.旧安定板 etch を使っているのが悪いのだが.

2010-11-07

Debian 旧安定版を使うよう source.list を書く

現在玄箱を etch で使用している.Debian GNU/Linux 4.0 は Debian GNU/Linux 5.0 ("lenny") で置き換えられました。セキュリティアップデートは 2010 年 2 月末に打ち切られました。 (Debian 「etch」 リリース情報) 注意: Debian 4.0 (etch) のサポートは 2010/02/15 で終了しました。今後、玄箱に Debian をインストールしようとする方は、玄箱に Debian 5.0 (lenny) をインストールする のページを参考にして下さい。 (玄箱に Debian をインストールする) とあるようにアップグレードする必要があるが,機会あるときやることにする.

/etc/apt/sources.list 中には配布元を次のように指定していたのだが,もう配布されていないため apt-get などではエラーとなる.

deb http://security.debian.org/ etch/updates main contrib non-free
deb http://ftp.jp.debian.org/debian/ etch main contrib non-free
deb http://ftp.jp.debian.org/debian-volatile/ etch/volatile main contrib non-free

how to add oldstable repository to sources.list in debian - Super User で示されているように,archive.debian.org を配布元として用いる.http://archive.debian.org/README を参照し,次のようにした.

deb http://archive.debian.org/debian/ etch main contrib non-free
deb http://archive.debian.org/debian-volatile/ etch/volatile main contrib non-free
deb http://archive.debian.org/debian-security/ etch/updates main contrib non-free

2010-10-22

結び

索を接着するには,web site Machovec.com 中の解説 Splicing Instructions が詳しい.また,掛け・巻き・結節・輪結び・結着・結合についての解説 Knots もある.財団法人帆船日本丸記念財団/編集発行『結び KNOTS』(1988),にいざかかずお/作『むすび』(1975;月刊予約・科学絵本『かがくのとも』;福音館書店) という良い本がある.

2010-07-08

ClamAV on Debian

See ClamAV Installation and Configuration -- Debian Admin.

The daemon to update virus database is kicked by /etc/init.d/clamav-freshclam.

Scheduled scanning is by cron like:

$ sudo crontab -u clamav -l
43 11 * * *     clamscan -r /

2010-07-07

Configure Debian to connect WiFi

Configured Debian on a laptop to connect some wireless LANs.

First, the driver ipw2200 is needed. Debian package is firmware-ipw2x00. See ipw2200 - Debian Wiki. wpa_supplicant can be installed by Debian package wpasupplicant. See WiFi/HowToUse - Debian Wiki. To switch between some wireless LANs, install ifscheme.

My /etc/network/interfaces contains the followings.

auto eth2
mapping eth2
        script ifscheme-mapping

iface eth2-a inet dhcp
        wpa-ap-scan 2
        wpa-scan-ssid 1
        wpa-ssid xxxxx
        wpa-psk xxxxx
        wpa-key-mgmt WPA-PSK
        wpa-proto WPA
        wpa-pairwise TKIP
        wpa-group TKIP

iface eth2-b inet dhcp
        wpa-ap-scan 2
        wpa-scan-ssid 1
        wpa-ssid xxxxx
        wpa-psk xxxxx
        wpa-key-mgmt WPA-PSK
        wpa-proto WPA
        wpa-pairwise TKIP
        wpa-group TKIP

Parameters ap-scan and scan-ssid were set in order to connect hidden ssids according to /usr/share/doc/wpasupplicant/README.modes. key-mgmt, proto, pairwise and group were set to connet WPA-PSK/TKIP according to /usr/share/doc/wpasupplicant/examples/wpa-psk-tkip.conf.

To switch wireless LAN, issue a command like ifscheme eth2-a as root. By putting foo ALL=NOPASSWD: /sbin/ifscheme to sudoers, User foo can switch by issuing sudo /sbin/ifscheme eth2-b without password.

2010-06-24

web で公開しているファイル群を BitTorrent で配布するには:その 3

web で公開しているファイル群を BitTorrent で配布するには:その 2 からのつづき.

BitTorrent の web seeding には,2 つの仕様がある.今回作成した metainfo で使用したのは Getright Webseeding spec (HTTP/FTP Seeding for BitTorrent).これに対応したクライアントは Comparison of BitTorrent clients によれば,BitComet,BitTyrant,µTorrent,Vuze である.

試したように Vuze では合計 2 GB を超えるばあいはダウンロードできなかった.BitTyrant は試していないが,Vuze と同様に Azureus を使っているので,同様の問題があると思われる.µTorrent は Web seed support for single-file torrents なので,今回作成した複数のファイルを対象とした metainfo には対応していない.

BitComet 1.21 ではダウンロードに成功した.ただし,Buildtorrent の -w オプションに与える web seeder の URL はスラッシュ / で終わっていなけばならなかった.

2010-06-21

web で公開しているファイル群を BitTorrent で配布するには:その 2

web で公開しているファイル群を BitTorrent で配布するにはのつづき.

前の記事で書いたように BitTorrent の metainfo ファイルを作り,Vuze でのダウンロードに成功したように見えたのだが,問題が見つかった.400 点弱のファイル群を 1 つの metainfo で配布しようとしたのだが,何度試してもある piece でダウンロードが停止してしまい,以降の piece はどれもダウンロードされなかった.Vuze のログを見たところ「IP Filters」でブロックされてしまっていた.デフォルト設定では「Block peers that consistently send bad data」するようになっており,これによって web server が peer としてブロックされていたようだ.「Tools」---「IP Filters」メニューで示される「Blocked IPs」ウィンドウ中の「IPs that have sent bad data - banned if limits exceeded」に web server が加えられていた.

なぜ不正なデータを送っていると見なされたのだろうか.Vuze Forums: Problems with http seeded torrents ... によると,SHA1 ハッシュ値が合致しないとそう扱われるとある.

ファイルに問題があるのかと考え,ls -1ls -1r に替えてファイル順を逆にして metainfo を生成してみた.その結果,まったく同じ位置の piece から後がダウンロードされなかった.このことから,ファイルに問題はないと考えた.

また,おもしろい現象があった.Buildtorrent は -L オプションの引数で piece の大きさを 2引数 bytes に指定できる.これを 17 と 20 にして試したところ,17 では 16384 番とその後の piece が,20 では 2048 番とその後がダウンロードできなかった.つまり,丁度 2 Gbytes = 231 bytes までしかダウンロードできなかった.このファイル群とは別のファイル群でも試した.合計 2 GB 未満のファイル群 2 点はいずれもダウンロードできた.合計 2 GB を超えるファイル群 2 点はいずれも丁度 2 GB となる piece までしかダウンロードできなかった.

Buildtorrent で生成した metainfo 中のハッシュ値が誤っているのだろうか.別の方法でハッシュ値を計算して比較してみよう.metainfo 中では,全ファイルをリストされる順序に連結したものを piece 長に切り分けたものに対する binary SHA1 ハッシュ値 20 bytes を piece 順に連結したものが格納される.以下の 2 つのプログラムを書いた.

#!/bin/bash

piecesize=262144

if [ $# -lt 1 ]; then
    echo "Usage: $0 file ..." >&2
    exit 1
fi

totallength=`cat "$@" | wc -c`
numberpieces=`expr ${totallength} / ${piecesize}`


for (( cursor=0; cursor<=${numberpieces}; cursor++ ))
do
    cursorbyte=`expr ${cursor} '*' ${piecesize}`
    cat "$@" ¥
        | tail -c `expr ${totallength} - ${cursor} '*' ${piecesize}` ¥
        | head -c "${piecesize}" ¥
        | openssl dgst -binary -sha1
done

もちろんこの bash のコードは効率が悪い.

#!/usr/bin/perl -w

use strict;
use Digest::SHA1 qw(sha1);

my @files = @ARGV;
my $size = 2**18;

my $carryover;
foreach my $file ( @files ) {
    open( FILE, "< $file" ) or next;
    while( my $length = read( FILE, my $piece, ( $carryover? $size - length( $carryover ): $size ) ) ) {
        $carryover and $piece = $carryover . $piece;
        undef( $carryover );
        if ( length( $piece ) < $size ) {
            $carryover = $piece;
            last;
        }
        print sha1( $piece );
    }
    close( FILE ) or die;
}
$carryover and print sha1( $carryover );

perl モジュール Digest::SHA1 での計算結果は,Buildtorrent のものと等しかった.bash から呼んだ openssl dgst での計算結果も等しかった.

また,ついでだが,Buildtorrent で必須とされているためダミーの値を与えていた Announce URL は,生成した metainfo を sed 's|8:announce30:dht://trackerless.dht/announce||' して除去できることがわかった.metainfo ファイルは bencode (びーえんこーど) されている.

つづく.

2010-06-17

web で公開しているファイル群を BitTorrent で配布するには

HTTP で公開しているファイル (群) を BitTorrent (BitTorrent プロトコル仕様書) で配布する方法を調べ,特定のクライアントでのダウンロードに成功した.

BitTorrent プロトコルの拡張には,Web Seeding (Wikipedia 英語版) という方法がある.また,トラッカーなしで配布を行なうことができる trackerless と呼ばれる方法もある.ここでは,この 2 つの条件を入れた配布を目指した.

配布したいファイルが大量にあるばあい,command line で torrent ファイルが生成できることが望ましい.command line ツールとしては,Buildtorrent がある.以下のようにして torrent ファイルを生成した.同じく command line ツールの mktorrent - Create BitTorrent metainfo files from command line は試さなかった.

ls -1 directory(s)/file(s) | sed 's:^\(.*\)$:\1|\1:' \
| buildtorrent -q -m -p 0 または 1 -a 'dht://trackerless.dht/announce' -w web site の URL -f - -n name torrent ファイル

web seeding における配布ファイルの URL 指定の方法はトリッキーで,HTTP/FTP WebSeeding Method for BitTorrent - GetRight Download ManagerHow to make torrent file with web seed and multiple files ? - Forums - µTorrent - The Lightweight and Efficient BitTorrent Client で解説されている.上のように生成した torrent は,web site の URL/name/directory(s)/file(s) を URL とするファイル (群) の配布を実現する.

オプション Announce URL -a は Buildtorrent では必須であるが,trackerless torrent ではこのフィールドはない (DHT Protocol).ここでは無効な URL を与えてみた.

Vuze ではこの torrent をダウンロードすることができた (Mac OS 10.6 X および Windows XP).Mainline BitTorrentµTorrent および Transmission のいずれもこれをダウンロードすることはできなかった (すべて Mac OS X 10.6).原因は追及していないが,Announce URL が無効なこと,BitTorrent seeder がないこと,あるいはこれら両方かもしれない.

つづいた.

2010-05-25

Bushnell 社の GPS 受信機『Backtrack』

霧などで目標が得られず,地図と方位磁石だけでは現位置がわからない状況で役立つと考え,Bushnell 社Backtrack という GPS 受信機を買った (Backtrack User's Manual).方位指示機能のほか,登録した地点への向き・距離を表示する機能がある.登録できる地点は 3 点で,登録したい地点において操作することで,その地点を登録することができる.まだ行ったことのない地点を登録することはできない.また,緯度経度を表示することはできない.

Amazon.co.jp で買ったのだが,日本の業者から発送される日本語取扱説明書が付属するものより,米国より発送されるものの方が安く,こちらを買った.色は選べなかったが,Gray/Orange が届いた.

2010-05-08

シーカヤックと国際 VHF

シーカヤックを始めた.まだまだ上手くはないが,いずれ長い距離を漕いでみたい.緊急事態に備えて船舶無線について調べるうち,国際 VHF というものを知った.シーカヤックにも積めそうな,トランシーバ型のものも販売されている (国際VHF無線機国際VHF無線機 | ワイズギア).見つかったもののうち,トランシーバ型のものはどれも 5W で,DSC 機能付きのものもある.これを使うためには,「無線従事者」免許を取得し「船舶局」を開局する.

無線従事者免許について調べた.国際VHF 5W の無線機を使うためには「第三級海上特殊無線技士」,DSC 機能を使うためには「第二級海上特殊無線技士」の免許がそれぞれ必要だそうだ (上で参考とした無線機製品のサイトより).財団法人日本無線協会で試験を受ける.第二級海上特殊無線技士の次の試験は,10 月 6 日 (水) 11:00 から,8 月 1 日から 20 日までが受験申し込み期間だそうだ (日本無線協会のサイトより).

船舶局の開局申請には,「無線局免許申請書」を出すのだが (総務省 電波利用ホームページ | 免許,無線局の免許手続き,免許総務省 電波利用ホームページ | ダウンロードお知らせ − 技術基準適合証明等を受けた国際VHFを使用したレジャー用船舶局の免許申請について - 東海総合通信局総務省 電波利用ホームページ | 無線局免許手続様式中「1.無線局免許申請書及び再免許申請書」中「2 上記以外の無線局用の免許申請書及び再免許申請書…」の「記載要領 (PDF)」,「2.無線局事項書及び工事設計書」中「6 船舶局」の「無線局事項書」の「記載要領 (PDF)」と「工事設計書」の「記載要領 (PDF)」),ここで問題になるのが添える「船舶検査証書」の写し.「ろ・かい・さお のみで運転する船舶[ただし、7人以上の旅客の運送を行うものは免除されない。]」にあたるシーカヤックには船舶検査がない (日本小型船舶検査機構).これを話題にしたサイトもあった (国際VHF/マリンVHF開局している奴,レス 83,663--670;国際VHFはシーカヤックでも開局できるのでしょうか? - Yahoo!知恵袋).

2010-05-01

flot: X 軸と Y 軸の入れ替え・軸の反転

flot の使い方.

X 軸と Y 軸を入れ替えるために,canvas の 2D context を rotate しようと試みたが,うまくいかなかった.$.plot() に与えるデータ中で入れ替えれば良いが,hook processDatapoints で入れ替えることもできる.

右から左に向かって増加する軸,上から下に向かって増加する軸を設定するために,transforminverseTransform を用いようとしたが,うまくいかなかった.Flot Reference によれば,Flot assumes that the transform function does not reorder values (monotonicity is assumed). これを実現するためには,$.plot() に与えるデータ中あるいは hook processDatapoints で値の正負を逆転し,軸の tickFormatter に正負を逆転した文字列を返すような関数を与える.

$.plot($( '#placeholder' ), data, {
  hooks: {
    processDatapoints: function( plot, series, datapoints ) {
      var points = datapoints.points, ps = datapoints.pointsize;
      for (var i = 0; i < points.length; i += ps) {
        var x = points[i];
        var y = points[i+1];
        points[i] = y;
        points[i+1] = -x;
      }
    }
  }
  yaxis: {
    tickFormatter: function( val, axis ) { return -val; }
  }
});

JavaScript

JavaScript を書くための資料.

2010-03-31

ローカルファイルを IMAP サーバに格納する

以下の手順によって,ローカルファイルを IMAP サーバに格納することができた.

Maildir 形式ディレクトリの作成

$ mkdir mdir
$ mkdir mdir/new
$ mkdir mdir/cur

格納したいファイルを添付として持つ e-mail メッセージを作成する

次に file2mime.pl を示す.引数にファイルパスを取り,標準出力にメッセージを吐く.ファイル名を Subject に,最終更新日時を Date ヘッダに格納する.メッセージ本文には,stat() 結果を格納する.Perl モジュール MIME::Lite を使用する.MIME::Litemake test を通すためには Email::Date::Format および MIME::Types が必要だった.

#!/usr/bin/perl -w

use strict;
use MIME::Lite;
use Email::Date::Format qw(email_date);
use utf8;
use Encode;
use File::Spec;

my $path = $ARGV[0];
$path or die( "Usage: $0 file" );

my @fileinfo = stat( $path )
    or die( "Could not stat $path" );

my ( $volume, $directories, $file )
    = File::Spec->splitpath( $path );

my $msg = MIME::Lite->new(
    From => 'nobody@nowhere',
    Subject => encode( 'MIME-Header-ISO_2022_JP' => $file ),
    Date => email_date( $fileinfo[9] ),
    Type => 'multipart/mixed'
    );

$msg->attach(
    Type => 'text/plain; charset=utf-8',
    Data => "stat($path):\n".join( "\n", @fileinfo )
    );

$msg->attach(
    Type => MIME::Types->new()->mimeTypeOf( $file ),
    Encoding => 'base64',
    Disposition => 'attachment',
    Filename => encode( 'MIME-Header-ISO_2022_JP' => $file ),
    Path => $path
    );

$msg->print( \*STDOUT );

次に file2mdir.sh を示す.作成した e-mail メッセージファイルの最終更新日時を元のファイルのそれと同じくする.Maidir 形式においては,ファイルのmtimeがメッセージの到着日時maildir(5)となる.

#!/bin/sh

file=1
while [ -e "${1}"/"${file}" ];
do
    file=`expr ${file} + 1`
done

perl -I`dirname "${0}"`/pm/lib/perl5/site_perl `dirname "${0}"`/file2mime.pl \
    "${2}" > "${1}"/"${file}"
touch -r "${2}" "${1}"/"${file}"

次のように実行した.

$ cd file_directory
$ find . -type f -exec file2mdir.sh mdir/new "{}" ";"

Maildir から Mbox への変換

Maildir を mbox に - technolazy.snapshot で示されている Python コードを用いて Maildir 形式のディレクトリを Mbox 形式のファイルに変換する.

$ md2mb mdir mbox

IMAP サーバへの登録

Thunderbird に mbox をインポートし (Manually importing and exporting, Importing and exporting your mail - MozillaZine Knowledge Base),IMAP サーバに送る.

2010-04-03 修正

file2mdir.sh を追加した.

以前に引用した次の Python コードでは,複数の e-mail メッセージを Mbox に正しく変換できなかった.

Maildir to Mbox – yergler.net で示されている Python コードを用いて Maildir 形式のディレクトリを Mbox 形式のファイルに変換する.リンク先ページにある Python コード中のシングルクォート文字が正しくコピーできなかった.

以前に用いた次の Python コードでは,メッセージの到着日時を正しく登録できなかった.このコードの問題なのか Gmail の問題なのかは不明.

IMAP Upload を用いて Mbox ファイルを IMAP サーバにアップロードする.

$ python imap_upload.py --gmail --box Inbox mbox

あるいは,

$ python imap_upload.py mbox imaps://user:pass@imap.gmail.com:993/Inbox

2010-03-21

玄箱の再セットアップ

Debian 化した玄箱が起動しなくなってしまった.結局原因はわからなかったが,再セットアップの記録を残す.背面のリセットスイッチを押したまま起動して EM モードにしても外部から接続できなかったため,HDD を取り出して PC に接続して,第 1 パーティションを書き換えた.その後,起動した玄箱を操作した.

イメージファイルの展開

# mke2fs -j /dev/hdc1
# mount -t ext3 /dev/hdc1 /home1
# cd /home1
# tar xvzf /tmp/debian-etch-2.6.25.1-kuroBOX-20090317.tgz

第 1 パーティションを破壊したあと,『玄箱/Debian/インストール』から得たイメージファイルを,マウントした第 1 パーティションにて展開した.

蛇足だが,HDD を廃棄・譲渡する前など,復元が難しくなるよう消去するには以下のようにする.

# dd if=/dev/zero of=/dev/hdc1
# shred --iterations=1 --zero /dev/hdc1

ネットワークの設定

vi etc/network/interfaces
address 192.168.0.100
network 192.168.0.0
netmask 255.255.255.0
broadcast 192.168.0.255
gateway 192.168.0.1

このように,必要な行を書き換えた.その他,etc/hostsetc/hostnameetc/hosts.allowetc/hosts.denyetc/resolve.conf を編集したあと,再度玄箱を組み立てて起動した.

ユーザアカウントの設定

% telnet 192.168.0.100
...
kuro login: tmp-kun
...
Linux kuro 2.6.25.1-kurobox #10 Sun May 4 21:50:38 JST 2008 ppc

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
1 failure since last login.
Last was Sun Mar 21 09:46:21 2010 on pts/0.

telnet でログイン.

tmp-kun@kuro:~$ su - root
kuro:~# passwd

まずは root のパスワードを変更した.

kuro:~# groupadd --gid 1001 radio
kuro:~# useradd --home-dir /home/radio --gid 1001 --create-home --uid 1001 --shell /bin/bash radio
kuro:~# passwd radio

自分のユーザを追加.

% telnet 192.168.0.100

ログインできることを確認.

kuro:~# userdel tmp-kun
kuro:~# rm -r /home/tmp-kun

テンポラリユーザ tmp-kun を削除.

# useradd --home-dir /nonexistent --gid 1000 --uid 1000 --shell /bin/false note
# useradd --home-dir /mnt/tm --gid 1001 --uid 1002 --shell /bin/false tm

ついでに私はここで,必要なユーザを追加した.

パッケージのアップグレード

kuro:~# vi /etc/apt/sources.list
deb http://ftp.jp.debian.org/debian/ etch main contrib non-free
deb http://ftp.jp.debian.org/debian-volatile/ etch/volatile main contrib non-free

既存の行はすべて無効にして,上記 2 行を追加 (参考:『Debian JP Project - ミラーサイトについて』).

kuro:~# apt-get update
W: GPG error: http://ftp.jp.debian.org etch Release: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 9AA38DCD55BE302B
kuro:~# gpg --keyserver wwwkeys.eu.pgp.net --recv-keys 9AA38DCD55BE302B
kuro:~# gpg --armor --export 9AA38DCD55BE302B | apt-key add -

この対処法は,検索の結果『GPG errorからの回復メモ - プロキオンのはてな』から得た.

kuro:~# apt-get update
kuro:~# apt-get upgrade

必要パッケージのインストール

kuro:~# apt-get install ssh sudo jed jless ntp samba rsync ssmtp

途中,samba のインストールのために Workgroup/Domain Name の入力を求められた.

ssh
% ssh 192.168.0.100
radio@kuro's password: 
radio@kuro:~$ 

SSH でログインできることを確認.

kuro:~# apt-get remove telnetd

telnetd を削除.

sudo
kuro:~# visudo
kuro:~# cat /etc/sudoers 
radio ALL=(ALL) ALL

上記行を追加.

ntp
kuro:~# vi /etc/ntp.conf 
kuro:~# /etc/init.d/ntp restart
ssmtp
kuro:~# vi /etc/ssmtp/ssmtp.conf
root=xxxxxxxx+kuro@gmail.com
mailhub=xxxxxxxx.smtp.xxxxxxx.or.jp:xxx
rewriteDomain=kuro.local
hostname=kuro.local
FromLineOverride=NO
AuthUser=xxxxxxxx
AuthPass=........
AuthMethod=LOGIN
# echo test | sendmail root

私は試していないが,mailhub を gmail にする設定もできるようだ (『Send Mail with Gmail and sSMTP』).

kuro:~# apt-get remove exim

exim を削除.

jless
kuro:~# vi /etc/profile
export PAGER=jless
alias less=jless

bash での設定をするため,上記を追加.

samba
kuro:~# vi /etc/samba/smb.conf
[global]
        dos charset = CP932
        workgroup = WORKGROUP
        server string = %h server
        security = SHARE
        obey pam restrictions = Yes
        passdb backend = tdbsam
        passwd program = /usr/bin/passwd %u
        passwd chat = *Enter\snew\sUNIX\spassword:* %n\n *Retype\snew\sUNIX\spassword:* %n\n *password\supdated\ssuccessfully* .
        syslog = 0
        log file = /var/log/samba/log.%m
        max log size = 1000
        load printers = No
        printcap name = /dev/null
        dns proxy = No
        ldap ssl = no
        panic action = /usr/share/samba/panic-action %d
        invalid users = root
        create mask = 0644

[arch]
        path = /mnt/arch
        guest only = Yes
        guest ok = Yes

[temp]
        path = /mnt/temp
        force user = nobody
        force group = nogroup
        read only = No
        guest only = Yes
        guest ok = Yes

[gt]
        path = /mnt/gt
        valid users = radio
        force user = radio
        force group = radio
        read only = No
        create mask = 0600
        directory mask = 0700
        browseable = No

[tm]
        path = /mnt/tm
        valid users = tm
        force user = radio
        force group = radio
        read only = No
        create mask = 0600
        directory mask = 0700
        browseable = No

[tp]
        path = /mnt/tp
        force user = nobody
        force group = nogroup
        read only = No
        guest only = Yes
        guest ok = Yes
        browseable = No
kuro:~# /etc/init.d/samba restart
kuro:~# smbpasswd radio
kuro:~# smbpasswd tm

Mac OS X での IP aliasing

How to create an IP Alias in Mac OS X using ifconfig - OS X Daily』に,Mac OS X での IP aliasing の方法が示されている.

2010-02-14

使い捨てメールアドレス

私がよく使う使い捨てメールアドレスのサービスとそれらの特徴.

そのほかたくさんある.「使い捨てメールアドレス」で検索「disposable email」で検索

2010-02-08

Dropbox

Dropbox を使っている.無料で 2GB 分を使用できる.Mac ならびに Windows 用のアプリケーションをダウンロードして実行すると,このオンラインストレージをローカルファイルシステムのディレクトリとして使用できるのが特徴 (Linux 用は提供されているが試していない).よくある web ベースのインターフェイスも提供され,他の DropBox ユーザにアクセスを許すディレクトリを設定することもできる.また,ファイル・ディレクトリの履歴を保持していて,この履歴には web インターフェイスからアクセスできる.

iPhone (iPod touch) 用のアプリも提供され,ファイルを開くことができる.もちろん iPhone (iPod touch) が開ける形式のファイルのみ.アプリ写真中のファイルを追加することもできるが,ファイル名は自動で決められてしまう.

『外来語・役所ことば言い換え帳』

数年前から,『外来語・役所ことば言い換え帳』(杉並区役所区長室総務課 編,ぎょうせい,2005) を使っている.

2010-02-04

iPod touch

iPod touch を買った.iTunesにバックアップしたiPhoneのデータを漁る方法iPhone and iPod touch:バックアップについてには,iTunes にバックアップした内容について記されている.

2009-12-24

AquaSKK 4.1

AquaSKK バージョン 4 がリリースされていた.配布されているインストーラでインストールする.このインストーラでは旧バージョンの AquaSKK はアンインストールされず,International コントロールパネル中 Input Menu リスト中で並列して示される.

RemoveAquaSKK を用いて旧バージョンのものをアンインストールする.RemoveAquaSKK のダイアログ中に文字化けがあったが,正常にアンインストールできたようだ.

配布されている RemoveAquaSKK はバージョン 3 に対するもので,現バージョン 4 に対するものはない.以前は,AquaSKK に問題が起きたときのために別アカウントを作っておいて,そのアカウントでログインして RemoveAquaSKK を実行せよとの記述があったが,これも見当たらない.

2009-08-19

ニンテンドー DS の修理品発送キット

ニンテンドー DS Lite が故障した.先日「オンライン修理受付」を申し込み,3 日経った今日「修理品発送キット」が届いた.この発送キットがすばらしい.封書で送られてきた発送キットには段ボール製の「キットボックス」が梱包材 (本体,電源アダプタ,ソフトを入れる袋,封印シール) やゆうパック伝票,梱包・発送法の説明書と共に入っている.この発送キットのみで梱包を完了,発送の準備ができる.ペンやテープなどの道具は一切用いない.伝票はすでに記入されているし,キットボックスは段ボールの組み合わせと封印シールで十分に強固な梱包を可能にしている.

2009-08-16

神奈川県で国際免許

神奈川県で国際免許を手続きするため,二俣川の運転免許試験場へ行った.公安委員会の web サイトになかった情報としては,顔の大きさほかを正しくして焼いた十分に大きい写真を用意して行けば,受け付け時に所定の大きさにカットしてもらえる.

2009-08-04

How to cook japonica rice without rice cooker

The followings is how to cook rice (japonica) not by using rice cooker.

  1. Measure rice by a measuring cup and put it into a bowl
  2. Fill water and remove the water
  3. Wash the rice
  4. Fill water and remove the water in a few times in order to remove ground rice powders
  5. Move the rice to a cookware. A thick one is fine, e.g. a saucepot
  6. Put water in the same volume as the rice
  7. Heat it up by strong fire
  8. When boiled, change to very low flame
  9. By using a wooden spatula, take rice grains from the pot bottom
  10. Put the cover. Wait 10 minutes sharp
  11. Put out the fire. Wait 10 minutes or more

Never remove the pot cover for 20 minutes.

鍋で米を炊くには

炊飯器を使わずに鍋で米 (ジャポニカ種) を炊く手順は次の通り.

  1. 米を研ぐ.計量カップで米をボウルなどに量り入れ,水を満たしたあと捨て,米を研ぐ.そのあと水を数回替える.最後に水をできるだけ切る
  2. 米を鍋に移す.厚手の鍋が良い.米と同量の水を加える
  3. 火にかける.鍋脇から炎がはみ出ない程度の強火
  4. 沸騰したら,トロ火にする.先の平たい木ベラなどで鍋底にくっつきかけた米をはがす
  5. 鍋に蓋をする.ここから 10 分間トロ火
  6. 10 分経ったら,火を止める.ここから 10 分蒸らす

20 分間は決して蓋を取ってはいけない.

2009-07-03

バックログから課題をダンプする

バックログから課題をダンプする』で示したプログラムでは,課題に添付したファイル,課題の変更履歴,status の変更履歴は取得できない.wget を用いて同じ目的のプログラムを書いた.この新しいプログラムでは,課題に添付したファイルを取得することができる.課題の変更履歴,status の変更履歴は取得できない.

2009-07-01

Zebra は ZBar bar code reader に

Zebra Barcode Reader は終了し,ZBar bar code reader がこれに代わったようだ.

ZBar is the bar code reader formerly known as "Zebra".

中央にスピナのある青い画面が繰り返して Mac が起動しない

Mac (1.83GHz Mac mini (MB138J/A)) が起動しなくなった.起動音,中央に Apple マークの灰色の画面のあと,青い画面の中央にスピナが出て,ややあってスピナが消える.ここまでは通常通りだが,このあと再び青にスピナの画面に戻ってしまい,これを繰り返す.

DVD からの起動を試みるも,Option キーも C キーも効かなかった (あとで詳しく述べる).

Mac OS X: シングルユーザモードまたは verbose モードで起動する方法に従い,verbose モードで起動する.問題の時点での表示は以下だった.

May 25 20:34:25 Hostname mds[32]: (Error) Import: importer:0x844800 Importer start failed for 505 (kr:268435459 (ipc/send) invalid destination port)
May 25 20:34:25 Hostname mds[32]: (Error) Import: importer:0x844800 Importer start failed for 505 (kr:268435459 (ipc/send) invalid destination port)
May 25 20:34:29 Hostname mds[32]: (Error) Import: importer:0x844800 Importer start failed for 505 (kr:268435459 (ipc/send) invalid destination port)
May 25 20:34:31 Hostname /System/Library/CoreServices/loginwindow.app/Contents/MacOS/loginwindow[341]: Login Window Application Started -- Threaded auth

検索したところ,Startup hangs with "Login Window Application Started" に行き当った.これに従い,シングルユーザモードで起動したあと以下を実行.この記事で削除するよう示されているファイルのうち,存在しているものを削除した.

/sbin/fsck -fy
/sbin/mount -uw /
cd /Library/Preferences
rm com.apple.loginwindow.plist
cd /Library/Caches
rm -r *
cd /System/Library/Caches
rm -r *
reboot

しかし状況は変わらず.Apple Store の Genius Bar に持ち込んだ.係の方は外付けのハードディスクを接続し,Option キーを用いてこの外付けボリュームから起動.内蔵ボリュームのパーミッションがおかしいと指摘.また,C キーよりも Option キーの方がよいとのアドバイスを貰った.

先に DVD からの起動を試みたとき Option キーも C キーも効かなかったのだが,実は,キーボードは Mac に直接接続されていたのではなく,ディスプレイを介して接続されていた.これを直接接続するように変えたところ,Option キーが働き DVD からの起動に成功した.

Disk UtilityVerify 機能を用いて内蔵ボリュームに対して Verify Disk Permission, Repair Disk Permission を実行し,再起動したところ復旧できた.

パーミッションの修正とキャッシュの消去のどちらが問題を解決したのかはわからない.両方かもしれない.

2009-04-11

バックログから課題をダンプする

SaaS な課題追跡システム』で示したバックログから課題をダンプするプログラムを書いた. 課題に添付したファイル,課題の変更履歴,status の変更履歴は取得できない.

2009-04-06

音声ファイルから 812SH 用の「着うた」を作るには

SHARP 812SH 用の「着うた」を音声ファイルから作成する方法を調べた.まず iTunes を用いて AIFF 形式に変換する.続いて WSD (Wave Sound Decorator) を用いて SMAF/MA-3 形式に変換する.最後に Bluetooth で携帯電話機に転送する.

iTunes を用いての AIFF への変換の際のパラメータは,Sample Rate, 16.000 kHz; Channels, Mono とする.

WSD で AIFF を開いたら,Select All して Normalize する.適宜 Trimming, Fade In, Fade Out する (今回はやらなかった).MA-3 を選んで保存する.

携帯電話機内の転送先は,Sounds & Ringtones (着うた・メロディ) である.

参考

2009-04-04

デジタルカメラで撮影した画像にゴミ

デジタル一眼レフカメラ (ニコン D40AF-S DX ズームニッコール ED 18-55mm F3.5-5.6G II) で撮影した画像の同じ位置に「ゴミ」が写っているのに気付いた.特に青空を撮ったときに顕著だった.これは「ローパスフィルタ」(LPF) に付着したゴミによるものだった.絞り優先モード (A) にして絞り,明るい一様な面を撮影すると,ゴミの輪郭がはっきりする.今回はニコンサービスセンターで清掃してもらった.保証期間 (購入日より 1 年間) 内ならば無料でクリーニングしてもらえるらしい.

参考