这个答案可能会晚一点,但是我遇到了同样的问题,被接受的答案对我来说似乎并不令人满意,因此我进行了进一步的调查。
困扰我的是这样一个事实,$0
即$PROGRAM_NAME
是否真正掌握了有关用户键入内容的正确信息。如果我的Ruby脚本位于PATH文件夹中,并且用户输入了可执行文件名称(没有任何路径定义,例如./script
或/bin/script
),它将始终扩展为总路径。
我以为这是Ruby的不足,所以我在Python上尝试了同样的方法,但令我感到恼火的是,两者没有什么不同。
一位朋友建议我用骇客寻找real thing
in /proc/self/cmdline
,结果为:([ruby, /home/danyel/bin/myscript, arg1, arg2...]
由null-char分隔)。此处的反派execve(1)
将路径传递给解释器时,会将路径扩展为总路径。
示例C程序:
extern char** environ;
int main() {
char ** arr = malloc(10 * sizeof(char*));
arr[0] = "myscript";
arr[1] = "-h";
arr[2] = NULL;
execve("/home/danyel/bin/myscript", arr, environ);
}
输出:ʻUsage:/ home / danyel / bin / myscript FILE ...
为了证明这确实是execve
一件事情,而不是bash的事情,我们可以创建一个虚拟解释器,该伪解释器只打印输出给它的参数:
// interpreter.c
int main(int argc, const char ** argv) {
while(*argv)
printf("%s\n", *(argv++));
}
我们将其编译并放在路径文件夹中(或将完整路径放在shebang之后),然后在其中创建一个虚拟脚本 ~/bin/myscript/
Hi there!
现在,在我们的main.c中:
extern char** environ;
int main() {
char ** arr = malloc(10 * sizeof(char*));
arr[0] = "This will be totally ignored by execve.";
arr[1] = "-v";
arr[2] = "/var/log/apache2.log";
arr[3] = NULL;
execve("/home/danyel/bin/myscript", arr, environ);
}
编译并运行./main
:解释器/ home / danyel / bin / myscript -v /var/log/apache2.log
造成这种情况的原因很可能是,如果脚本位于您的PATH中并且未提供完整路径,则解释程序会将此视为No such file
错误,如果您这样做,则会这样做:ruby myrubyscript --options arg1
并且您不在该脚本的文件夹中。