Existe uma maneira de o shell script saber qual programa o executou?

13

No mundo * nix, existe uma maneira de o shell script ter informações sobre qual programa o executou?

Exemplo:

/path/to/script1 /path/to/script_xyz

neste cenário imaginário, script_xyz teria informações de caminho ( /path/to/script1 )

ou

process PID

da entidade que o executou.

Observação: Estou curioso sobre diferentes soluções e abordagens, não espero que seja exatamente possível que isso seja realmente possível

    
por Miloš Đakonović 23.07.2016 / 10:39

2 respostas

23

Muitas vezes há confusão entre o processo de bifurcação e execução.

Quando você faz no prompt de um shell bash .

$ sh -c 'exec env ps'

O processo P1 emitindo esse prompt $ está atualmente executando bash code. Esse código bash bifurca um novo processo P2 que executa /bin/sh , que então executa /usr/bin/env , que então executa /bin/ps .

Portanto, o P2 executou o código de bash , sh , env e ps .

ps (ou qualquer outro comando como um script que usaríamos aqui) não tem como saber que ele foi executado pelo comando env .

Tudo o que ele pode fazer é descobrir qual é o ID do processo pai, que nesse caso seria P1 ou 1 se P1 tiver morrido no intervalo ou no Linux outro processo que foi designado como um sub subinterrupto em vez de 1 .

Ele pode então consultar o sistema sobre qual comando esse processo está atualmente em execução (como com readlink /proc/<pid>/exe no Linux) ou quais argumentos foram passados para o último comando executado (como com ps -o args= -p <pid> ).

Se você quiser que seu script saiba o que o invocou, uma maneira confiável seria fazer com que o invocador o contasse. Isso pode ser feito, por exemplo, através de uma variável de ambiente. Por exemplo, script1 pode ser escrito como:

#! /bin/sh -
INVOKER=$0 script2 &

e script2 :

#! /bin/sh -
printf '%s\n' "I was invoked by $INVOKER"
# and in this case, we'll probably find the parent process is 1
# (if not now, at least one second later) as script1 exited just after
# invoking script2:
ps -fp "$$"
sleep 1
ps -fp "$$"
exit

$INVOKER will ( geralmente ) contém um caminho para script1 . Em alguns casos, pode ser um caminho relativo e o caminho será relativo ao diretório de trabalho atual no momento em que script1 iniciou. Portanto, se script1 alterar o diretório de trabalho atual antes de chamar script2 , script2 obterá informações erradas sobre o que chamou. Por isso, pode ser preferível certificar-se de que $INVOKER contenha um caminho absoluto (preferivelmente mantendo o nome da base), como escrevendo script1 as:

#! /bin/sh -
mypath=$(
  mydir=$(dirname -- "$0") &&
  cd -P -- "$mydir" &&
  pwd -P) && mypath=$mypath/$(basename -- "$0") || mypath=$0

... some code possibly changing the current working directory
INVOKER=$mypath script2

Em shells POSIX, $PPID conterá o pid do pai do processo que executou o shell no momento da inicialização do shell. Depois disso, como visto acima, o processo pai pode mudar se o processo de id $PPID morrer.

zsh no módulo zsh/system , pode consultar o pid pai atual do (sub) shell atual com $sysparams[ppid] . Em shells POSIX, você pode obter o atual ppid do processo que executou o interpretador (assumindo que ele ainda está em execução) com ps -o ppid= -p "$$" . Com bash , você pode obter o ppid da (sub) shell atual com ps -o ppid= -p "$BASHPID" .

    
por 23.07.2016 / 12:40
8

Sim, um programa pode saber quem é seu pai.

Para ilustrar, vamos criar dois scripts bash. O primeiro reporta seu PID e inicia o segundo script:

$ cat s1.sh
#!/bin/bash
echo s1=$$
bash s2.sh

O segundo script informa seu ID de processo, o PID de seu pai e a linha de comando usada para executar o pai:

$ cat s2.sh
#!/bin/bash
echo s2=$$ PPID=$PPID
echo "Parent command: $(ps -o cmd= -q $PPID)"

Agora, vamos executá-lo:

$ bash s1.sh
s1=17955
s2=17956 PPID=17955
Parent command: bash s1.sh

Como você pode ver, o segundo script, de fato, conhece o PID de seu pai. Usando ps , esse PID revela a linha de comando usada para chamar o pai.

Para uma discussão mais aprofundada do PPID, consulte a resposta de Stéphane Chazelas.

    
por 23.07.2016 / 10:50