[ruby-dev:42270] WindowsでのKernel.systemの挙動、一貫性について
From:
NAJIMA Hiroki <h.najima@...>
Date:
2010-09-16 18:20:57 UTC
List:
ruby-dev #42270
名島(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 <stdlib.h>
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