En pocas palabras: me gustaría rastrear la forma en que se llaman algunos ejecutables para rastrear el comportamiento del sistema. Digamos que tengo un ejecutable:
/usr/bin/do_stuff
Y en realidad se llama por varios nombres diferentes a través del enlace simbólico:
/usr/bin/make_tea -> /usr/bin/do_stuff
/usr/bin/make_coffee -> /usr/bin/do_stuff
y así. Claramente, do_stuff
va a usar el primer argumento que recibe para determinar qué acción se lleva a cabo realmente, y el resto de los argumentos se manejarán a la luz de eso.
Me gustaría grabar alguna llamada a /usr/bin/do_stuff
(y la lista completa de argumentos). Si no existieran los enlaces simbólicos, me basta con mover do_stuff
a do_stuff_real
y escribo un guión
#!/bin/sh
echo "$0 $@" >> logfile
/usr/bin/do_stuff_real "$@"
Sin embargo, como sé que examinará el nombre por el que se llama, esto no funcionará. ¿Cómo se escribe un script para lograr lo mismo, pero aún se pasa al do_stuff
'nombre usado ejecutable' correcto?
Para el registro, para evitar respuestas en estas líneas:
- Sé que puedo hacerlo en C (usando execve), pero sería mucho más fácil si pudiera, en este caso, simplemente usar un script de shell.
- No puedo simplemente reemplazar
do_stuff
con un programa de registro.
fuente
sh
, puede usar enmybase=${0##*/}
lugar de basename.basename
invocación comobasename -- foo.bar
no me resulta familiar, y en el sistema Linux que lo probé produce el resultadofoo.bar
que rompería el script. ¿Estás seguro de que es un método común?basename -- foo.bar
vuelvefoo.bar
,basename -- --foo--/bar
vuelvebar
como se esperaba.basename "$foo"
solo funciona si puedes garantizar$foo
que no comienza con a-
. La sintaxis general para invocar un comando con argumentos arbitrarios escmd -x -y -- "$argument"
.cmd "$argument"
está mal a menos que quieras decircmd "$option_or_arg"
. Ahora, algunos comandos (incluidas algunas implementaciones históricas debasename
) no son compatibles,--
por lo que a veces puede que tenga que elegir entre portabilidad y confiabilidad.Se puede utilizar
exec -a
(como se encuentra enbash
,ksh93
,zsh
,mksh
,yash
pero no POSIX aún) que se utiliza para especificar unaargv[0]
a un comando que se está ejecutando:Tenga en cuenta que ese no
$0
es el que recibe el comando. Es la ruta del script que se pasa a (y que se pasa como argumento a ), pero es probable que sea suficiente para su propósito.argv[0]
execve()
bash
Como ejemplo, if
make_tea
fue invocado como:Como lo haría normalmente un shell al invocar el comando por su nombre (buscando el ejecutable en
$PATH
), el contenedor debería:Eso no es:
pero eso es lo suficientemente bueno como se
do_stuff_real
sabe que está destinado a hacer té.Donde eso sería un problema es si
do_stuff
se invocara como:como eso se traduciría a:
Eso no sucedería durante las operaciones normales, pero tenga en cuenta que nuestro contenedor hace algo así.
En la mayoría de los sistemas, el
argv[0]
que pasó a la secuencia de comandos se pierde una vez que el intérprete (en este caso/bin/bash
se ejecuta) ( laargv[0]
del intérprete en la mayoría de los sistemas es la ruta dada en la línea de ella-bang ) así que no hay nada que un script puede hacer al respecto.Si quisieras pasar el
argv[0]
tiempo, necesitarías compilar un ejecutable. Algo como:fuente
perl
opython
si está disponible. Las versiones anteriores dezsh
no eran compatiblesexec -a
, pero siempre puedes usarlasARGV0=the-argv-0 cmd args
.zsh
(aunque ahora ha dejado en claro que no) pero era demasiado viejo, aún podría usarloARGV0
allí.