Hoje, eu estava trabalhando com meu Raspberry Pi 4 com Debian 12 Bookworm, e achei estranho, que alguns arquivos de texto do sistema, ou seja, eu precisasse destes dois:
/sys/firmware/devicetree/base/model
/sys/firmware/devicetree/base/serial-number
foram, ao ler e armazenar em uma variável bash
assim:
rpi_model_name=$(cat /sys/firmware/devicetree/base/model)
rpi_serial_number=$(cat /sys/firmware/devicetree/base/serial-number)
produzindo o seguinte aviso do qual não consegui me livrar redirecionando stderr
para, /dev/null
por exemplo:
warning: command substitution: ignored null byte in input
O redirecionamento mencionado é semelhante a este trecho de comando; observe que ainda recebemos aquele aviso irritante:
rpi_model_name=$(cat /sys/firmware/devicetree/base/model 2>/dev/null)
-bash: warning: command substitution: ignored null byte in input
Eu só tenho dois shells instalados bash
e o dash
. Enquanto dash
se comporta normalmente sem esse aviso; bash
parece ser mais falador sobre isso. Então, neste ponto, não posso ter certeza se outros shells emitiram isso ou algum aviso semelhante também.
Meu objetivo é suprimir este aviso para todos os shells. Não me importo com sua origem ou valor, só quero que desapareça.
A solução deve ser escrita em POSIX para portabilidade.
Isso funcionou para mim no Raspberry Pi 4 com Debian 12 Bookworm e deve ser uma solução portátil (aderindo ao POSIX).
Podemos traduzir todos os caracteres NULL com uma string vazia, excluindo efetivamente todas as suas ocorrências da string usando o
tr
utilitário (página de manual POSIX) (sabemos que, no meu caso, há apenas uma string e um caractere NULL no final dela em ambos os casos, portanto, não removeremos vários caracteres NULL, apenas um no final da string.)Tomemos como exemplo o primeiro arquivo mencionado (talvez seja melhor ler
/proc/device-tree/model
conforme a resposta de Marcus Müller ):ou até mesmo se livrar de
cat
:O seguinte
printf
pode ser trocado porecho
,.. o que deixar você confortável:deve gerar algo como:
Esta pode não ser a única maneira, fique à vontade para postar a sua própria ou melhorar esta resposta.
Ignorar ou excluir explicitamente um número desconhecido de zero bytes sem entender de onde eles vêm parece uma má ideia! Então, vamos ver de onde isso vem e em quais casos podemos querer removê-lo.
Em primeiro lugar, por que o erro? Uma string de shell em si é uma string terminada em zero (uma "string C" se você estiver familiarizado com essa linguagem de programação) internamente. Portanto, não pode conter o byte 0; que sempre sinaliza o fim da string. Portanto, no momento em que você tenta armazenar algo com byte zero em uma string no bash (ou qualquer outro shell POSIX), a string é "limpa" de todos os 0 bytes, caso contrário, você salvaria toda a saída nessa variável de string , mas sempre que você o ler, você obterá apenas todos os caracteres até (mas excluindo) o primeiro 0 byte. Os programadores Bash sabem que esta é uma grande fonte de bugs, então eles avisam sobre isso.
Agora, podemos remover com segurança esses bytes da entrada sem quebrá-la?
O que é isso, de acordo com a documentação do kernel :
E, como tal, as propriedades do tipo devicetree
string
terminam em 0 byte estringlist
as propriedades do tipo são várias strings terminadas em 0 apenas concatenadas. No seu caso, o campo do modelo termina corretamente em um byte zero; isso faz parte dos dados binários exatos e, portanto, também está presente na entrada sysfs.Como, no entanto, sabemos que será o último byte,
podia funcionar. E, bônus, se isso não for realmente uma única string, mas várias strings concatenadas (você veria isso, por exemplo, nas
compatible
entradas!), você ainda receberia um aviso em vez de algo quebrado sem espaços.Claro, você pode querer lidar com isso de forma mais geral: se algo for uma lista de strings, você ainda pode querer lê-lo e usá-lo (por exemplo, para impressão) elemento a elemento ou concatenado, por exemplo, com novas linhas ou espaços.
Fora isso, você não deve acessar esses caminhos
/sys/firmware/devicetree/base
diretamente, mas sim/proc/device-tree/base/
como prefixo. É garantido que isso ainda será válido na próxima atualização do kernel,/sys/firmware/devicetree/
pode ter desaparecido. ( Na verdade, esses não são arquivos armazenados em algum lugar - esta é apenas a estrutura devicetree analisada representada em sysfs. Ela é calculada pelo kernel quando você a lê, não por algum arquivo armazenado em um disco. Portanto, a existência deles é basicamente a API para o kernel aqui - e os desenvolvedores do kernel dizem "por favor acesse via /proc, a outra parte é o que usamos atualmente, mas não podemos garantir que isso não mudará. O caminho /proc, nós garantimos.")De acordo com minha resposta para Suprimir rastreamento de execução para comando echo? , tentar
ou