zip ファイル作成中に Too many open files (Zip::Error)

zipruby の続き。200超のファイルをzipに追加していたら、こんなエラーが出た。(T^T)

Close archive failed: Failure to create temporary file: 
Too many open files (Zip::Error)


エラーが出たときのスクリプトはこんな感じ。エラーメッセージからすると、ファイルディスクリプタを開きっぱになってるのかな?

Zip::Archive.open("outdir/test.zip", Zip::CREATE) do |ar|
  1000.times do |count|
    entry = "target.txt" + sprintf("%04d", count)
    ar.add_file(entry, "target.txt")
  end
end


おんで、修正したスクリプトがこちら。ファイルを1つ追加するのに zip を open/close させるように変更してみた。Zip::CREATE オプションを指定しておくと、既存zipがあれば追加モードになってくれるから、期待通りに格納してくれる。

1000.times do |count|
  Zip::Archive.open("outdir/test.zip", Zip::CREATE) do |ar|
    entry = "tkuser.txt" + sprintf("%04d", count)
    ar.add_file(entry, "tkuser.txt")
  end
end


パフォーマンス的にもっと良い解決方法があるかもしれないけど、まずは動くのが最優先だね :-)

環境

  • Mac OSX 10.7.5
  • ruby ruby 2.1.0
  • zipruby (0.3.6)

zipruby で zip ファイルを作る

Ruby で zip ファイルを作る方法をメモっとこ。こちらさんを参考にさせてもらいました。:-)

インストール

gem を読み込んで、rb ファイルに require 'zipruby' を追記すればOK。

>gem install zipruby

使い方

1ファイルをzip化する。

Zip::Archive.open("outdir/test.zip", Zip::CREATE) do |ar|
  ar.add_file('tkuser.txt')
end


指定フォルダ以下を全部zip化する。ちなみにパス名は Shift_JIS に変換してみたよ。

Zip::Archive.open("outdir/test2.zip", Zip::CREATE) do |ar|
  Find.find("target_dir") do |path|
    entry = NKF.nkf('-U -s -Lw', path)
    if File.directory?(path)
      ar.add_dir(entry)
    else
      ar.add_file(entry, path)
    end
  end
end


test3.zip ファイルを暗号化する。test3.zip は先に作っておいてね。:-)

Zip::Archive.encrypt("outdir/test3.zip", 'pass123')


簡単だね! (^_^)v

環境

  • Mac OSX 10.7.5
  • ruby ruby 2.1.0
  • zipruby (0.3.6)

Windows でコマンドのパスを探す方法

コマンドプロンプトで,PATH上のファイルの位置を検索する方法 (Vistaの where コマンドをXPで) 曰く、Windows 環境でコマンドパスを探す方法があるそうな。which や type(bash) の代わりになる。

知らなかった。 :-)

> for %V in (wuapp.exe) do @echo %~$PATH:V
C:\Windows\System32\wuapp.exe

確認環境

sc.exe でサービスのスタートアップの種類を変更する

sc.exe の config コマンドで永続的に設定を変更できるらしい。start オプションで delayed-auto にすればよさげだね。:-)

>sc config
使用法:
        sc <server> config [サービス名] <オプション1> <オプション2>...

オプション:
...
 start= <boot|system|auto|demand|disabled|delayed-auto>
...

サービスのスタートアップの種類として覚えておけば良いのはこんなかな。詳細はこちらを参照

auto 自動
demand 手動
disabled 無効
delayed-auto 自動(遅延実行)

単純に cmd から実行するとアクセスが拒否される。そりゃそうだ :-p

>sc config wuauserv start= delayed-auto
[SC] ChangeServiceConfig SUCCESS

>sc config wuauserv start= delayed-auto
[SC] OpenService FAILED 5:

アクセスが拒否されました。


cmd を管理者権限で実行して実行する。

>sc qc wuauserv
[SC] QueryServiceConfig SUCCESS

>sc queryex wuauserv

SERVICE_NAME: wuauserv
        TYPE               : 20  WIN32_SHARE_PROCESS
        START_TYPE         : 2   AUTO_START  (DELAYED)  ★
        ERROR_CONTROL      : 1   NORMAL
        BINARY_PATH_NAME   : C:\Windows\system32\svchost.exe -k netsvcs
        LOAD_ORDER_GROUP   :
        TAG                : 0
        DISPLAY_NAME       : Windows Update
        DEPENDENCIES       : rpcss
        SERVICE_START_NAME : LocalSystem

