Was ist POSIXLY_CORRECT und wodurch ändert es sich (Centos 8.4)?

Was ist POSIXLY_CORRECT und wodurch ändert es sich (Centos 8.4)?

Ich teste mit dem migrate2rocky.shSkript von GitHub:

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

Ich habe das gestern getestet und es hat gut funktioniert. Heute bin ich auf einen Snapshot zurückgegangen, um es noch einmal zu versuchen. Diesmal ist das Skript bei der ersten Überprüfung fehlgeschlagen:

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

Konkret schlägt der  $POSIXLY_CORRECTTest fehl (ich habe den Codeausschnitt unabhängig davon ausgeführt, um dies zu überprüfen). Ich habe die laufende Bash-Version überprüft:

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

Soweit ich weiß, ist POSIX ein Standardsatz zur Erleichterung der Anwendungsportabilität zwischen UNIX-ähnlichen Betriebssystemen.

Auf unseren Servern wurden keine Änderungen vorgenommen, die erklären, warum das Skript nicht mehr funktioniert. Ich habe das Skript auf Servern getestet, auf denen ich es noch nicht verwendet habe, und das gleiche Problem tritt auf.

Die Server sind alle CentOS 8.4.

Ich weiß nicht, was das $POSIXLY_CORRECTmacht und warum jetzt ein Fehler auftritt, obwohl gestern noch alles in Ordnung war.

Wenn Sie Fragen haben, lassen Sie es mich bitte wissen. Ich bin wirklich ratlos.


Ausgabe des sudo bash -x migrate2rocky.shBefehls:

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

Interessanterweise funktioniert der Befehl, wie Sie oben sehen können (er besteht den  POSIXLY_CORRECTTest und testet anschließend die Werte von BASH_VERSIONund EUID), wenn er über bashden Befehl " " und nicht über " sh" ausgeführt wird, wie ich es gestern getan habe.

Antwort1

Die Fehlermeldung weist darauf hin, dass Sie es nicht mit einer bashShell-Version neuer als Version 4.0 ausgeführt haben. Vermutlich verwendet das Skript Funktionen, die die bashShell implementiert und die sich von den Funktionen unterscheiden oder diese erweitern, die der POSIX-Standard für die Unix-Shell-Sprache vorschreibt.

Das Ende Ihrer Frage bestätigt, dass Sie es mit ausgeführt haben sh, was auf Ihrem System eine andere Shell als sein kann bash. Selbst wenn Ihr getarnt shist bash, wäre es die Shell, die im POSIX-Modus ausgeführt wird.

Erwägen Sie die Ausführung des Skripts mit bash, oder, wenn das Skript #!ganz oben eine -Zeile hat, machen Sie das Skript einfach ausführbar (mit chmod +x scriptname) und führen Sie es dann wie aus ./scriptname.

Die POSIXLY_CORRECTUmgebungsvariable ist eine Variable, die Dienstprogrammen bei der Auswahl des Verhaltens hilft, wenn das Tool ein Verhalten implementiert, das vom POSIX-Standard abweicht.

Die bashShell verhält sich im POSIX-Modus etwas anders (d. h. wenn set -o posixaktiviert ist oder die Shell als gestartet wird sh). Die Unterschiede werden im Abschnitt „Bash POSIX-Modus" im bashHandbuch.

Antwort2

Ergänzung der Antwort von Kusalananda mit einigen kontextbezogenen Details.

Von demverlinkte Github URLsehen Sie, dass die erste Zeile des Skripts lautet #!/bin/bash. Diese Zeile gibt den für das Skript zu verwendenden Interpreter an, in diesem Fall die bashShell. Mit anderen Worten: Dieses Skript soll mit der bashShell ausgeführt werden.

Der Grund dafür wird durch die Kommentare in den Zeilen 35 und 26 deutlich:

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

„Bash-ismen“ sind Features, die spezifisch für die bashShell sind. Arrays sind hierfür ein gutes Beispiel. Um sicherzustellen, dass die bashShell verwendet wird, werden zwei Bedingungen überprüft.

Die BASH_VERSIONVariable ist eine spezielle Variable, die von der bashShell gesetzt wird. Andere Shells setzen diese Variable nicht, daher genügt es, einfach zu prüfen, ob sie definiert ist, um fortzufahren.

Die POSIXLY_CORRECTVariable kommt ins Spiel, weil bashes in einem anderen Modus namens POSIX-Modus ausgeführt werden kann. Dieser Modus dient der Gewährleistung der Kompatibilität mit anderen Shells, auch älteren Shells. Um diese Kompatibilität zu erreichen, bashwerden einige der neueren Funktionen deaktiviert. Auch hier würde das Skript beschädigt, sodass es nicht von einer bashInstanz im POSIX-Modus ausgeführt werden kann. Aus diesem Grund wird die Prüfung umgekehrt, d. h. sie POSIXLY_CORRECTsollte nicht gesetzt werden. Sie wird gesetzt, wenn bashes im POSIX-Modus ausgeführt wird.

Wie Sie bereits in der Frage angemerkt haben, werden beim Ausführen des Skripts mit /bin/bash- wie vorgesehen - die Prüfungen sauber bestanden: BASH_VERSIONist definiert und POSIXLY_CORRECTist nicht definiert.

verwandte Informationen