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 .