O comportamento do comando de exportação é diferente em sh e no bash?

6

Eu tenho um script de shell sem a primeira linha que especifica qual tipo de shell usar para interpretar os comandos.

Este arquivo .sh foi usado em um sistema SCO Unix 5 até o momento da migração em um sistema mais moderno como o RHEL 7.

Parece-me que sh é o shell padrão no SCO Unix enquanto o bash é o shell padrão no Red Hat Linux, então eu acho que portar o script para linux e executá-lo, este será interpretado por padrão com o bash.

Chegando ao ponto, neste script há uma seção como esta:

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

Como você pode ver o nome da variável depois que o comando de exportação não é o da tarefa (foi um erro de digitação).

Percebi que o valor da variável MY_SETUP após esta seção é diferente se o script é interpretado por sh ou bash.

  • sh valor MY_SETUP = 2

  • bash valor MY_SETUP = 1

Parece que o bash ignora completamente a atribuição em linha com o comando de exportação e mantém o valor anterior.

Tudo isso é executado sem retornar nenhum erro, por isso fiquei me perguntando por que há um comportamento diferente. Alguém pode me explicar?

EDITAR:

Da resposta de Stéphane Chazelas parece que no bash esta instrução

var=x export var

não define o valor "x" e não o exporta, mas no meu ambiente faz os dois. Estou confuso.

    
por alessaro 07.06.2018 / 17:11

2 respostas

2

Parece que você detectou um desvio POSIX em bash que também é um desvio do histórico Bourne Shell. Você pode chamá-lo de um bug ou apenas um comportamento de desvio.

O script ao qual você se refere imprime

1
2

com todos os shells, exceto o bash no comportamento padrão.

Se você chamar bash --posix , funcionará corretamente.

De um ponteiro do usuário Kusalananda, parece que o bash, por padrão, faz com que todos os comandos internos restaurem seu ambiente temporário na saída e não apenas para os não-especiais. Como export é um especial embutido, o POSIX requer que um shell se comporte como um Bourne Shell do início dos anos 80 para manter o valor do ambiente.

Como o bash não implementa isso por padrão, você obtém o desvio.

    
por 07.06.2018 / 17:20
0

Sim, o comportamento é diferente. Toda a descrição não é tão simples.

Primeiro: quando é igual?

Esta linha de código:

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

Será impressa 1 2 em todos os shells (não semelhantes a csh) exceto zsh.

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

Isso parece um erro de zsh para mim. Como poderia ser razoável que a exportação de uma variável não retenha o valor exportado?

Mas isso ocorre porque a variável exportada: var , é a mesma var que é impressa.

Exportando algumas outras variantes

Se a linha for alterada para algo mais parecido com o que você está perguntando, com algum outro nome de variável, como este:

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

A diferença (s) fica clara:

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

É claro que o bash é diferente do sh antigo (Bourne), sh mais recente (traço), ksh e outros (não listados aqui).

Mas o mais importante é que o bash age de maneira diferente de bash --posix .

Requisito de Posix.

Alguns dos builtins do shell (não todos) são chamados de "built-ins especiais":

De: 2.14. Utilitários Internos Especiais

The following "special built-in" utilities shall be supported in the shell command language. … however, the special built-in utilities described here differ from regular built-in utilities in two respects:

  1. An error in a special built-in utility may cause a shell executing that utility to abort, while an error in a regular built-in utility shall not cause a shell executing that utility to abort. …

  2. As described in Simple Commands, variable assignments preceding the invocation of a special built-in utility remain in effect after the built-in completes; this shall not be the case with a regular built-in or other utility.

Portanto, em um comando simples: var=2 specialBuiltin , a variável var deve reter seu valor após a saída do specialBuiltin. Mas nem todas as implementações de shell seguem essa regra.

Portanto, isso deve imprimir 1 hello 2 (como eval é um especial incorporado):

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

Faz em sh e bash --posix , mas não em bash simples.

Lista de builtins especiais.

Na verdade, a lista POSIX de especiais especiais está aqui , sendo a lista:

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

O número na primeira coluna é o valor de var usado para cada teste.

Poderíamos testar todos os builtins especiais (exceto exit, exec e times) com este código:

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

Para imprimir esta lista:

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

Como você pode ver, onde posix solicita que var retenha 02 a maioria dos shells a retenha e imprima 02-02 , mas não no bash (nem zsh), pois eles imprimem 02-01 . Apenas em export é impressão bash 09-09 e zsh printing 09-01 .

    
por 10.06.2018 / 07:10

Tags