내보내기 명령이 sh와 bash에서 다르게 작동합니까?

내보내기 명령이 sh와 bash에서 다르게 작동합니까?

첫 번째 줄에서 명령을 해석하는 데 사용되는 셸 유형을 지정하지 않는 셸 스크립트가 있습니다.

이 .sh 파일은 RHEL 7과 같은 최신 시스템으로 마이그레이션할 때까지 SCO Unix 5 시스템에서 사용되었습니다.

SCO Unix에서는 sh가 기본 쉘이고, Red Hat Linux에서는 bash가 기본 쉘인 것 같아서, 스크립트를 리눅스로 포팅해서 실행시키면 기본적으로 bash 해석을 사용하게 될 거라 생각했습니다.

집에 더 가까운 이 스크립트에는 다음과 같은 부분이 있습니다.

MY_SETUP=1
echo $MY_SETUP
MY_SETUP=2 export MYSETUP
echo $MY_SETUP

보시다시피, 내보내기 명령 뒤의 변수 이름은 할당에 있는 변수 이름이 아닙니다(오타입니다).

스크립트가 sh 또는 bash로 해석되면 이 섹션 뒤의 MY_SETUP 변수 값이 다르다는 것을 알았습니다.

  • sh MY_SETUP 값 = 2

  • 배쉬 MY_SETUP 값 = 1

bash는 내보내기 명령과 함께 인라인 할당을 완전히 무시하고 이전 값을 유지하는 것 같습니다.

이러한 실행은 모두 오류를 반환하지 않으므로 동작이 다른 이유가 무엇인지 궁금합니다. 누군가 나에게 이것을 설명해 줄 수 있습니까?

편집하다:

Stéphane Chazelas의 답변에 따르면 bash에서는 이 명령이

var=x export var

"x" 값을 설정하지 않고 내보내지도 않지만 내 환경에서는 두 가지를 모두 수행합니다. 혼란스러워요.

답변1

bash역사적인 Bourne Shell과의 편차이기도 한 POSIX 편차를 감지한 것 같습니다 . 이를 버그라고 부를 수도 있고 단순히 동작의 편차라고 부를 수도 있습니다.

인용한 스크립트가 인쇄됩니다.

1
2

기본 동작에서 bash를 제외한 모든 쉘과 함께 사용됩니다.

라고 부르면 bash --posix잘 됩니다.

사용자 Kusalananda의 포인터에 따르면 기본적으로 bash는 비특수 내장 기능뿐만 아니라 종료 시 모든 내장 기능이 임시 환경을 복원하도록 하는 것으로 보입니다. exportPOSIX는 특수하게 내장되어 있기 때문에 환경 값을 유지하기 위해 셸이 1980년대 초반의 Bourne Shell처럼 동작하도록 요구합니다.

Bash는 기본적으로 이를 구현하지 않으므로 편견이 발생합니다.

답변2

예, 행동이 다릅니다. 전체 설명은 그렇게 간단하지 않습니다.

첫째: 언제 동등합니까?

다음 코드 줄은 다음과 같습니다.

$ var=1; printf "%s" "$var"; var=2 export var; echo " $var"

1 2csh와 유사하지 않은 모든 쉘에서 인쇄 됩니다 .와는 별개로쉿.

jsh             : 1 2      # ATT version sh (heirloom).
ash             : 1 2
yash            : 1 2
dash            : 1 2
zsh/sh          : 1 2
bash            : 1 2
posixbash       : 1 2
lksh            : 1 2
mksh            : 1 2
ksh93           : 1 2
attsh           : 1 2
zsh             : 1 1

이것은 나에게 zsh 버그처럼 보입니다. 내보낸 변수가 내보낸 값을 유지하지 않는 것이 어떻게 합리적일 수 있습니까?

하지만 이는 내보낸 변수 때문입니다. var인쇄된 변수와 동일합니다.

다른 변수를 내보냅니다.

해당 줄이 다음과 같이 다른 변수 이름을 사용하여 요청한 것과 더 유사한 것으로 변경된 경우:

$ var=1; printf "%s" "$var"; var=2 export othervar; echo " $var"

차이점은 다음과 같습니다.

jsh             : 1 2
dash            : 1 2
bash            : 1 1
posixbash       : 1 2
ksh93           : 1 2
zsh             : 1 1

bash가 이전 sh(Bourne), 새로운 sh(dash), ksh 및 기타(여기에 나열되지 않음)와 다르다는 것은 분명합니다.

하지만 더 중요한 것은 bash 의 동작입니다 bash --posix.

Posix 요구 사항.

