Что такое POSIXLY_CORRECT и что он меняет (Centos 8.4)?

Что такое POSIXLY_CORRECT и что он меняет (Centos 8.4)?

Я тестирую, используя migrate2rocky.shскрипт с GitHub:

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

Я вчера это проверил, и все работало отлично. Сегодня я вернулся к снимку, чтобы сделать это снова. На этот раз скрипт не сработал при первой проверке:

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

В частности, он не проходит тест  $POSIXLY_CORRECT(я запустил фрагмент кода независимо, чтобы проверить). Я проверил запущенную версию bash:

[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 ~]$

Насколько я могу судить, POSIX — это набор стандартов, облегчающих переносимость приложений между UNIX-подобными ОС.

На наших серверах не было сделано никаких изменений, объясняющих, почему скрипт больше не работает. Я протестировал скрипт на серверах, на которых я его еще не использовал, и возникла та же проблема.

Все серверы работают под управлением CentOS 8.4.

Я не знаю, что он $POSIXLY_CORRECTделает и почему сейчас возникает ошибка, хотя вчера все было нормально.

Пожалуйста, дайте мне знать, если у вас возникнут какие-либо вопросы, я совсем запутался.


Вывод sudo bash -x migrate2rocky.shкоманды:

[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 ~]$

Любопытно, что команда работает, как вы можете видеть выше (она проходит проверку  POSIXLY_CORRECTи переходит к проверке значений BASH_VERSIONи EUID), если ее запустить через bashкоманду " ", а не " sh", как я сделал вчера.

решение1

Сообщение об ошибке указывает на то, что вы не запустили его с релизом оболочки bashновее релиза 4.0. Предположительно, скрипт опирается на функции, которые bashреализует оболочка, отличающиеся от или расширяющие набор функций, предписываемых стандартом POSIX для языка оболочки Unix.

Конец вашего вопроса подтверждает, что вы запустили его с помощью sh, который в вашей системе может быть какой-то оболочкой, отличной от bash. Даже если ваш shзамаскирован bash, это будет оболочка, работающая в режиме POSIX.

Рассмотрите возможность запуска скрипта с помощью bash, или, если скрипт имеет #!-строку в самом начале, просто сделайте скрипт исполняемым (с помощью chmod +x scriptname), а затем запустите его как ./scriptname.

Переменная окружения POSIXLY_CORRECT— это переменная, которая помогает утилитам выбирать поведение, когда инструмент реализует поведение, отличающееся от предписанного стандартом POSIX.

Оболочка bashбудет вести себя немного по-другому в режиме POSIX (т. е. если set -o posixвключено или оболочка запущена как sh). Различия описаны в разделе под названием "Режим Bash POSIXbashруководстве.

решение2

Дополню ответ Кусалананды некоторыми контекстуальными подробностями.

ИзURL-адрес Github, вы можете видеть, что первая строка скрипта — #!/bin/bash. Эта строка указывает интерпретатор, который будет использоваться для скрипта, в данном случае это оболочка bash. Другими словами, этот скрипт предназначен для выполнения с помощью bashоболочки.

Причина этого ясна из комментариев в строках 35 и 26:

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

«Башизмы» — это функции, специфичные для bashоболочки. Массивы — хороший пример. Чтобы убедиться, что bashоболочка используется, проверяются два условия.

Переменная BASH_VERSION— это специальная переменная, устанавливаемая bashоболочкой. Другие оболочки не устанавливают эту переменную, поэтому для продолжения достаточно просто проверить, что она определена.

Переменная POSIXLY_CORRECTвступает в игру, поскольку bashможет работать в другом режиме, называемом режимом POSIX. Этот режим существует для обеспечения совместимости с другими оболочками, даже старыми. Чтобы получить эту совместимость, bashотключает ряд своих новых функций. Опять же, это сломает скрипт, поэтому скрипт не может быть выполнен из bashэкземпляра в режиме POSIX. Вот почему проверка инвертирована, то есть ее POSIXLY_CORRECTне следует устанавливать. Она устанавливается при bashзапуске в режиме POSIX.

Как вы уже отметили в вопросе, запуск скрипта с /bin/bash- как и предполагалось - чисто проходит проверки: BASH_VERSIONопределено, и POSIXLY_CORRECTне определено.

Связанный контент