Como posso obter o pid de um processo iniciado dessa maneira

1
#!/bin/bash

mkfifo /var/run/out
while true
do
    cat /var/run/out | nc -l 8080 > >(
        while read line
        do
            do some stuff
        done
    )
done

Como posso obter o pid de nc e cat ? Usando $! não funciona. Eu quero escrevê-los para um arquivo pid.

    
por Cameron Ball 18.08.2014 / 09:06

3 respostas

3

Pode haver uma maneira mais elegante de fazer o que você quer, mas isso funciona:

do
    (cat /var/run/out& echo $! > cat_pid; wait) |
                            (nc -l 8080 <&0 & echo $! > nc_pid; wait) > >(
                ︙

(dividido em linhas separadas após o | para legibilidade). Isso funciona envolvendo cada comando cujo PID você quer em um subshell, rodando de forma assíncrona naquela sub-camada, capturando seu PID, e então esperando o comando terminar. (Isso, na verdade, coloca o comando de volta no primeiro plano.) Use o truque Scott <&0 para obter um processo assíncrono em um script para ler sua entrada padrão correta.

Mas por que você está usando o “gato” ? E por que você está usando > >(…) em vez de simples piping ?

Você pode simplificar isso um pouco:

while true
do
    (nc -l 8080 < /var/run/out & echo $! > nc_pid; wait) |
                while read line
                do
                    do some stuff
                done
done

deixando nc ler diretamente de /var/run/out , e usando um pipe simples em vez de substituição de processo.

    
por 18.08.2014 / 17:54
1

A maneira mais simples de pensar é pegar o pid antes de você iniciar o processo.

Por exemplo (no bash):

pidfile() { (
    echo $BASHPID > "$1"
    shift
    exec "$@"
) }

mkfifo /var/run/out
while true
do
    pidfile /tmp/cat.pid cat /var/run/out | pidfile /tmp/nc.pid nc -l 8080 > >(
        while read line
        do
            do some stuff
        done
    )
done

Isso cria uma função pidfile que grava o PID atual no arquivo especificado e, em seguida, executa o resto dos argumentos usando exec . O exec faz com que o comando seja executado com o mesmo pid do shell que acabou de gravar o arquivo.

Envolvemos toda a função pidfile() entre parênteses () , para que possamos garantir que ela seja executada em uma subcamada. A situação em que isso se torna crítico é quando você executa um comando que não está em um pipeline. Por exemplo:

pidfile /tmp/foo some command here

Quando você fizer isso, pidfile() será executado no mesmo processo que o restante do script e, assim, quando chamar exec , o comando que está sendo executado assumirá o PID e o script não estará mais em execução.

Observe também que o acima é todo escrito para bash. $BASHPID é uma variável específica do bash. $$ não muda ao usar um subshell, então o valor está incorreto para nosso uso.

    
por 19.08.2014 / 06:27
0

Você não pode obter o PID de cat ou nc nesse script , a menos que você com & . Qualquer processo em que você não seja plano de fundo precisará ser concluído antes que o script continue.

O artigo de gerenciamento de processos do Bash wiki explica como fazer essas coisas de forma adequada.

    
por 18.08.2014 / 13:59