From: NAJIMA Hiroki Date: 2010-09-17T03:20:57+09:00 Subject: [ruby-dev:42270] WindowsでのKernel.systemの挙動、一貫性について 名島(Nazy)と申します。 [Ruby 1.9-Bug#3836] Kernel.system, spawnがスペースを含むパスで動作しない] の続きですが、チケット違いになるので、こちらで。 本件、まだ落とし穴がありそうなので、いろいろ実験してみました。 数点気になるところがあります。 個人的には、1引数の場合"/"を"\\"を解釈するだけで、 あとはsystem(3)と同じ動作でいいのでは?と思いますが、どれもそうなっていません。 1.ruby 1.8.7でご呈示いただいたコードが動かない。 C:\>C:\ruby187\bin\ruby -v ruby 1.8.7 (2010-06-23 patchlevel 299) [i386-mingw32] C:\>C:\ruby187\bin\ruby -e 'p system(["spa ce.bat"]*2)' false # 1.9系では動く。 C:\>C:\ruby192\bin\ruby -e 'p system(["spa ce.bat"]*2)' This is C:\spa ce.bat. ARG0=""spa ce.bat"" ARG1="" true C:\>C:\ruby191\bin\ruby -e 'p system(["spa ce.bat"]*2)' This is C:\spa ce.bat. ARG0=""spa ce.bat"" ARG1="" true 2.ruby1.9.2のsystem関数はカレントディレクトリを実行パスに含まない。 Windowsなので、ruby1.9.2でもカレントディレクトリをサーチパスに含めるべきで無いでしょうか? 実験1参照 3.1.9.1で、"./"が解釈できない ある意味system関数にそのまま渡すという意味で正しいが、Rubyらしくない。 1.9.2、1.8.7は".\\"と解釈 実験2参照 4.1.9.2で独自のarg0の設定がある 実験4参照 5.1.9.1, 1.8.7はPATH上にコマンドがあるかないで、不思議な挙動の変化が起きる 5−1.PATH上に"spa"があると、カレントディレクトリに"spa ce.bat"があってもカレントディレクトリの"spa.bat"を使う 最終的な挙動は望ましい動作だが、影響するべきでない物が影響している 実験5参照 5−2.PATH上から見つけた誤った実行ファイル("spa ce.bat")のARG0がおかしくなる 実験7、9参照 以下、バージョンによる挙動の検証結果です。 ## 環境の確認 ## C:\>set COMSPEC ComSpec=C:\WINDOWS\system32\cmd.exe C:\>set RUBYSHELL 環境変数 RUBYSHELL が定義されていません # よって、the command shellはcmd.exe C:\>set PATH Path=C:\bin;C:\Windows;C:\Windows\System32 PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.PSC1;.tcl;.RB;.RBW # "spa ce.bat"と"spa.bat"を用意 C:\>type "spa ce.bat" @echo This is %~dpnx0. ARG0="%0" ARG1="%1" C:\>type spa.bat @echo This is %~dpnx0. ARG0="%0" ARG1="%1" # stdlib.hのsystem関数の挙動確認用プログラム C:\>type mysystem.c #include int main(int argc, char *argv[]) { printf("%d\n", system(argv[1])); return 0; } # コンパイル C:\>gcc mysystem.c -o mysystem.exe # 実験1:カレントディレクトリに"spa ce.bat"、"spa.bat"を置いて、コマンド名のみを実行 有:"C:\spa ce.bat" 有:"C:\spa.bat" 無:"C:\bin\spa ce.bat" 無:"C:\bin\spa.bat" C:\>mysystem "spa ce.bat" This is C:\spa.bat. ARG0="spa" ARG1="ce.bat" 0 C:\>spa ce.bat This is C:\spa.bat. ARG0="spa" ARG1="ce.bat" # 1.9.2:なぜかカレントディレクトリを実行パスに含まないので、見つからない C:\>C:\ruby192\bin\ruby -e 'p system("spa ce.bat")' nil # 1.9.1:バグにより誤って"space ce.bat"が実行される C:\>C:\ruby191\bin\ruby -e 'p system("spa ce.bat")' This is C:\spa ce.bat. ARG0=""spa ce.bat"" ARG1="" true # 1.8.7:バグにより誤って"space ce.bat"が実行される C:\>C:\ruby187\bin\ruby -e 'p system("spa ce.bat")' This is C:\spa ce.bat. ARG0=""spa ce.bat"" ARG1="" true ## 実験2:カレントディレクトリを"./"で指定してみる。 ## C:\>mysystem "./spa ce.bat" '.' は、内部コマンドまたは外部コマンド、 操作可能なプログラムまたはバッチ ファイルとして認識されてい 1 C:\>./spa ce.bat '.' は、内部コマンドまたは外部コマンド、 操作可能なプログラムまたはバッチ ファイルとして認識されてい # 1.9.2:意図通り(Rubyらしく)動作 C:\>C:\ruby192\bin\ruby -e 'p system("./spa ce.bat")' This is C:\spa.bat. ARG0=".\spa.bat" ARG1="ce.bat" true # 1.9.1:"./"が".\"に解釈されない C:\>C:\ruby191\bin\ruby -e 'p system("./spa ce.bat")' '.' は、内部コマンドまたは外部コマンド、 操作可能なプログラムまたはバッチ ファイルとして認識されていません。 false # 1.8.7:"./"は".\\"として動作。バグにより誤って"space ce.bat"が実行される C:\>C:\ruby187\bin\ruby -e 'p system("./spa ce.bat")' This is C:\spa ce.bat. ARG0=""./spa ce.bat"" ARG1="" true ## 実験3:カレントディレクトリを.\\で指定してみる C:\>mysystem ".\spa ce.bat" This is C:\spa.bat. ARG0=".\spa" ARG1="ce.bat" 0 C:\>.\spa ce.bat This is C:\spa.bat. ARG0=".\spa" ARG1="ce.bat" # 1.9.2:意図通り動作 C:\>C:\ruby192\bin\ruby -e 'p system(".\\spa ce.bat")' This is C:\spa.bat. ARG0=".\spa.bat" ARG1="ce.bat" true # 1.9.1:意図通り動作 C:\>C:\ruby191\bin\ruby -e 'p system(".\\spa ce.bat")' This is C:\spa.bat. ARG0=".\spa" ARG1="ce.bat" true # 1.8.7:バグにより誤って"space ce.bat"が実行される C:\>C:\ruby187\bin\ruby -e 'p system(".\\spa ce.bat")' This is C:\spa ce.bat. ARG0="".\spa ce.bat"" ARG1="" true ## 実験4:カレントディレクトリから"spa ce.bat"とspa.batを外し、PATH上に置いてみる。 無:"C:\spa ce.bat" 無:"C:\spa.bat" 有:"C:\bin\spa ce.bat" 有:"C:\bin\spa.bat" C:\>mysystem "spa ce.bat" This is C:\bin\spa.bat. ARG0="spa" ARG1="ce.bat" 0 C:\>spa ce.bat This is C:\bin\spa.bat. ARG0="spa" ARG1="ce.bat" # 1.9.2:動作するものの、arg0が絶対パスに変換されてしまっている C:\>C:\ruby192\bin\ruby -e 'p system("spa ce.bat")' This is C:\bin\spa.bat. ARG0="C:\bin\spa.bat" ARG1="ce.bat" true # 1.9.1:意図通り動作 C:\>C:\ruby191\bin\ruby -e 'p system("spa ce.bat")' This is C:\bin\spa.bat. ARG0="spa" ARG1="ce.bat" true # 1.8.7:意図通り動作 C:\>C:\ruby187\bin\ruby -e 'p system("spa ce.bat")' This is C:\bin\spa.bat. ARG0="spa" ARG1="ce.bat" true ## 実験5:"spa ce.bat"とspa.batをカレントディレクトリと、PATH上に置いてみる。 有:"C:\spa ce.bat" 有:"C:\spa.bat" 有:"C:\bin\spa ce.bat" 有:"C:\bin\spa.bat" C:\>mysystem "spa ce.bat" This is C:\spa.bat. ARG0="spa" ARG1="ce.bat" 0 C:\>spa ce.bat This is C:\spa.bat. ARG0="spa" ARG1="ce.bat" # 1.9.2:カレントディレクトリをサーチパスに含まないため、C:\binの物が動作している C:\>C:\ruby192\bin\ruby -e 'p system("spa ce.bat")' This is C:\bin\spa.bat. ARG0="C:\bin\spa.bat" ARG1="ce.bat" true # 1.9.1:意図通り動作 C:\>C:\ruby191\bin\ruby -e 'p system("spa ce.bat")' This is C:\spa.bat. ARG0="spa" ARG1="ce.bat" true # 1.8.7:意図通り動作 C:\>C:\ruby187\bin\ruby -e 'p system("spa ce.bat")' This is C:\spa.bat. ARG0="spa" ARG1="ce.bat" true ## 実験6: 有:"C:\spa ce.bat" 有:"C:\spa.bat" 有:"C:\bin\spa ce.bat" 無:"C:\bin\spa.bat" C:\>mysystem "spa ce.bat" This is C:\spa.bat. ARG0="spa" ARG1="ce.bat" 0 C:\>spa ce.bat This is C:\spa.bat. ARG0="spa" ARG1="ce.bat" # 1.9.2:カレントディレクトリをサーチパスに含まず、PATH上にもspa.batがないので見つからない C:\>C:\ruby192\bin\ruby -e 'p system("spa ce.bat")' nil # 1.9.1:バグにより誤って"space ce.bat"が実行される C:\>C:\ruby191\bin\ruby -e 'p system("spa ce.bat")' This is C:\spa ce.bat. ARG0=""spa ce.bat"" ARG1="" true # 1.8.7:バグにより誤って"space ce.bat"が実行される C:\>C:\ruby187\bin\ruby -e 'p system("spa ce.bat")' This is C:\spa ce.bat. ARG0=""spa ce.bat"" ARG1="" true ## 実験7: 無:"C:\spa ce.bat" 有:"C:\spa.bat" 有:"C:\bin\spa ce.bat" 無:"C:\bin\spa.bat" C:\>mysystem "spa ce.bat" This is C:\spa.bat. ARG0="spa" ARG1="ce.bat" 0 C:\>spa ce.bat This is C:\spa.bat. ARG0="spa" ARG1="ce.bat" # 1.9.2:カレントディレクトリをサーチパスに含まず、PATH上にもspa.batがないので見つからない C:\>C:\ruby192\bin\ruby -e 'p system("spa ce.bat")' nil # 1.9.1:存在しない"C:\spa ce.bat"が動作している??(実際は"C:\bin\spa ce.bat"が動作している。CMDの%~dpfn0がだまされてる?) C:\>C:\ruby191\bin\ruby -e 'p system("spa ce.bat")' This is C:\spa ce.bat. ARG0=""spa ce.bat"" ARG1="" true # 1.8.7:存在しない"C:\spa ce.bat"が動作している??(実際は"C:\bin\spa ce.bat"が動作している。CMDの%~dpfn0がだまされてる?) C:\>C:\ruby187\bin\ruby -e 'p system("spa ce.bat")' This is C:\spa ce.bat. ARG0=""spa ce.bat"" ARG1="" true ## 実験8: 無:"C:\spa ce.bat" 有:"C:\spa.bat" 無:"C:\bin\spa ce.bat" 無:"C:\bin\spa.bat" C:\>mysystem "spa ce.bat" This is C:\spa.bat. ARG0="spa" ARG1="ce.bat" 0 C:\>spa ce.bat This is C:\spa.bat. ARG0="spa" ARG1="ce.bat" # 1.9.2:カレントディレクトリをサーチパスに含まず、PATH上にもspa.batがないので見つからない C:\>C:\ruby192\bin\ruby -e 'p system("spa ce.bat")' nil # 1.9.1:バグにより、実行するべき"spa.bat"が見つけられない C:\>C:\ruby191\bin\ruby -e 'p system("spa ce.bat")' nil # 1.8.7:バグにより、実行するべき"spa.bat"が見つけられない C:\>C:\ruby187\bin\ruby -e 'p system("spa ce.bat")' false ## 実験9: 無:"C:\spa ce.bat" 無:"C:\spa.bat" 有:"C:\bin\spa ce.bat" 無:"C:\bin\spa.bat" C:\>mysystem "spa ce.bat" 'spa' は、内部コマンドまたは外部コマンド、 操作可能なプログラムまたはバッチ ファイルとして認識されて 1 C:\>spa ce.bat 'spa' は、内部コマンドまたは外部コマンド、 操作可能なプログラムまたはバッチ ファイルとして認識されて # 1.9.2:意図通りの動作 C:\>C:\ruby192\bin\ruby -e 'p system("spa ce.bat")' nil # 1.9.1:バグにより、がんばってパス上から"spa ce.bat"を探してる。実験7と同様にARG0がおかしい C:\>C:\ruby191\bin\ruby -e 'p system("spa ce.bat")' This is C:\spa ce.bat. ARG0=""spa ce.bat"" ARG1="" true # 1.8.7:バグにより、がんばってパス上から"spa ce.bat"を探してる。実験7と同様にARG0がおかしい C:\>C:\ruby187\bin\ruby -e 'p system("spa ce.bat")' This is C:\spa ce.bat. ARG0=""spa ce.bat"" ARG1="" true -- h.najima@gmail.com