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
パフォーマンス的にもっと良い解決方法があるかもしれないけど、まずは動くのが最優先だね :-)
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
Windows でコマンドのパスを探す方法
コマンドプロンプトで,PATH上のファイルの位置を検索する方法 (Vistaの where コマンドをXPで) 曰く、Windows 環境でコマンドパスを探す方法があるそうな。which や type(bash) の代わりになる。
知らなかった。 :-)
> for %V in (wuapp.exe) do @echo %~$PATH:V
C:\Windows\System32\wuapp.exe
確認環境
- Windows 7 SP1
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 でできるんだね。参考にさせてもらったネタ元はこちら。:-)
- IPPro SCコマンド -- あらゆる目的に使えるサービス管理コマンド
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
なるほどね。:-)