Executa um script em múltiplos shells?

3

Eu tenho dois servidores, um AIX com o shell padrão ksh, o outro RHEL com o bash padrão do shell.

Eu tenho um script que é montado em ambos os quais executará comandos semelhantes, mas para o AIX ou Linux. Este script não funciona nos servidores bash, existe uma maneira de fazer este script ser executado tanto no bash quanto no ksh, ou a melhor opção seria criar dois scripts diferentes?

#!/usr/bin/ksh
export OS='uname -s'
echo "OS is "$OS"."
case $OS in
        "AIX")
                #run AIX commands;;
        "Linux")
                #run Linux commands;;
        "*")
                echo "Exiting. The OS type is not found.";;
esac
echo "Done."
exit 0

UPDATE

Os comandos que preciso executar são para contas de usuário em cada servidor. Um exemplo de desbloquear uma conta. AIX / usr / bin / chuser account_locked = falso $ USERNAME

Linux / usr / bin / passwd -u $ USERNAME

Por meio de investigações posteriores, descobri que o local dos shells no AIX está localizado em / usr / bin / sh, enquanto os do Redhat estão localizados em / bin / sh.

Posso definir o shebang com base nos resultados de "uname"?

    
por SpruceTips 05.08.2014 / 21:56

5 respostas

2

Provavelmente seria mais fácil ter duas versões separadas do script. Como é curto, pode não valer a pena adicionar código extra para lidar com as diferenças entre os dois formatos, conforme sugerido pelo jw013. Por outro lado, se você tivesse um script maior, provavelmente seria mais fácil ter um e fazer o script executar comandos diferentes dependendo de onde ele está sendo executado.

    
por 05.08.2014 / 22:28
4

A maneira mais fácil é usar o mesmo shell em ambos os sistemas. Só porque um shell é pré-instalado (não existe um “shell padrão” para scripts, o shell é o que a linha shebang disser) não significa que você não possa instalar outros. Você pode instalar o bash no AIX (a partir da caixa de ferramentas , para exemplo), ou ksh93 para Linux (com o gerenciador de pacotes de sua distribuição: instale o pacote ksh ).

Se você escolher ksh, tenha cuidado com o fato de /usr/bin/ksh no AIX ser ksh88. Não há versão do ksh88 para Linux, apenas o ksh93, que está disponível como /usr/bin/ksh93 no AIX.

É mais fácil se o mesmo shell estiver instalado no mesmo local em ambos os sistemas (um link simbólico é bom), para que você possa usar o mesmo caminho na linha shebang. Se ter o mesmo local é muito difícil, você pode usar algo como #!/usr/bin/env bash , desde que você garanta que bash esteja no PATH em ambos os sistemas. Isso pode ser útil se você precisar instalar o bash ou ksh em seu diretório pessoal, porque você não tem acesso root.

Se você realmente não pode instalar o mesmo shell em ambas as máquinas - presumivelmente porque há alguma regra de complacência que só complica a vida das pessoas, mas está muito arraigada para derrubar - você tem algumas possibilidades.

  • Use #!/bin/sh como sua linha de shebang e programe na interseção do que seus sistemas oferecem. Todos os sistemas unix modernos fornecem um shell POSIX como /bin/sh . No AIX, /bin/sh é ksh88. Na Red Hat, /bin/sh é bash (que se comporta de maneira ligeiramente diferente quando invocado como sh ). Cuidado com isso em alguns outros sistemas operacionais (por exemplo, em muitas distribuições Linux), /bin/sh é um shell menor que pode não ter muito mais que recursos POSIX.
  • Inicie seus scripts com algum código clichê que procure por um shell melhor e o execute.

    #!/bin/sh
    if [ -n "$BASH" ]; then
      … bash compatibility code …
    elif type whence >/dev/null 2>/dev/null; then
      … ksh compatibility code …
    elif type ksh93 >/dev/null 2>/dev/null; then
      exec ksh93 "$0" "$@"
    elif type ksh >/dev/null 2>/dev/null; then
      exec ksh "$0" "$@"
    elif type mksh >/dev/null 2>/dev/null; then
      exec mksh "$0" "$@"
    elif type bash >/dev/null 2>/dev/null; then
      exec bash "$0" "$@"
    else
      echo 1>&2 "Cannot find ksh or bash, aborting"
      exit 125
    fi
    