これで OK :-)

sc.exe でサービス設定を確認してみた

Windows Update サービスが Windows7 まで「自動起動(遅延実行)」だったのが Windows8 から「手動」になった。お客さんPCでこの設定を「自動起動(遅延実行)」にしときたいとのこと。訪問するのも大変なので、とりあえず、バッチを配って変更してもらうことにした。

Windows Update に限らず、サービスに対する操作は sc.exe でできるんだね。参考にさせてもらったネタ元はこちら。:-)


sc の基本構文はこんな。

sc [\\<サーバー名>] <コマンド> <サービス名> [<オプション>] 

稼働中のサービスを取得する場合 query コマンドを指定する。サービス名が分かってると絞り込みできるとのこと。なるほど。φ(.. )

>sc query wuauserv

SERVICE_NAME: wuauserv
        TYPE               : 20  WIN32_SHARE_PROCESS
        STATE              : 4  RUNNING
                                (STOPPABLE, NOT_PAUSABLE, ACCEPTS_PRESHUTDOWN)
        WIN32_EXIT_CODE    : 0  (0x0)
        SERVICE_EXIT_CODE  : 0  (0x0)
        CHECKPOINT         : 0x0
        WAIT_HINT          : 0x0

ちなみに sc で指定するサービス名(SERVICE_NAME)は「コンピュータの管理」で表示されるサービス名(DISPLAY_NAME)とは別モノ。指定するサービス名を知りたい場合、getkeyname で取得できる。なるほどね。φ(.. )

>sc getkeyname "Windows Update"
[SC] GetServiceKeyName SUCCESS
名前 = wuauserv

指定したサービスが他サービスに依存しているか知りたい場合、qc コマンドを使う。DEPENDENCIESで「rpcss」に依存してることが分かる。

>sc qc wuauserv
[SC] QueryServiceConfig SUCCESS

SERVICE_NAME: wuauserv
        TYPE               : 20  WIN32_SHARE_PROCESS
        START_TYPE         : 2   AUTO_START  (DELAYED)
        ERROR_CONTROL      : 1   NORMAL
        BINARY_PATH_NAME   : C:\Windows\system32\svchost.exe -k netsvcs
        LOAD_ORDER_GROUP   :
        TAG                : 0
        DISPLAY_NAME       : Windows Update
        DEPENDENCIES       : rpcss
        SERVICE_START_NAME : LocalSystem


逆に他サービスから依存されているか知りたい場合、enumdepend コマンドを使う。wuauserv の場合、他からの依存なし。lanmanserve の場合、Browser から依存ありってことだね。

>sc enumdepend wuauserv
[SC] EnumDependentServices: entriesread = 0

>sc enumdepend lanmanserver
[SC] EnumDependentServices: entriesread = 1

SERVICE_NAME: Browser
DISPLAY_NAME: Computer Browser
        TYPE               : 20  WIN32_SHARE_PROCESS
        STATE              : 4  RUNNING
                                (STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
        WIN32_EXIT_CODE    : 0  (0x0)
        SERVICE_EXIT_CODE  : 0  (0x0)
        CHECKPOINT         : 0x0
        WAIT_HINT          : 0x0

なるほどね。:-)

Ruby & Rails 関連サイト

ちょっと小ネタを拾いたいときとか、RubyRails で使えるプラグインを探したいとき、どこを探せばいいんだっけ?って良くなってる。 使ってないと忘れるちゃうんで、備忘録としてメモっとこ。:-)

Ruby 公式サイト

本家サイト。日本語だから情報も拾いやすい。

Ruby on Rails 公式サイト

Rails 情報を拾うなら、まずここを見よう。

RubyGems.org

リリースされてるバージョンを確認できる。gem ファイルのダウンロードもできる。

RVM

RVM の使い方が分かる。インストールとか環境設定で迷ったらここを見るべし。:-)

Ruby Toolbox

利用頻度に合わせてレーティングされてる。どうせ使うなら利用頻度の高いものを使った方が良いよね。 :-)

Rails Casts

Snippet 満載。勉強になる。