O que é POSIXLY_CORRECT e o que o faz mudar (Centos 8.4)?

O que é POSIXLY_CORRECT e o que o faz mudar (Centos 8.4)?

Estou testando usando o migrate2rocky.shscript do GitHub:

https://github.com/rocky-linux/rocky-tools/blob/main/migrate2rocky/migrate2rocky.sh

Testei isso ontem e funcionou bem. Hoje voltei a um instantâneo para fazer novamente. Desta vez, o script falhou na primeira verificação:

if [ -n "$POSIXLY_CORRECT" ] || [ -z "$BASH_VERSION" ]; then
    printf '%s\n' "bash >= 4.0 is required for this script." >&2
    exit 1
fi

Especificamente, ele falha no  $POSIXLY_CORRECTteste (executei o trecho de código de forma independente para verificar). Eu verifiquei a versão do bash em execução:

[user@server ~]$ rpm -qa | grep bash
bash-completion-2.7-5.el8.noarch
bash-4.4.20-1.el8_4.x86_64
[user@server ~]$ echo $BASH_VERSION
4.4.20(1)-release
[user@server ~]$ echo $POSIXLY_CORRECT

[user@server ~]$

Pelo que sei, o POSIX é um conjunto padrão para facilitar a portabilidade de aplicativos entre sistemas operacionais do tipo UNIX.

Nenhuma alteração foi feita em nossos servidores para explicar por que o script não funciona mais. Testei o script em servidores nos quais ainda não usei e o mesmo problema ocorre.

Os servidores são todos CentOS 8.4.

Não sei o que $POSIXLY_CORRECTfaz e por que está dando erro agora, quando estava tudo bem ontem.

Por favor, deixe-me saber se você tiver alguma dúvida, estou realmente perdido.


Saída do sudo bash -x migrate2rocky.shcomando:

[user@server ~]$ sudo bash -x migrate2rocky.sh
+ '[' -n '' ']'
+ '[' -z '4.4.20(1)-release' ']'
+ ((  BASH_VERSINFO < 4  ))
+ ((  EUID != 0  ))
+ logfile=/var/log/migrate2rocky.log
+ truncate -s0 /var/log/migrate2rocky.log
+ exec
++ tee -a /var/log/migrate2rocky.log
++ tee -a /var/log/migrate2rocky.log
+ errcolor=
+ blue=
+ nocolor=
+ export LANG=en_US.UTF-8
+ LANG=en_US.UTF-8
+ shopt -s nullglob
+ SUPPORTED_MAJOR=8
+ SUPPORTED_PLATFORM=platform:el8
++ arch
+ ARCH=x86_64
+ gpg_key_url=https://dl.rockylinux.org/pub/rocky/RPM-GPG-KEY-rockyofficial
+ gpg_key_sha512=88fe66cf0a68648c2371120d56eb509835266d9efdf7c8b9ac8fc101bdf1f0e0197030d3ea65f4b5be89dc9d1ef08581adb068815c88d7b1dc40aa1c32990f6a
+ declare -A repo_urls
+ repo_urls=([rockybaseos]="https://dl.rockylinux.org/pub/rocky/${SUPPORTED_MAJOR}/BaseOS/$ARCH/os/" [rockyappstream]="https://dl.rockylinux.org/pub/rocky/${SUPPORTED_MAJOR}/AppStream/$ARCH/os/")
+ unset CDPATH
+ convert_info_dir=/root/convert
+ unset convert_to_rocky reinstall_all_rpms verify_all_rpms update_efi
+ noopts=0
+ getopts hrVR option
+ ((  ! noopts  ))
+ usage
+ printf '%s\n' 'Usage: migrate2rocky.sh [OPTIONS]' '' Options: '-h Display this help' '-r Convert to rocky' '-V Verify switch' '   !! USE WITH CAUTION !!'
Usage: migrate2rocky.sh [OPTIONS]

Options:
-h Display this help
-r Convert to rocky
-V Verify switch
   !! USE WITH CAUTION !!
+ exit 1
[user@server ~]$

Curiosamente o comando funciona, como você pode ver acima (ele passa no  POSIXLY_CORRECTteste e passa a testar os valores de BASH_VERSIONand EUID), ao rodar via bashcomando " " ao invés de " sh", como fiz ontem.

Responder1

A mensagem de erro indica que você não o executou com uma versão do bashshell mais recente que a versão 4.0. Presumivelmente, o script depende de recursos bashimplementados pelo shell que são diferentes ou estendem o conjunto de recursos prescritos pelo padrão POSIX para a linguagem shell Unix.

O final da sua pergunta confirma que você a executou sh, que no seu sistema pode ser algum shell diferente de bash. Mesmo que você shesteja bashdisfarçado, seria o shell rodando no modo POSIX.

Considere executar o script com bash, ou, se o script tiver uma #!linha - no topo, apenas torne o script executável (com chmod +x scriptname) e execute-o como ./scriptname.

A POSIXLY_CORRECTvariável de ambiente é uma variável que ajuda os utilitários a selecionar o comportamento quando a ferramenta implementa um comportamento diferente do prescrito pelo padrão POSIX.

O bashshell agirá de maneira um pouco diferente no modo POSIX (ou seja, se set -o posixestiver ativado ou se o shell for iniciado como sh). As diferenças estão descritas na seção intitulada "Modo Bash POSIX" no bashmanual.

Responder2

Complementando a resposta de Kusalananda com alguns detalhes contextuais.

DeURL vinculado do Github, você pode ver que a primeira linha do script é #!/bin/bash. Esta linha indica o intérprete a ser utilizado para o script, que neste caso é o bashshell. Em outras palavras, este script deve ser executado com o bashshell.

A razão para isso fica clara nos comentários nas linhas 35 e 26:

# These checks need to be right at the top because we start with bash-isms right
# away in this script.

'Bash-ismos' são recursos específicos do bashshell. Matrizes são um bom exemplo disso. Para garantir que o bashshell seja usado, duas condições são verificadas.

A BASH_VERSIONvariável é uma variável especial definida pelo bashshell. Outros shells não definem esta variável, portanto, basta verificar se ela está definida para prosseguir.

A POSIXLY_CORRECTvariável entra em ação porque bashpode ser executada em um modo diferente chamado modo POSIX. Este modo existe para garantir compatibilidade com outros shells, até mesmo shells mais antigos. Para obter essa compatibilidade, bashdesative vários de seus recursos mais recentes. Novamente, isso quebraria o script, portanto o script não pode ser executado a partir de uma bashinstância no modo POSIX. É por isso que a verificação está invertida, ou seja, POSIXLY_CORRECTnão deve ser definida. É definido quando bashexecutado no modo POSIX.

Como você já observou na pergunta, a execução do script com /bin/bash- conforme pretendido - passa de forma limpa nas verificações: BASH_VERSIONestá definido e POSIXLY_CORRECTnão está.

informação relacionada