Pipes, scripts de shell e ulimit

3

Eu tenho um comando que estou chamando do código:

execvp('generate', ...)

que é um programa executável com o qual meu código se comunica via stdin, stdout e stderr. Isso funciona bem, não é um problema único.

Eu quero mudar isso para poder definir limites de recursos em generate . Então, tentei ligar:

ulimit -t 1 && generate

Mas eu recebo um cano quebrado quando tento me comunicar com ele.

Então eu coloquei a linha acima em um script de shell generate_wrapper :

#!/bin/bash
ulimit -t 1 && generate

E eu recebo um cano quebrado quando tento me comunicar com ele.

Mas

$ echo "foo" | generate_wrapper
$ echo "foo" | generate

ambos me dão a saída correta e idêntica. Eu imaginei que poderia ser o & &; então tentei apenas o comando simples:

#!/bin/bash
generate

Mas ainda funciona a partir do CL, e eu ainda recebo um pipe quebrado quando tento me comunicar com ele a partir do código.

Eu tentei rotear explicitamente os fds e consegui:

#!/bin/bash
generate >&1 2>&2 <&0

Mas não, ainda recebo um cano quebrado quando tento me comunicar com ele a partir do código.

Então obviamente eu não faço ideia do que estou fazendo. Você pode ajudar? Como escrevo um wrapper para que eu possa ulimit um sub-processo gerado ( rlimit não está disponível para pids em meu idioma de host) e ainda me comunico com ele?

    
por Ian 29.06.2011 / 13:37

3 respostas

1

Alguma razão pela qual você não queira chamar ulimit (2) no código de geração antes de execvp ?

Da página do manual:

SYNOPSIS
#include <ulimit.h>
long ulimit (int cmd, ...);

DESCRIPTION
The ulimit() function will get and set process limits.

    
por 29.06.2011 / 16:43
1

EPIPE com sua mensagem de erro "canal interrompido" é disparada quando o sinal SIGPIPE está definido para ser ignorado e um processo de gravação tenta gravar saída adicional no final de leitura já fechado do canal onde, no seu caso , generate tem todos os descritores de arquivos referentes a sua stdin fechada.

Se houver um processo pai que tenha definido o sinal SIGPIPE a ser ignorado, o processo filho herdará esse comportamento (... e em shells não interativos isso não poderá ser desfeito).

Portanto, no seu caso, o programa que chama seu executável generate definiu o sinal SIGPIPE a ser ignorado. Então, quando o programa generate no seu generate_wrapper tiver processado a entrada por um segundo ( ulimit -t 1 ) generate sairá e fechará seu stdin. Se o seu processo de gravação com SIGPIPE ignorado tentar gravar mais dados no stdin fechado de generate , a chamada do sistema write falhará e você verá EPIPE com sua mensagem de erro "canal interrompido" (consulte man 2 write ).

Quanto a um wrapper para reduzir o consumo de recursos da CPU, use ferramentas como cstream ou mbuffer .

# test: ulimit -t
#help ulimit
{
time -p bash -c 'yes | head -100000000 | wc -c'
echo
time -p bash -c 'ulimit -t 1; yes | head -100000000 | wc -c'
}

# cstream test
#top -u
yes | cstream -b 100000 -t 100000 -o -
yes | cstream -b 100000 -t 100000 | cat -n

# generate_wrapper
#!/bin/bash
cstream -b 100000 -t 100000 | generate
    
por 26.03.2016 / 17:30
0

execvp não suporta comandos do sistema, mas apenas binários diretos. Além disso, os arquivos de script são apenas comandos do sistema mascarados dessa maneira.

Eu acho que você precisa usar system () se você deseja executar comandos em vez de binários.

A idéia de dmckee sobre chamar ulimit () antes de execvp () também é um som. Isso afetará tudo o que o processo faz daqui em diante.

    
por 07.07.2011 / 12:04

Tags