Comportamento de comparação de inteiro Peculiar Solaris

5

Este me pegou de surpresa!

Temos uma máquina Solaris (versão: SunOS 5.8) hospedando um processo / script essencial que está em execução há muitos anos sem reclamações. Recentemente tivemos motivos para dar uma olhada nos bastidores e encontramos uma condição de teste que - até onde eu sei - não deveria funcionar, mas por alguma razão:

$ sh
$ [ 90% -gt 95 ]; echo $?
1
$ [ 96% -gt 95 ]; echo $?
0

O que ?! Não parece ser um acaso:

$ [ 96% -lt 95 ]; echo $?
1
$ [ 96% -eq 96 ]; echo $?
0   

Não é só o % :

$ [ 96blah -eq 96 ]; echo $?
0
$ [ 1.2 -gt 1 ]; echo $?
1

Parece ser assim no SunOS 5.8, 5.9 e 5.10, mas caso contrário, não percebi isso antes. Infelizmente, não pareço ter outro sistema não-Solaris à mão para verificar se ele não tem /bin/sh symlinked to bash (o que não é tão liberal em sua interpretação).

Portanto, código malfeito de lado (o x% é passado por variável e provavelmente não foi percebido), por que o shell padrão (presumivelmente Bourne?) trata esses argumentos de teste como números inteiros, truncando-os? Este comportamento documentado? Não consegui ver nada em man sh , mas posso ter perdido alguma coisa.

NB: Este foi realmente um boo-boo secundário dentro de outra condição de teste estranho, mas que provavelmente merece sua própria pergunta.

    
por AlexC 30.06.2015 / 18:19

3 respostas

0

O padrão diz que operadores de teste como -gt comparam seus operandos como inteiros, mas não menciona o que deve acontecer quando as strings fornecidas não são inteiros. Portanto, o comportamento observado está totalmente correto. BTW: também é compatível com o comportamento histórico do UNIX.

/ bin / sh, claro, não está vinculado ao bash, já que o bash não é compatível com o padrão e provavelmente causaria a falha de muitos scripts.

Em 2010, com o desenvolvimento do Solaris 10, o / bin / sh foi substituído pelo ksh93 e, embora o ksh seja muito mais compatível com o Bourne Shell do que o bash, isso fez com que o Solaris não pudesse ter / e / usr em diferentes sistemas de arquivos que não era problema antes. Note que o ksh93 carrega bibliotecas dinâmicas de / usr.

    
por 02.09.2015 / 15:00
1

Como não posso formatar um comentário em linhas pretendidas, eu uso o formulário de resposta para explicar meu comentário sobre como obter um shell POSIX.

O método oficial para obter um shell POSIX é:

1)  unset PATH                       # if you run an older Bourne Shell
2a) PATH='getconf PATH'              # this is with the Bourne Shell
2b) PATH=$(command -p getconf PATH)  # this is with a Korn shell
3)  sh                               # This starts a POSIX shell

Houve várias tentativas de padronizar #!/path/to/shell , mas o POSIX não lida com os PATHs e, por esse motivo, não conseguimos encontrar uma solução.

    
por 03.09.2015 / 11:45
1

Parece que isso foi respondido nos comentários: O Solaris sh tem peculiaridades. Pelo menos no passado, não era nem mesmo um shell POSIX . (Schily aponta que o POSIX não requer /bin/sh para ser POSIX sh , o que significa que você tem que pular outro aro para escrever scripts shell totalmente portáveis.)

Esta questão pode ter algumas informações / links úteis: link

A resposta de Schily indica que o padrão não especifica o que acontece com os números com o lixo à direita, portanto, o script tem um comportamento realmente indefinido e depende do que o Solaris sh faz. Assim, não é portátil.

Coisas como essa são a principal razão pela qual aparentemente não é recomendado usar bash as /bin/sh em um sistema Solaris. Algumas distribuições GNU / Linux usam dash para /bin/sh , enquanto outras usam bash .

Eu testei seu código em 3 shells que instalei:

bash  4.3-11ubuntu2
$ [ 96blah -eq 96 ]; echo $?
bash: [: 96blah: integer expression expected
2

dash  0.5.7-4ubuntu1
$ [ 96blah -eq 96 ]; echo $?
dash: 1: [: Illegal number: 96blah
2

busybox sh  1.22.0-9ubuntu1
$ [ 96blah -eq 96 ]; echo $?
sh: 96blah: bad number
2
    
por 03.09.2015 / 03:53