AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / unix / Perguntas / 779636
Accepted
Vlastimil Burián
Vlastimil Burián
Asked: 2024-07-07 03:47:18 +0800 CST2024-07-07 03:47:18 +0800 CST 2024-07-07 03:47:18 +0800 CST

Como ignorar POSIX "aviso: substituição de comando: byte nulo ignorado na entrada"?

  • 772

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 bashassim:

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 stderrpara, /dev/nullpor 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 bashe o dash. Enquanto dashse comporta normalmente sem esse aviso; bashparece 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.

shell-script
  • 3 3 respostas
  • 25 Views

3 respostas

  • Voted
  1. Vlastimil Burián
    2024-07-07T03:47:18+08:002024-07-07T03:47:18+08:00

    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 trutilitá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/modelconforme a resposta de Marcus Müller ):

    rpi_model_name=$(cat /proc/device-tree/model|tr -d '\0')
    

    ou até mesmo se livrar de cat:

    rpi_model_name=$(tr -d '\0' </proc/device-tree/model)
    

    O seguinte printfpode ser trocado por echo,.. o que deixar você confortável:

    printf '%s\n' "$rpi_model_name"
    

    deve gerar algo como:

    Raspberry Pi 4 Model B Rev 1.5
    

    Esta pode não ser a única maneira, fique à vontade para postar a sua própria ou melhorar esta resposta.

    • 1
  2. Marcus Müller
    2024-07-07T04:42:37+08:002024-07-07T04:42:37+08:00

    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 :

    O conteúdo de cada arquivo são os dados binários exatos da árvore de dispositivos.

    E, como tal, as propriedades do tipo devicetreestring terminam em 0 byte e stringlistas 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,

    rpi_model_name="$(head -c -1 /proc/device-tree/base/model)"
    

    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 compatibleentradas!), 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.

    function read_devicetree_node() {
      mapfile -d '' result < "$1"
    }
    
    ## use like this
    
    read_devicetree_node /proc/device-tree/base/model
    # save the result in a variable. 
    # Strange syntax, because we want to save *all* entries from `result` in `model_names`.
    model_names=( ${result[@]} )
    # print the first element from that `result` array we just got
    printf 'First element is %s. Total elements %d.\n' "$model_names" "${#model_names[@]}"
    printf 'All elements concatenated with "foobar" in between:'
    printf '%sfoobar' ${model_names[@]}
    
    function simple_devicetree_string() {
      local tmp
      mapfile -d '' tmp < $1
      printf '%s ' ${tmp[@]}
    }
    
    printf 'Let's read this simply into a line, safely: %s\n' "$(simple_devicetree_string /proc/device-tree/base/model)"
    

    Fora isso, você não deve acessar esses caminhos /sys/firmware/devicetree/basediretamente, 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.")

    • 1
  3. Best Answer
    G-Man Says 'Reinstate Monica'
    2024-07-07T07:26:12+08:002024-07-07T07:26:12+08:00

    De acordo com minha resposta para Suprimir rastreamento de execução para comando echo? , tentar

    { rpi_model_name=$(cat /proc/device-tree/model); }            2>/dev/null
    { rpi_serial_number=$(cat /proc/device-tree/serial-number); } 2>/dev/null
    

    ou

    {
      rpi_model_name=$(cat /proc/device-tree/model)
      rpi_serial_number=$(cat /proc/device-tree/serial-number)
    } 2>/dev/null
    
    • 1

relate perguntas

  • Subtraindo a mesma coluna entre duas linhas no awk

  • Um script que imprime as linhas de um arquivo com seu comprimento [fechado]

  • exportar variáveis ​​​​env programaticamente, via stdout do comando [duplicado]

  • Dividir por delimitador e concatenar problema de string

  • MySQL Select com função IN () com array bash

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Possível firmware ausente /lib/firmware/i915/* para o módulo i915

    • 3 respostas
  • Marko Smith

    Falha ao buscar o repositório de backports jessie

    • 4 respostas
  • Marko Smith

    Como exportar uma chave privada GPG e uma chave pública para um arquivo

    • 4 respostas
  • Marko Smith

    Como podemos executar um comando armazenado em uma variável?

    • 5 respostas
  • Marko Smith

    Como configurar o systemd-resolved e o systemd-networkd para usar o servidor DNS local para resolver domínios locais e o servidor DNS remoto para domínios remotos?

    • 3 respostas
  • Marko Smith

    apt-get update error no Kali Linux após a atualização do dist [duplicado]

    • 2 respostas
  • Marko Smith

    Como ver as últimas linhas x do log de serviço systemctl

    • 5 respostas
  • Marko Smith

    Nano - pule para o final do arquivo

    • 8 respostas
  • Marko Smith

    erro grub: você precisa carregar o kernel primeiro

    • 4 respostas
  • Marko Smith

    Como baixar o pacote não instalá-lo com o comando apt-get?

    • 7 respostas
  • Martin Hope
    user12345 Falha ao buscar o repositório de backports jessie 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl Por que a maioria dos exemplos do systemd contém WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky Como exportar uma chave privada GPG e uma chave pública para um arquivo 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll status systemctl mostra: "Estado: degradado" 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim Como podemos executar um comando armazenado em uma variável? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S Por que /dev/null é um arquivo? Por que sua função não é implementada como um programa simples? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 Como ver as últimas linhas x do log de serviço systemctl 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - pule para o final do arquivo 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla Por que verdadeiro e falso são tão grandes? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis Substitua a string em um arquivo de texto enorme (70 GB), uma linha 2017-12-30 06:58:33 +0800 CST

Hot tag

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve