esta respuesta puede llegar un poco tarde, pero he tenido el mismo problema y la respuesta aceptada no me pareció muy satisfactoria, así que investigué un poco más.
Lo que me molestó fue el hecho de que $0
, o $PROGRAM_NAME
en realidad no tiene la información correcta sobre lo que el usuario hubiera tecleado . Si mi script Ruby estaba en una carpeta PATH y el usuario ingresó el nombre del ejecutable (sin ninguna definición de ruta como ./script
o /bin/script
), siempre se expandiría a la ruta total.
Pensé que esto era un déficit de Ruby, así que intenté lo mismo con Python y, para mi disgusto, no fue diferente.
Un amigo me sugirió un truco para buscar la real thing
en /proc/self/cmdline
, y el resultado fue: [ruby, /home/danyel/bin/myscript, arg1, arg2...]
(separados por la nula-char). El villano aquí es el execve(1)
que expande el camino al camino total cuando se lo pasa a un intérprete.
Programa de ejemplo 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);
}
Salida: `Uso: / home / danyel / bin / myscript ARCHIVO ...
Para demostrar que esto es realmente una execve
cosa y no de bash, podemos crear un intérprete ficticio que no hace más que imprimir los argumentos que se le pasan:
// interpreter.c
int main(int argc, const char ** argv) {
while(*argv)
printf("%s\n", *(argv++));
}
Lo compilamos y lo colocamos en una carpeta de ruta (o colocamos la ruta completa después del shebang) y creamos un script ficticio en ~/bin/myscript/
Hi there!
Ahora, en nuestro 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);
}
Compilando y ejecutando ./main
: interpreter / home / danyel / bin / myscript -v /var/log/apache2.log
Lo más probable es que la razón detrás de esto sea que si el script está en su PATH y no se proporcionó la ruta completa , el intérprete reconocería esto como un No such file
error, lo que hace si lo hace: ruby myrubyscript --options arg1
y no está en la carpeta con ese script .