Parfois, j'ai besoin de maintenir des programmes qui invoquent des scripts shell qui invoquent d'autres programmes et scripts. Par conséquent, lorsque le script shell principal se termine par le code de sortie 126, il est difficile de savoir lequel des scripts et commandes invoqués définit ce code de sortie.
Existe-t-il un moyen de voir quelle commande était à l'origine du code de sortie pour faciliter la vérification de ses autorisations ?
Réponse acceptée :
Si sous Linux, vous pouvez exécuter la commande sous strace -fe process
pour savoir quel processus a fait un exit_group(126)
et quelle commande il (ou l'un de ses parents s'il n'a rien exécuté lui-même) a exécuté en dernier avant de faire cela :
$ 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 +++
Ci-dessus, c'était le processus 26326 qui s'est terminé pour la première fois avec 126, c'est parce qu'il a tenté d'exécuter /
. C'était un enfant du processus 26325 qui a exécuté en dernier sh -c /
.
Si ces scripts sont bash
scripts ou s'ils sont sh
scripts et sh
se trouve être bash
sur votre système, vous pourriez faire :
$ 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
Cela ne nous dit pas exactement quel processus s'est terminé avec 126, mais cela pourrait vous donner suffisamment d'indices.
Connexe :Comment renommer plusieurs fichiers à l'aide de la recherche ?
Nous utilisons BASH_TRACEFD=7 7>&2
pour que les traces soient sorties sur l'original stderr, même lorsque stderr est redirigé dans les scripts. Sinon, ces messages de trace pourraient affecter le comportement des scripts s'ils font des choses comme (....) 2>&1 | ...
. Cela suppose que ces scripts n'utilisent pas ou ne ferment pas explicitement fd 7 eux-mêmes (ce serait peu probable, beaucoup plus improbable que de rediriger stderr).