Obtenha o PID do processo iniciado pelo tempo

3

Digamos que eu corra time ./a.out , então eu posso obter o PID de time pela variável $! . Mas como obtenho o PID de a.out ?

Claro, eu poderia analisar a saída de ps , mas quero uma solução mais elegante.

Eu verifiquei man time e não consegui encontrar nada.

O mais próximo que obtive é time (sleep 10 & echo $!) , mas por causa do fork, o tempo gasto é basicamente 0 e não 10s como deveria ser.

    
por texasflood 13.03.2015 / 19:00

5 respostas

2

Por definição, a.out é um processo filho de time . Então time é o pai pid de a.out ! aqui está um teste em que eu substituo a.out por sleep 60 :

$ time sleep 50 & timepid=$!
$ aoutpid=$(pgrep -P $timepid)
$ ps -o ppid,pid,start,cmd w -p $$,$timepid,$aoutpid

PPID   PID  STARTED CMD
2065  2068 21:34:57 -bash
2068  3297 22:16:05 -bash
3297  3298 22:16:05 sleep 50

(note: onde time é na verdade um build de shell, então o comando acima é bash !)

    
por 13.03.2015 / 22:18
2

Se o tempo para iniciar um shell for insignificante comparado ao tempo gasto para executar o comando, você poderá executar um shell intermediário e usar o exec incorporado para garantir que a.out substitua o shell em vez de ser executado como um subprocesso.

time sh -c 'echo $$; exec ./a.out'
    
por 14.03.2015 / 16:33
1

Tente pgrep para encontrar o PID:

pgrep -l "a.out"

Leia map pgrep para ter mais ideia.

    
por 13.03.2015 / 19:12
1

O controle de tarefas permite colocá-lo em segundo plano e recuperá-lo novamente em primeiro plano:

time ( set -m; sleep 10 & echo $! ; fg >/dev/null ; )

Hmm ... o comando completo acaba como um trabalho parado, no entanto. Ímpar. Veja uma solução alternativa:

bash -c ' time ( set -m; sleep 10 & echo $! ; fg >/dev/null ; ) '

É claro que, a essa altura, também poderia ser:

bash -c ' time { set -m; sleep 10 & echo $! ; fg >/dev/null ; } '

Eu prefiro evitar esse bash -c , mas estou meio que sem ideias. : - \

ETA: Claro, se você não tem o controle de trabalho ativado no seu shell, a primeira versão funciona. Se você tem o controle de trabalho ativado no seu shell, é possível desativá-lo primeiro e depois novamente:

set +m; time ( set -m; sleep 10 & echo $! ; fg >/dev/null ; ) ; set -m

Mas, para o caso geral, em que o shell pode ou não ter o controle de trabalho ativado? Verificar por monitor em $SHELLOPTS e escolher um?

    
por 13.03.2015 / 22:04
1

É possível escrever um pequeno fragmento de shell que executa o restante de sua linha de comando como um processo filho, capturando o PID dessa criança como um efeito colateral.

Aqui está um script que fará isso para você (verificação de erros omitido por brevidade)

#!/bin/sh
#
"$@" &
CHILD=$!
echo "$CHILD" >/tmp/mychild.pid
echo "INFO: child is $CHILD" >&2
wait

Se você nomeasse whatsmychild , você o usaria em seu cenário assim:

time whatsmychild a.out

Evidências de que isso funciona? Aqui está outro scriptlet; vamos chamar isso de um whatsmypid :

#!/bin/sh
#
echo "My PID is $$" >&2
exit 0

Agora vamos executá-lo:

$ time identifymychild whatsmypid
INFO: child is 8105
My PID is 8105

real    0m0.006s
user    0m0.000s
sys     0m0.000s
$ cat /tmp/mychild.pid
8105
    
por 13.03.2015 / 23:34