Tenho um microcontrolador executando uma distribuição Linux baseada em Debian.
Tenho uma tela Nextion conectada a ela via UART na porta /dev/ttyMOD1. Tenho um script que usa stty e obtém dados da tela usando cat e os envia para tópicos mqtt. Quando executo o script a partir do próprio shell ou se reinicio o serviço após a inicialização do sistema e consigo conectar via SSH, ele funciona perfeitamente. No entanto, quando o sistema inicializa, a tarefa cat dentro do serviço não funciona por algum motivo, somente após a reinicialização do serviço.
Os arquivos de script e serviço têm permissões +x para o usuário. Preciso de ajuda para corrigir o erro cat que não funciona na inicialização.
Texto para roteiro e serviço:
serial.service
[Unit]
Description=Serial script on startup
Requires=wb-mqtt-serial.service
After=wb-mqtt-serial.service
[Service]
User=root
WorkingDirectory=/mnt/data/root
ExecStart=/mnt/data/root/serial.sh
Restart=on-failure
Type=simple
[Install]
WantedBy=multi-user.target
serial.sh
#!/bin/bash
mqtt-delete-retained "/devices/screen/#"
stty -F /dev/ttyMOD1 ospeed 9600 ispeed 9600 raw clocal -parenb -echo cs8
CR="$(echo -e '\r')"
exec 4<> /dev/ttyMOD1
/bin/cat <&4 | while :
do
IFS="$CR" read -r line
case "$line" in quit*)
break
;;
*)
if [[ -n "$line" ]]; then
mosquitto_pub -t /devices/screen/controls/raw/meta/type -r -m text
mosquitto_pub -t /devices/screen/controls/raw -r -m "$line"
fi
;;
esac
done
A maneira mais óbvia de resolver o seu problema é se o serviço tentar iniciar antes de
ttyMOD1
poder ser utilizado; isso causariacat
falha, mas como o seu loop continua mesmo seread
falhar, o processo no lado direito do operador pipe não sabe quecat
falhou e continua tentando ser executado, impedindo que aRestart=on-failure
diretiva na sua configuração de serviço tenha qualquer efeito.Você pode adicionar algumas dependências extras e diretivas de ordenação à sua definição de serviço systemd:
...para dizer ao systemd para iniciá-lo mais tarde, em um momento em que haja maior probabilidade de sucesso (você também pode querer saber
After=network-online.target
se os comandos mqtt não funcionarão sem rede). (IssoBindTo=
diz ao systemd que, se o dispositivo desaparecer e voltar, o serviço precisará ser reiniciado).Para garantir que seu sistema possa se recuperar se o script for executado antes que as dependências sejam atendidas, considere:
Observação:
read
falhar -- dessa forma, o systemd pode reiniciar o serviço, em vez de deixá-lo morto, mas falhando, se o dispositivo não for aberto, tiver sua conexão perdida (ou, no código original, secat
for encerrado por qualquer motivo).stty
a tentativa de abrir o TTY falhar; novamente, isso evita que o script fique preso em um estado quebrado, mas ainda em execução.cat
nada aqui, mas simread
ing diretamente do dispositivo.