vazando memória com shell script e tty [closed]

3

Estou executando um script de shell em um pi de framboesa para se comunicar com um arduino. A cada hora meu ram é usado em cerca de 50 megabytes a mais.

O próprio script apenas se conecta ao ttyACM0 (o terminal usb do arduino) e, em seguida, envia um caractere para ele. O script é executado uma vez por minuto para verificar os Temps. Os valores para o primeiro argumento podem ser: 'a', 'b' ou 'T'. No caso de 'a' ou 'b', liga / desliga um relé. No caso de 'T' o arduino retorna 3 valores de temperatura, que eu armazeno.

O script é executado corretamente (eu posso controlar o relé e receber valores, sem que a série arduinos seja reiniciada). mas estou tendo problemas por causa da minha memória limitada.

Eu não tenho nenhum outro processo em execução no dispositivo e já tentei uma nova configuração raspbian.

Alguém pode me dizer onde e se há vazamentos de memória neste script e como posso evitá-los?

EDIT: Eu encontrei o culpado: o script executa centenas de comandos 'cat' com o tempo, como me livrar deles? Eu já tentei killall cat, mas isso redefine minha conexão serial framboesa (eu quero proibir isso, porque 'reinicia' o arduino!) @ mikeserv me apontou para usar head, que automaticamente sai depois de ler um número definido de linhas, infelizmente isso também não funciona. E eu não consigo obter as temperaturas escritas no meu arquivo de saída sem um tubo

head -n3 <&3 >>/home/pi/output

não funciona, pois não está saindo também e eu não recebo nenhuma saída

Eu poderia matar todos os gatos a cada poucos minutos para liberar o mem, mas isso também redefine meu tty para o arduino (então ele reinicia e perde o estado para o relay)

Edit2: Eu não consegui fazer isso funcionar (eu tentei várias possibilidades, incluindo minicom, tela, etc ...), mas a parte de recebimento é onde eu tenho problemas. O envio de caracteres para o arduino funciona bem!

#!/bin/bash

# READ / WRITE ARDUINO

exec 3<> /dev/ttyACM0

echo "connected, sleep for 1 sec..."
sleep 1

echo "send $1..."

echo "$1" >&3

if [ "$1" = "T" ]
then
        cat <&3 | cat >> /home/pi/output &2>1
else
        echo "nothing to save"
fi

echo "closing.."

exec 3>&-

exit 0
    
por Gotschi 27.09.2014 / 20:35

2 respostas

3

Quando você:

exec 3<> /dev/ttyACM0

... você abre um descritor de arquivo de leitura / gravação para o usb serial tty em 3, que é automaticamente herdado por filhos - como subshells clonados - e é por isso que você pode lê-lo com cat <&3 posteriormente em seu backgrounded. gasoduto.

O problema é que, como você faz o segundo plano do pipeline - que o coloca e todas as subshells associadas em um grupo de processos separado - ele não é fechado para os processos do pipeline mais tarde quando você ...

exec 3<&-

... e feche esse descritor para os processos de shell atuais do script. Em vez disso ...

cat </dev/ttyACM0 | cat >> file &

... paira no fundo, não lendo nada enquanto não há nada para ler, e mantendo uma linha aberta naquela mensagem o tempo todo. Isso ocorre porque cat apenas encerra sua entrada no EOF, que, nesse caso, nunca recebe.

Você pode fazer:

cat /dev/tty

... no seu prompt para aproximar esse comportamento.

O que você deve fazer é sair explicitamente da entrada assim que ler o quanto precisar, ou então matar explicitamente cat depois disso. Você pode fazer isso como:

head -n"$GUARANTEED_NUM_AVAIL_INPUT LINES" <&3 >>file

... ou com sed [num]q ou similar. Dessa forma, você deve evitar |pipe , e provavelmente pode omitir totalmente a & de plano de fundo. Senão matar cat que você pode fazer:

cat <&3 >>file &
sleep 1 && kill "$!"

... mas provavelmente isso não é necessário, já que sair da entrada é muito mais simples.

Como um aparte, vale a pena notar que seu script já é composto inteiramente de sintaxe portátil, e por isso provavelmente vale a pena alterar a linha #!/bin/bash e invocar um shell mais leve - e provavelmente mais rápido - em vez de. Eu recomendo dash para algo assim. Dê uma olhada aqui se estiver interessado nessa linha de pensamento para um q & a sobre comparações de desempenho entre vários shells - para inclua ambos bash e dash .

    
por 27.09.2014 / 22:53
2

Não posso escrever uma correção, mas posso explicar o que está acontecendo.

  1. Você está abrindo o Porto.
  2. Seus valores de verificação / envio do sensor de temperatura.
  3. Você está fechando a porta.

Algumas possibilidades:

  • O Buffer USB do Arduino é Preenchimento até você executar novamente o script, mas o buffer ainda está cheio desde a última execução. Você inadvertidamente está causando um estouro de buffer na sua Comm Port, já que as quantidades de execuções anteriores se acumulam no buffer.
  • O mesmo problema está ocorrendo no Raspberry Pi, já que o buffer é preenchido da mesma maneira.

Você precisa encontrar uma maneira de limpar o buffer em ambos os lados para que o gate se abra, envie 3 e feche, abra, envie 3 e feche, etc. Subshell, como o Yeti sugere é um caminho. Tenho certeza de que há outras, como fechar e reabrir o buffer, mas não matar o CommPort. Como não sou especialista em Comm Drivers, só posso oferecer uma teoria.

Atualizar

If [ "$1" = "T" ]
then
        cat <&3 | cat >> /home/pi/output &2>1
        cat <&3 | cat >> /dev/null
else
        echo "nothing to save"
        cat <&3 | cat >> /dev/null
fi
    
por 27.09.2014 / 21:37