bash while / loop de leitura se comporta de maneira diferente em uma VM baseada em mips / musl / busybox

2

Em um sistema baseado em musl / busybox em execução no qemu (mips), o script

#!/usr/bin/bash

printf '%s\n' "${BASH_VERSION}"

> test.txt
echo 'test.txt:'
cat test.txt

echo "No process substitution:"
while IFS= read -r i; do
    printf 'ABC %s\n' $i | cat -vet
done < test.txt

echo 'test.txt:'
cat test.txt

echo "Process substitution:"
while IFS= read -r i; do
    printf 'ABC %s\n' $i | cat -vet
done < <(cat test.txt)

echo 'test.txt:'
cat test.txt

echo "Pipes:"
cat test.txt | while IFS= read -r i; do
    printf 'ABC %s\n' $i | cat -vet
done

echo 'test.txt:'
cat test.txt

echo "Why???"

imprime

4.3.42(1)-release
test.txt:
No process substitution:
test.txt:
Process substitution:
ABC $
test.txt:
Pipes:
ABC $
test.txt:
Why???

Em uma caixa do Arch Linux, com a mesma versão do bash, ela é impressa

4.3.42(1)-release
test.txt:
No process substitution:
test.txt:
Process substitution:
test.txt:
Pipes:
test.txt:
Why???

Observe que o sistema baseado em musl / busybox imprime uma string 'ABC' para os exemplos de substituição do processo, enquanto a caixa x86_64 não. O script se comporta de maneira idêntica nos dois sistemas se eu substituir > test.txt por echo 'some text' > test.txt .

Estou confuso sobre por que o script imprime 'ABC' em uma caixa, mas não na outra, e por que isso acontece apenas sob certas condições (exemplos de substituição de tubulação e processo, até agora). Eu adoraria saber o que estava causando a mudança de comportamento - isso é causado por bash? coreutils / busybox? a libc? alguma variável ambiental? algo mais que eu não tenho pensado? A mudança de comportamento é intencional (em caso afirmativo, um ponteiro para alguma documentação seria útil) ou um bug? Eu confiei algo errado?

A resolução de problemas seria boa, ou até mesmo um apontador educado para outro local mais adequado à questão. Eu postaria em uma lista de discussão, mas não tenho certeza do que está causando o comportamento, então não sei em qual lista de discussão devo postar. Como tal, eu pensei que um fórum mais geral seria apropriado - eu ficaria feliz em ser corrigido se eu estiver errado.

EDITAR:

A VM e a caixa Arch têm o bash-4.3.042 instalado (via pacman; na VM é um PKGBUILD personalizado) para / usr / bin / bash. A caixa Arch usa coreutils glibc e GNU e está sendo executada em um laptop x86_64, enquanto a VM é um sistema baseado em musl e busybox, em execução no qemu (qemu-system-mips). Eu tentei executar o script de teste na caixa Arch com os utilitários busybox no PATH, que não parecem mudar nada. A partir disso, estou assumindo que o bash na VM é o problema, já que acredito que o único não envolvido envolvido seja o 'gato'. Eu também tentei executar o script usando o binário bash (ele está vinculado estaticamente) na caixa do Arch via qemu-mips e obtive o mesmo resultado que executá-lo na VM ('ABC' é impresso para os exemplos de substituição de tubulação e processo) , o que parece apoiar a hipótese de que o binário bash na VM está em falta. Estou assumindo que o bash deve se comportar da mesma forma que na caixa do Arch; Vou tentar fazer alguns testes para isso depois.

Uma das sugestões nos comentários foi postar a saída de od -cb < <(cat test.txt) e od -cb <(cat test.txt) , presumivelmente para ver se havia uma diferença entre os dois. Para tentar cobrir todas as bases, experimentei várias versões diferentes:

Na caixa do Arch:

$ od -cb < <(cat test.txt)
0000000
$ od -cb <(cat test.txt)
0000000
$ od -cb < test.txt
0000000
$ cat test.txt | od -cb
0000000
$ # Just to show that od is actually working...
$ od -cb < <(echo 'yes')
0000000   y   e   s  \n
        171 145 163 012
0000004

Usando o bash da VM (via qemu-mips):

$ od -cb < <(cat test.txt)
0000000
$ od -cb <(cat test.txt)
0000000
$ od -cb < test.txt
0000000
$ cat test.txt | od -cb
0000000
$ # Just to show that od is actually working...
$ od -cb < <(echo 'yes')
0000000   y   e   s  \n
        171 145 163 012
0000004

Usando od do busybox (tanto na vm, com o binário bash (via qemu-mips), e na bash do sistema):

$ od -cb < <(cat test.txt)
$ od -cb <(cat test.txt)
$ od -cb < test.txt
$ cat test.txt | od -cb
$ # Just to show that od is actually working...
$ od -cb < <(echo 'yes')
0000000    y   e   s  \n                                                
         171 145 163 012                                                
0000004

Então, isso parece ser o esperado.

EDITAR:

O bash na VM está estaticamente vinculado ao musl 1.1.12 e construído com a readline interna. Para garantir que as versões bash fossem configuradas da forma mais similar possível, testei o bash empacotado com o Arch e um build usando o readline interno (ambos se comportaram de maneira idêntica); ambos estão dinamicamente ligados à glibc.

Para demonstrar que realmente é um golpe em ambas as máquinas:

Caixa do arco:

$ /usr/bin/bash --version
GNU bash, version 4.3.42(1)-release (x86_64-unknown-linux-gnu)
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

VM:

/usr/bin/bash --version
GNU bash, version 4.3.42(1)-release (mips-unknown-linux-musl)
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Alguns antecedentes; Eu estou tentando obter um script bash razoavelmente complexo em execução sem erros no sistema baseado musl / busybox, no entanto parte do script contém um loop while sendo alimentado por uma substituição de processo. No sistema baseado em musl / busybox, isso é inesperadamente alimentado com uma entrada vazia (no exemplo, $ i == ""). Eu poderia contornar isso, mas eu prefiro entender por que isso não funciona como eu esperava.

    
por pypi 02.01.2016 / 03:31

1 resposta

2

O comportamento observado foi um bug no bash, desencadeado pelo bash building sem suporte a controle de job. Como eu estava fazendo a compilação cruzada, a verificação de configuração para o controle de tarefas foi padronizada como 'ausente' (eu deveria ter dito para configurar o que usar, veja CLFS ). O relatório da lista de discussão tem um conjunto reduzido de casos de teste, e o correções no ramo de desenvolvimento para essa semana podem ser de interesse. A correção específica é uma alteração para subst.c .

    
por 20.01.2016 / 19:48