A volte ho bisogno di mantenere programmi che invocano script di shell che invocano altri programmi e script. Pertanto, quando lo script della shell principale termina con il codice di uscita 126, è difficile scoprire quale degli script e dei comandi richiamati imposta quel codice di uscita.
C'è un modo per vedere quale comando è stato il motivo del codice di uscita per semplificare la verifica delle sue autorizzazioni?
Risposta accettata:
Se su Linux, puoi eseguire il comando in strace -fe process
per sapere quale processo ha eseguito un exit_group(126)
e quale comando esso (o uno qualsiasi dei suoi genitori se non ha eseguito nulla da solo) eseguito per ultimo prima di farlo:
$ 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 +++
Sopra, quello era il processo 26326 che è uscito per primo con 126, perché ha tentato di eseguire /
. Era un figlio del processo 26325 che ha eseguito l'ultima volta sh -c /
.
Se quegli script sono bash
script o se sono sh
script e sh
sembra essere bash
sul tuo sistema, potresti fare:
$ 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
Questo non ci dice esattamente quale processo è terminato con 126, ma potrebbe darti un indizio sufficiente.
Correlati:come rinominare più file usando trova?
Usiamo BASH_TRACEFD=7 7>&2
in modo che le tracce vengano emesse sull'originale stderr, anche quando stderr viene reindirizzato all'interno degli script. Altrimenti quei messaggi di traccia potrebbero influenzare il comportamento degli script se fanno cose come (....) 2>&1 | ...
. Ciò presuppone che quegli script non utilizzino o chiudano esplicitamente fd 7 (sarebbe improbabile, molto più improbabile di reindirizzare stderr).