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