A veces necesito mantener programas que invocan scripts de shell que invocan otros programas y scripts. Por lo tanto, cuando el script de shell principal termina con el código de salida 126, es difícil averiguar cuál de los scripts y comandos invocados establece ese código de salida.
¿Hay alguna manera de ver qué comando fue el motivo del código de salida para que sea más fácil verificar sus permisos?
Respuesta aceptada:
Si está en Linux, puede ejecutar el comando en strace -fe process
para saber qué proceso hizo un exit_group(126)
y qué comando ejecutó (o cualquiera de sus padres si no ejecutó nada por sí mismo) antes de hacer eso:
$ strace -fe process sh -c 'env sh -c /; exit'
execve("/bin/sh", ["sh", "-c", "env sh -c /; exit"], [/* 53 vars */]) = 0
arch_prctl(ARCH_SET_FS, 0x7f24713b1700) = 0
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f24713b19d0) = 26325
strace: Process 26325 attached
[pid 26324] wait4(-1, <unfinished ...>
[pid 26325] execve("/usr/bin/env", ["env", "sh", "-c", "/"], [/* 53 vars */]) = 0
[pid 26325] arch_prctl(ARCH_SET_FS, 0x7fbdb4e2c700) = 0
[pid 26325] execve("/bin/sh", ["sh", "-c", "/"], [/* 53 vars */]) = 0
[pid 26325] arch_prctl(ARCH_SET_FS, 0x7fef90b3b700) = 0
[pid 26325] clone(strace: Process 26326 attached
child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7fef90b3b9d0) = 26326
[pid 26325] wait4(-1, <unfinished ...>
[pid 26326] execve("/", ["/"], [/* 53 vars */]) = -1 EACCES (Permission denied)
sh: 1: /: Permission denied
[pid 26326] exit_group(126) = ?
[pid 26326] +++ exited with 126 +++
[pid 26325] <... wait4 resumed> [{WIFEXITED(s) && WEXITSTATUS(s) == 126}], 0, NULL) = 26326
[pid 26325] --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=26326, si_uid=10031, si_status=126, si_utime=0, si_stime=0} ---
[pid 26325] exit_group(126) = ?
[pid 26325] +++ exited with 126 +++
<... wait4 resumed> [{WIFEXITED(s) && WEXITSTATUS(s) == 126}], 0, NULL) = 26325
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=26325, si_uid=10031, si_status=126, si_utime=0, si_stime=0} ---
exit_group(126) = ?
+++ exited with 126 +++
Arriba, ese fue el proceso 26326 que salió primero con 126, eso fue porque intentó ejecutar /
. Fue un hijo del proceso 26325 que ejecutó por última vez sh -c /
.
Si esos scripts son bash
guiones o si son sh
guiones y sh
pasa a ser bash
en su sistema, podría hacer:
$ env SHELLOPTS=xtrace
BASH_XTRACEFD=7 7>&2
PS4='[$?][$BASHPID|${BASH_SOURCE:-$BASH_EXECUTION_STRING}|$LINENO]+ '
sh -c 'env sh -c /; exit'
[0][30625|env sh -c /; exit|0]+ env sh -c /
[0][30626|/|0]+ /
sh: /: Is a directory
[126][30625|env sh -c /; exit|0]+ exit
Eso no nos dice exactamente qué proceso salió con 126, pero podría darle suficiente pista.
Relacionado:¿Cómo cambiar el nombre de varios archivos usando buscar?
Usamos BASH_TRACEFD=7 7>&2
para que las huellas se emitan en el original stderr, incluso cuando stderr se redirige dentro de los scripts. De lo contrario, esos mensajes de rastreo podrían afectar el comportamiento de los scripts si hacen cosas como (....) 2>&1 | ...
. Eso supone que esos scripts no usan ni cierran explícitamente fd 7 (eso sería poco probable, mucho más improbable que redirigir stderr).