Diese Antwort könnte etwas spät kommen, aber ich hatte das gleiche Problem und die akzeptierte Antwort schien mir nicht ganz zufriedenstellend zu sein, also habe ich etwas weiter nachgeforscht.
Was mich störte, war die Tatsache, dass die richtigen Informationen darüber, was der Benutzer eingegeben hatte, nicht wirklich vorhanden waren $0
oder $PROGRAM_NAME
nicht . Wenn sich mein Ruby-Skript in einem PATH-Ordner befindet und der Benutzer den Namen der ausführbaren Datei eingibt (ohne Pfaddefinitionen wie oder ), wird es immer auf den Gesamtpfad erweitert../script
/bin/script
Ich dachte, dies sei ein Ruby-Defizit, also versuchte ich dasselbe mit Python und zu meinem Leidwesen dort war es nicht anders.
Ein Freund schlug mir einen Hack vor, um nach dem real thing
In zu suchen /proc/self/cmdline
, und das Ergebnis war: [ruby, /home/danyel/bin/myscript, arg1, arg2...]
(durch das Nullzeichen getrennt). Der Bösewicht hier ist execve(1)
der, der den Pfad zum Gesamtpfad erweitert, wenn er an einen Dolmetscher weitergegeben wird.
Beispiel C Programm:
#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);
}
Ausgabe: `Verwendung: / home / danyel / bin / myscript DATEI ...
Um zu beweisen, dass dies tatsächlich eine execve
Sache ist und nicht von Bash, können wir einen Dummy-Interpreter erstellen, der nichts anderes tut, als die an ihn übergebenen Argumente auszudrucken:
// interpreter.c
int main(int argc, const char ** argv) {
while(*argv)
printf("%s\n", *(argv++));
}
Wir kompilieren es und legen es in einem Pfadordner ab (oder legen den vollständigen Pfad nach dem Shebang ab) und erstellen ein Dummy-Skript in ~/bin/myscript/
#!/usr/bin/env interpreter
Hi there!
Nun, in unserer 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);
}
Kompilieren und Ausführen ./main
: Interpreter / home / danyel / bin / myscript -v /var/log/apache2.log
Der Grund dafür ist wahrscheinlich, dass , wenn das Skript in Ihrer PATH ist und der vollständige Pfad wurde nicht zur Verfügung gestellt, der Dolmetscher dies als erkennen würde No such file
Fehler, der es tut , wenn Sie tun: ruby myrubyscript --options arg1
und du bist nicht im Ordner mit diesem Skript .