Execute uma tarefa em segundo plano e saiba a hora da sua terminação

2

Eu preciso executar um script de shell unix ( my_script ) em segundo plano e monitorá-lo na interface da web.

Eu inicio o roteiro real do php assim:

$command = 'my_script';
$pid= exec("nohup {$command} > {$logFile} & echo $!");

Em seguida, $pid contém o pid do meu processo e posso descobrir se o processo ainda está em execução, verificando file_exists("/proc/{$pid}") .

No entanto, eis o problema: como descubro quando o processo foi encerrado e quanto tempo correu quando foi terminado?

Além disso, há uma boa maneira de descobrir quando o processo foi iniciado? Eu posso gravar o timestamp no PHP antes ou depois de fazer a chamada exec , mas isso será um pouco impreciso.

EDITAR:

Para esclarecer, o script PHP não pode esperar pela conclusão do script de shell. O script de shell precisa ser executado em segundo plano. Eu provavelmente posso envolver três comandos (tempo de gravação iniciado, executar my_script , tempo de gravação concluído) em um shell com sh -c passá-lo para nohup , mas eu preferiria que toda a seqüência fosse atômica, acabar com o tempo de início registrado apenas se algo der errado.

    
por Beowulfenator 20.06.2015 / 23:03

3 respostas

1

Você precisará se livrar do shell intermediário e iniciá-lo como seu filho direto, provavelmente com algo como proc_open (não sou especialista em PHP). Então você receberá um SIGCHLD quando o filho terminar. Você pode instalar um manipulador de sinal para ele ( pcntl_signal mais provável) e nele não bloquear ( WNOHANG ) esperar ( pcntl_waitpid ) no PID do seu filho e se a espera for bem sucedida, registre a hora e remova o manipulador de sinal.

file_exists("/proc/{$pid}") não é confiável se você não controlar as chamadas wait (se pid não for seu filho) porque os PIDs são reciclados.

    
por 20.06.2015 / 23:34
0

Isso parece exigir em / batch, já que você está usando um front-end da web. Os resultados podem ser enviados por e-mail para o usuário ou um que é enviado pelo usuário (usando o javascript do lado do cliente ou simplesmente a verificação baseada no usuário).

    
por 21.06.2015 / 01:03
0

A maneira mais fácil de gravar as condições de saída de um script é registrá-las.

#!/bin/sh
trap 'date +"
    My name is $0. My PID is $$.
    My start time was '"$(date)."'
    The time is now %X on %x.
    My exit code is $?. Goodbye.
"   >/tell/somebody' EXIT
: now do some stuff

Um trap EXIT deve funcionar em todos os cenários de saída, mas um iniciado por um SIGKILL .

Se você não conseguir editar o script em questão, apenas coloque o script em um shell cujas instruções você pode controlar, como sh -c , como você mencionou:

trap=': the trap' sh -c '
trap "$trap" 0;. "$0"'   \
    ./script/i/cant/edit \
    positional params    &

Uma coisa semelhante pode ser feita com sh -s , mas o valor de $0 pode não ser tão simples quanto controlado. Com alguns shells você precisa exec um novo shell de infile / replacement para alterá-lo (eu às vezes uso links simbólicos e PATH=. w / exec para alterar / descartar todos os componentes do caminho em um nome de processo) .

echo 'trap "$trap" EXIT'   |
cat - ./script/i/cant/edit | 
trap=': the trap' sh -s -- \
    positional params go here &
    
por 21.06.2015 / 04:41