Em ambos os casos, a interseção de ksh88 e bash fornece alguns recursos úteis além do POSIX, mas você pode precisar de um pouco de código de compatibilidade. Em particular:

  • A atribuição de matriz em ksh88 usa set -A . Consulte variável de atribuição em um ambiente diferente de ksh
  • As variáveis locais são declaradas por typeset .
  • O Ksh88 não tem ${VAR/PATTERN/REPLACEMENT} , $'…' ou FIGNORE . Tem [[ … ]] .
  • Para ativar @(…) e outros padrões estendidos do ksh no bash, execute shopt -s extglob .
por 06.08.2014 / 01:41
1

Eu tinha um requisito semelhante - eu precisava usar o ksh93 no AIX 5.3 para suportar matrizes associativas. Então eu configurei o script para iniciar uma segunda instância usando o ksh93. Eu também adicionei uma salvaguarda para evitar que reabasteça repetidamente.

#!/bin/ksh

scr=$0
safe=$1
echo "Check OS to determine if ksh93 is needed..."
if ( 'typeset -A testvar > /dev/null 2>&1' ); then
  echo "Associative array functions supported."
else
  echo "Associative array functions NOT supported. Starting second instance with ksh93..."
  if [ "$safe" -eq 1 ]; then
    echo "SECOND INSTANCE ALREADY STARTED!"
    exit 1
  else
    echo "BEGIN SECOND INSTANCE USING KSH93"
    /bin/ksh93 $scr 1
    exit 0
  fi
fi
    
por 30.01.2015 / 17:09
0

Eu colocaria algum trabalho em ver se você pode realmente ter uma versão com o comando que funciona nos dois sistemas.

Eu tive este problema com o meu arquivo .bashrc que guardo no meu repositório de arquivos pontuáveis. Eu quero que ele funcione tanto no OSX quanto no Ubuntu e houve alguns comandos que eu tive que modificar para fazer isso. Neste caso, foi principalmente quais switches funcionaram para determinado comando ou como um comando de teste foi escrito. Eu abordei cada questão, encontrando uma maneira de fazer qualquer comando que eu estivesse tentando de uma forma que funcionasse em ambos os SO's

Eu tentei os 'dois arquivos diferentes' e 'duas seções diferentes dependendo das abordagens do sistema operacional' e achei que era difícil mantê-los.

    
por 06.08.2014 / 01:58
0

A resposta de Gilles é (IMHO) brilhante (como sempre), mas desde que você não escolheu ou até mesmo vota, talvez ache muito complicado. Então, aqui estão alguns pontos (simples) que podem ou não ser úteis, e podem ajudá-lo a evitar a manutenção de dois scripts separados, o que pode se transformar em loucura para um script grande que deve ser mantido por um longo período de tempo. p>

1) As máquinas AIX podem ter bash instalado, embora não seja o shell padrão para uso interativo. (As máquinas AIX com as quais eu trabalho têm bash instalado, mas não sei se veio dessa maneira dos administradores de sistemas. Acredito que veio, já que todos os nossos administradores de sistemas são ksh junkies. ) E estou disposto a apostar que as máquinas RHEL têm ksh instalado. Verifique isso, porque se você puder usar o mesmo shell em ambas as máquinas, você economizará um lote de problemas.

2) Se você não sabe onde o shell vai ser instalado, evite colocar seu caminho diretamente na linha shebang. Em vez disso, coloque o caminho para env e o nome do executável do shell, assim:

#!/usr/bin/env bash

Isso deve funcionar nas duas máquinas, mas você terá que testá-lo para ter certeza. (O local para env é supostamente mais padrão do que o local para bash ou a maioria das outras coisas.)

Quando você estiver usando o mesmo shell em ambas as máquinas, o problema poderá ser resolvido ali mesmo. Mas se não ...

3) Você pode dividir o seu código específico da plataforma em funções que você fonte no script principal. Isso significa que, embora o script possa ter lotes de locais em que as coisas funcionem de maneira diferente, dependendo de estar sendo executado no AIX ou RHEL, não é necessário verificar repetidamente a plataforma. Basta fazer isso uma vez e criar as funções apropriadas:

case $OS in
    "AIX")
            source aix_functions;;
    "Linux")
            source redhat_functions;;
    "*")
            echo "Exiting. The OS type is not found.";;
esac

Agora, você pode usar as funções de origem, em todo o seu script, sem precisar ter outra instrução case para diferenciar as plataformas:

do_something_platform_specific "$SOME_ARGUMENT" "$SOME_OTHER_ARGUMENT"
    
por 18.11.2014 / 20:26