O script ash do Busybox não sai corretamente após a execução do gato; incapaz de obter o código de saída

2

Considere o seguinte script wrapcat.sh(um invólucro para gato) para fins ilustrativos. É executado com o busybox (ash) em uma caixa Linux 2.6 incorporada.

#!/bin/sh
cat $1

Sob certas circunstâncias, esse script nem sempre sai corretamente. Por exemplo, quando eu corro

$./wrapcat.sh /proc/pid/cmdline

para alguns pid, às vezes vou cair dentro de um shell aguardando um comando. Depois de pressionar retorno ou similar, ele termina.

Meu diagnóstico é que caté interrompido por algum sinal e, portanto, o script não sai corretamente (como eu não defini nenhuma opção -e). Então, eu estou interessado no status de retorno do catcomando. Eu modifico o script da seguinte maneira:

#!/bin/sh
cat $1
echo $? # echo the exit status

No entanto, o status de saída não é ecoado quando o script falha ao sair corretamente. Eu gostaria de saber por que o $?status de saída não é ecoado (e talvez mais especificamente por que uma saída limpa nem sempre acontece particularmente quando se faz o gato /proc/pid/cmdline). O mesmo também ocorre às vezes quando se faz gatos /proc/pid/auxve /proc/pid/environ. Função relevante na fonte: http://lxr.linux.no/#linux+v2.6.31/fs/proc/base.c#L253

Eu não quero necessariamente saber como 'consertar' isso, isso provavelmente pode ser feito configurando a opção -e acima mencionada.

Nota: você provavelmente não será capaz de reproduzir isso em algo como Ubuntu ou Debian - o fenômeno pode ser específico para o busybox ash, gato ou Linux incorporado. No entanto, você pode simulá-lo interrompendo um processo filho sleepexecutado dentro de um script.

Por exemplo, execute um script s.sh:

#!/bin/sh
sleep 1000
echo $?

Então $./s.sh, ctrl-z, bg, disown %1para executar o script em seu próprio processo. Agora psvocê verá algo como:

15610 pts/35   00:00:00 s.sh
15611 pts/35   00:00:00 sleep

Se você seguir em frente e executar kill -2 15611(no processo filho ), você observará

$ 130 # the exit status, which does get printed
command line waits for next command without clean exit
user54945
fonte
O bug provavelmente é específico para uma versão específica do BusyBox, um conjunto específico de opções de compilação do BB, uma arquitetura específica ... Poste todas essas informações sobre sua configuração. Você procurou por um relatório de bug existente? Você fez um relatório de bug? Podemos ajudá-lo a encontrar uma solução alternativa, mas a melhor maneira de corrigir isso é reportar o erro.
Gilles
Você observa que, $ 130porque o processo em segundo plano produziu isso 130, seu shell não redesenha seu prompt, mas isso é esperado, pois não há como saber que algo foi gravado no terminal em segundo plano.
Stéphane Chazelas
Isso faz sentido - o exemplo é um pouco artificial e não é realmente representativo do problema (veja abaixo).
usar o seguinte comando

Respostas:

1

Você está interpretando mal a saída.

Só que esses arquivos (cmdline, environment ...) não são finalizados por um caractere de nova linha.

Assim, por exemplo, se /proc/pid/cmdlinecontiver xxx, cat /proc/pid/cmdlineserá exibida xxx, mas como não há um caractere de nova linha (que a disciplina do terminal converte na saída em CRLF), o cursor não voltará ao início da linha (CR) nem diminuirá um (LF). )

Em seguida, ao sair, seu shell emitirá seu prompt para aguardar o próximo comando, então você verá algo como:

xxx$ 

e se houver echo $?, será:

xxx0
$ 

Se o arquivo contiver mais que xxx, isso pode ficar mais confuso.

Se você quer um caractere de nova linha a ser adicionado quando se está faltando você poderia usar cutem vez de cat:

#! /bin/sh -
cut -b1- < "$1"
Stéphane Chazelas
fonte
talvez tr '\0' '\n'?
glenn jackman
Quase, mas não exatamente. Sei que não gera uma nova linha. Para esclarecer, em vez de ver xxx$ , só vejo xxx sem ele redesenhar o prompt ou imprimir o echo $?e simplesmente aguarda o próximo comando. O cursor ainda está na xxxlinha, como você indica.
user54945
Então, por que não redesenhar o prompt? O script realmente sai?
user54945
0

Eu posso ver, se $ 1 avalia como uma string vazia, que catestá esperando para ler a partir de stdin. Então você precisa pressionar Ctrl-D ou Ctrl-C para fechar o gato, para que o script possa continuar. Para esse problema especificamente, eu tentaria

cat "${1:-/dev/null}"

Para que, se $ 1 estiver vazio ou não definido, pelo menos cat obtenha um nome de arquivo válido com conteúdo finito para trabalhar.

Glenn Jackman
fonte
Sim, ignore isso e assuma que um nome de arquivo seja especificado.
user54945
1
cat "$1"não seria um problema se $1estivesse vazio. Melhor, cat < "$1"para evitar problemas, se $1houver -ou uma opção.
Stéphane Chazelas