этот ответ может быть немного запоздалым, но у меня была такая же проблема, и принятый ответ не казался мне вполне удовлетворительным, поэтому я исследовал немного дальше.
Что меня беспокоило, так это то, что на самом деле $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:
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 ФАЙЛ ...
Чтобы доказать, что это действительно так 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
и вы не в папке с этим сценарием .