Czy w świecie * nix istnieje sposób, aby skrypt powłoki zawierał informacje o tym, który program go wykonał?
Przykład:
/path/to/script1 /path/to/script_xyz
w tym urojonym scenariuszu script_xyz
miałby informacje o ścieżce ( /path/to/script1
)
lub
proces PID
podmiotu, który go wykonał.
Uwaga: jestem ciekawy różnych rozwiązań i podejść, nie spodziewam się, że to faktycznie będzie możliwe
shell-script
shell
process
debugging
Miloš Đakonović
źródło
źródło
Odpowiedzi:
Często występuje pomieszanie między rozwidlaniem procesów a wykonywaniem.
Gdy zrobisz to z polecenia
bash
powłoki.Proces P1 wydający ten
$
monit aktualnie uruchamiabash
kod. Tenbash
kod powoduje uruchomienie nowego procesu P2 ,/bin/sh
który następnie wykonuje się/usr/bin/env
, a następnie wykonuje/bin/ps
.Więc P2 jest z kolei wykonany kod
bash
,sh
,env
ips
.ps
(lub jakiekolwiek inne polecenie, takie jak skrypt, którego użylibyśmy tutaj zamiast tego) nie ma sposobu, aby wiedzieć, że zostało ono wykonane przezenv
polecenie.Wszystko, co może zrobić, to dowiedzieć się, jaki jest jego identyfikator procesu nadrzędnego, którym w tym przypadku byłby P1 lub
1
gdyby P1 zmarł w tym przedziale czasu, lub w systemie Linux inny proces, który został wyznaczony jako podrzędny zamiast1
.Następnie może zapytać system o to, jakie polecenie aktualnie wykonuje ten proces (jak
readlink /proc/<pid>/exe
w systemie Linux) lub jakie argumenty zostały przekazane do ostatniego polecenia, które wykonał (jak w przypadkups -o args= -p <pid>
).Jeśli chcesz, aby skrypt wiedział, co go wywołało, niezawodnym sposobem byłoby, aby wywołujący go powiedział. Można to zrobić na przykład za pomocą zmiennej środowiskowej. Na przykład
script1
można zapisać jako:I
script2
:$INVOKER
będzie ( ogólnie ) zawierać ścieżkę doscript1
. W niektórych przypadkach może to być ścieżka względna, a ścieżka będzie względna do bieżącego katalogu roboczego w momenciescript1
uruchomienia. Więc jeśliscript1
zmieni bieżący katalog roboczy przed wywołaniemscript2
,script2
otrzyma błędne informacje o tym, co go wywołało. Dlatego może być wskazane, aby upewnić się, że$INVOKER
zawiera ścieżkę bezwzględną (najlepiej zachowując basename), na przykład piszącscript1
jako:W powłokach POSIX
$PPID
będzie zawierał pid rodzica procesu, który wykonał powłokę w momencie inicjalizacji tej powłoki. Następnie, jak pokazano powyżej, proces nadrzędny może ulec zmianie, jeśli proces id$PPID
umrze.zsh
wzsh/system
module może zapytać o bieżący nadrzędny pid bieżącej (pod-) powłoki za pomocą$sysparams[ppid]
. W powłokach POSIX można uzyskać bieżący ppid procesu, który wykonał interpreter (zakładając, że nadal działa)ps -o ppid= -p "$$"
. Za pomocąbash
można uzyskać ppid bieżącej (pod-) powłoki za pomocąps -o ppid= -p "$BASHPID"
.źródło
Tak, program może wiedzieć, kto jest jego rodzicem.
Aby to zilustrować, stwórzmy dwa skrypty bash. Pierwszy zgłasza swój PID i rozpoczyna drugi skrypt:
Drugi skrypt zgłasza swój identyfikator procesu, PID swojego rodzica oraz wiersz poleceń użyty do uruchomienia rodzica:
Teraz uruchommy to:
Jak widać, drugi skrypt w rzeczywistości zna PID swojego rodzica. Użycie
ps
tego PID ujawnia wiersz poleceń użyty do wywołania elementu nadrzędnego.Bardziej szczegółowe omówienie PPID znajduje się w odpowiedzi Stéphane Chazelas .
źródło
s1
,s2
iPPID
wartości, ale potem, w wielu liniach poERROR: Unsupported SysV option.
i kilku liniach z dodatkowym wyjaśnieniem i - pustą wartością dlaParent command
ps
zprocps-ng
pakietu w wersji 3.3.12. Jak sugerował Jasen, prawdopodobnie używasz innej wersji, która może wymagać innej składni do wydrukowania linii poleceń rodzica. Spróbowaćps -f | grep $PPID
.