일부 쉘 내장 기능(전부는 아님)을 "특수 내장 기능"이라고 합니다.

에서:2.14.특수 내장 유틸리티

쉘 명령 언어는 다음과 같은 "특별 내장" 유틸리티를 지원해야 합니다. …그러나 여기에 설명된 특수 내장 유틸리티는 두 가지 측면에서 일반 내장 유틸리티와 다릅니다.

  1. 특수 내장 유틸리티의 버그로 인해 유틸리티를 실행하는 셸이 중단될 수 있지만, 일반 내장 유틸리티의 버그로 인해 유틸리티를 실행하는 셸이 중단되어서는 안 됩니다. …

  2. 단순 명령에 설명된 대로 특수 내장 유틸리티를 호출하기 전의 변수 할당은 내장 유틸리티가 완료된 후에도 유효한 상태로 유지됩니다. 이는 일반 내장 유틸리티나 기타 유틸리티에서는 발생하지 않습니다.

따라서 간단한 명령에서 var=2 specialBuiltin변수는 varSpecialBuiltin이 종료된 후에도 해당 값을 유지해야 합니다. 그러나 모든 쉘 구현이 이러한 규칙을 따르는 것은 아닙니다.

따라서 다음은 인쇄되어야 합니다 ( 특수 내장 함수 1 hello 2와 마찬가지로 ):eval

var=1; printf '%s ' "$var"; var=2 eval printf %s hello; echo " $var"

sh일반 bash에서는 작동 하지만 일반 bash에서는 작동 bash --posix하지 않습니다.

특수 내장 함수 목록입니다.

사실은,POSIX 특수 내장 목록은 여기, 목록은 다음과 같습니다.

02 break
03 :
04 .
05 continue
06 eval
07 exec
08 exit
09 export
10 readonly
11 return
12 set
13 shift
14 times
15 trap
16 unset

첫 번째 열의 숫자는 각 테스트에 사용된 var 값입니다.

다음 코드를 사용하여 모든 특수 내장 함수(exit, exec 및 times 제외)를 테스트할 수 있습니다.

var=01;
while : ; do var=02 break; done;    printf ' %s' "02-$var"; var=01
var=03 : ;      printf ' %s' "03-$var"; var=01
echo 'printf " %s" "04-<$var>"' >source-sh
var=04 . source-sh; printf ' %s' "04-$var"; var=01
c=0; while ((c++<1)); do
     var=05 continue
     done; printf ' %s' "05-$var"; var=01
var=06 eval 'printf " %s" "06-<$var>"'; printf ' %s' "06-$var"; var=01
#( var=07 exec bash -c  'printf " %s" "07-$var"'); var=01
#( var=08 exit;     printf ' %s' "08-$var" ); var=01 
var=09 export var;  printf ' %s' "09-$var"; var=01
var=10 readonly i;  printf ' %s' "10-$var"; var=01
varfun(){ var=11 return; }; varfun; printf ' %s' "11-$var"; var=01
var=12 set -- aa ;  printf ' %s' "12-$var"; var=01
var=13 shift;       printf ' %s' "13-$var"; var=01
var=15 trap;        printf ' %s' "14-$var"; var=01
var=16 unset j;     printf ' %s' "15-$var"; var=01
echo

이 목록을 인쇄하려면:

jsh             :  02-02 03-03 04-<04> 04-04 05-05 06-<06> 06-06 09-09 10-10 11-11 12-12 13-13 15-15 16-16
dash            :  02-02 03-03 04-<04> 04-04 05-05 06-<06> 06-06 09-09 10-10 11-11 12-12 13-13 15-15 16-16
bash            :  02-01 03-01 04-<04> 04-01 05-01 06-<06> 06-01 09-09 10-01 11-01 12-01 13-01 15-01 16-01
posixbash       :  02-02 03-03 04-<04> 04-04 05-05 06-<06> 06-06 09-09 10-10 11-11 12-12 13-13 15-15 16-16
ksh93           :  02-02 03-03 04-<04> 04-04 05-05 06-<06> 06-06 09-09 10-10 11-11 12-12 13-13 15-15 16-16
zsh             :  02-01 03-01 04-<04> 04-01 05-01 06-<06> 06-01 09-01 10-01 11-01 12-01 13-01 15-01 16-01

보시다시피, posix에서 var를 보존해야 하는 경우 02대부분의 쉘은 이를 보존하고 인쇄 02-02하지만 bash(또는 zsh)에서는 인쇄하지 않습니다 02-01. exportbash 인쇄 09-09및 zsh 인쇄 에만 해당됩니다 09-01.

관련 정보