этот ответ может прийти с некоторым опозданием, но у меня возникла та же проблема, и принятый ответ не казался мне вполне удовлетворительным, поэтому я исследовал немного дальше.
Меня беспокоил тот факт, что $0
или $PROGRAM_NAME
действительно не содержали правильную информацию о том, что пользователь напечатал . Если мой Ruby-скрипт находился в папке PATH и пользователь вводил имя исполняемого файла (без каких-либо определений пути, таких как ./script
или /bin/script
), он всегда расширялся до общего пути.
Я думал, что это был дефицит Ruby, поэтому я попробовал то же самое с Python, и к моему огорчению там ничего не изменилось.
Друг предложил мне взломать для поиска real thing
в /proc/self/cmdline
, и результат был: [ruby, /home/danyel/bin/myscript, arg1, arg2...]
(разделенный нулевым символом). Злодей здесь - execve(1)
, который расширяет путь к общему пути, когда он передает его переводчику.
Пример программы C:
#include <stdlib.h>
#include <unistd.h>
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);
}
Вывод: `Использование: / 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/
#!/usr/bin/env interpreter
Hi there!
Теперь в нашем main.c:
#include <stdlib.h>
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
:
переводчик
/ Главная / Danyel / бен / MyScript
-v
/var/log/apache2.log
Причина этого, скорее всего, заключается в том, что если сценарий находится в вашей переменной PATH, а полный путь был предоставлен , а не , интерпретатор распознает это как ошибку No such file
, что происходит, если вы делаете : ruby myrubyscript --options arg1
и вы не в папке с этим скриптом.