什麼是 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和的值) ,就像我昨天所做的那樣。EUIDbashsh

答案1

該錯誤訊息表示您沒有使用bash比 4.0 版本更新的 shell 版本來運行它。據推測,該腳本依賴bashshell 實現的功能,這些功能不同於或擴展了 Unix shell 語言的 POSIX 標準規定的功能集。

問題的結尾確認您使用 運行了它sh,在您的系統上可能是 shell 之外的其他 shell bash。即使你shbash偽裝的,它也會是在 POSIX 模式下運行的 shell。

考慮使用 運行腳本bash,或者,如果腳本的#!最頂部有一個 - 行,只需使腳本可執行(使用chmod +x scriptname),然後像 一樣運行它./scriptname

環境POSIXLY_CORRECT變量是一個變量,當工具實現的行為與 POSIX 標準規定的行為不同時,它可以幫助實用程式選擇行為。

shellbash在 POSIX 模式下的行為略有不同(即,如果set -o posix啟用,或 shell 啟動為sh)。標題為「的部分描述了這些差異Bash POSIX 模式「在bash手冊中。

答案2

用一些上下文細節來補充 Kusalananda 的答案。

來自連結的 Github URL,你可以看到腳本的第一行是#!/bin/bash.該行指示用於腳本的解釋器,在本例中是bashshell。換句話說,該腳本旨在透過bashshell 執行。

第 35 行和第 26 行的註解清楚地說明了原因:

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

「Bash-isms」是特定於bashshell 的功能。數組就是一個很好的例子。為了確保bashshell 被使用,需要檢查兩個條件。

BASH_VERSION變數是shell設定的特殊變數bash。其他 shell 不會設定此變量,因此只需檢查它是否已定義就足以繼續。

POSIXLY_CORRECT變數發揮作用是因為bash它可以在稱為 POSIX 模式的不同模式下運行。此模式的存在是為了確保與其他 shell,甚至較舊的 shell 的兼容性。為了獲得這種相容性,bash請關閉一些較新的功能。同樣,這會破壞腳本,因此無法從bashPOSIX 模式下的執行個體執行腳本。這就是為什麼檢查是反向的,即POSIXLY_CORRECT不應設定。它bash在 POSIX 模式下運行時設定。

正如您在問題中已經指出的那樣,按/bin/bash預期運行腳本可以乾淨地通過檢查:BASH_VERSION已定義,但POSIXLY_CORRECT未定義。

相關內容