Como superar uma incompatibilidade entre o ksh no Linux vs.instalado no AIX/Solaris/HPUX?

StackOverflow https://stackoverflow.com/questions/74372

  •  09-06-2019
  •  | 
  •  

Pergunta

Estou envolvido no processo de portabilidade de um sistema contendo centenas de scripts ksh do AIX, Solaris e HPUX para Linux.Me deparei com a seguinte diferença na forma como o ksh se comporta nos dois sistemas:

#!/bin/ksh
flag=false
echo "a\nb" | while read x
do
    flag=true
done
echo "flag = ${flag}"
exit 0

No AIX, Solaris e HPUX a saída é "flag = true" no Linux a saída é "flag = false".

Minhas perguntas são:

  • Existe uma variável de ambiente que eu posso definir para fazer com que o KSH do Linux se comporte como o outro sistema operacional?Falhando naquilo:
  • Existe uma opção no ksh do Linux para obter o comportamento necessário?Falhando naquilo:
  • Existe uma implementação ksh disponível para Linux com o comportamento desejado?

Outras notas:

  • No AIX, Solaris e HPUX ksh é uma variante do ksh88.
  • No Linux, ksh é o domínio público ksh (pdksh)
  • No AIX, Solaris e HPUX dtksh e ksh93 (onde os tenho instalados) são consistentes com ksh
  • Os sistemas Windows NT aos quais tenho acesso:Cygwin e MKS NT são consistentes com Linux.
  • No AIX, Solaris e Linux, o bash é consistente, fornecendo o resultado incorreto (da minha perspectiva) de "flag = false".

A tabela a seguir resume os sistemas do problema:

uname -s       uname -r                   which ksh          ksh version                     flag =
========       ========                   =========          ===========                     ======
Linux          2.6.9-55.0.0.0.2.ELsmp     /bin/ksh           PD KSH v5.2.14 99/07/13.2       false
AIX            3                          /bin/ksh           Version M-11/16/88f             true    // AIX 5.3
                                          /bin/ksh93         Version M-12/28/93e             true
SunOS          5.8, 5.9 and 5.10          /bin/ksh           Version M-11/16/88i             true
                                          /usr/dt/bin/dtksh  Version M-12/28/93d             true
HP-UX          B.11.11 and B.11.23        /bin/ksh           Version 11/16/88                true
                                          /usr/dt/bin/dtksh  Version M-12/28/93d             true
CYGWIN_NT-5.1  1.5.25(0.156/4/2)          /bin/ksh           PD KSH v5.2.14 99/07/13.2       false
Windows_NT     5                          .../mksnt/ksh.exe  Version 8.7.0 build 1859...     false    // MKS

Atualizar

Após alguns conselhos de pessoas da minha empresa, decidimos fazer a seguinte modificação no código.Isso nos dá o mesmo resultado, seja usando os ksh "reais" (ksh88, ksh93) ou qualquer um dos clones ksh (pdksh, MSK ksh).Isso também funciona corretamente com o bash.

#!/bin/ksh
echo "a\nb" > junk
flag=false
while read x
do
    flag=true
done < junk
echo "flag = ${flag}"
exit 0

Obrigado a jj33 pela resposta aceita anteriormente.

Foi útil?

Solução 2

Após alguns conselhos de pessoas da minha empresa, decidimos fazer a seguinte modificação no código.Isso nos dá o mesmo resultado, seja usando os ksh "reais" (ksh88, ksh93) ou qualquer um dos clones ksh (pdksh, MSK ksh).Isso também funciona corretamente com o bash.

#!/bin/ksh
echo "a\nb" > junk
flag=false
while read x
do
    flag=true
done < junk
echo "flag = ${flag}"
exit 0

Obrigado a jj33 pela resposta aceita anteriormente.

Outras dicas

Em vez de usar o pdksh no Linux, use o ksh "real" de kornshell.org.pdksh é uma reimplementação cega do ksh.kornshell.org é o shell korn original que data de cerca de 25 anos (aquele escrito por David Korn).AIX e Solaris usam versões do ksh original, portanto a versão kornshell.org geralmente está completa com recursos e bugs.Tendo começado a usar o SunOS/Solaris, instalar o kornshell.org ksh geralmente é uma das primeiras coisas que faço em uma nova máquina Linux ...

Instalei 'ksh' e 'pdksh' no meu sistema Ubuntu Hardy local.

ii  ksh            93s+20071105-1 The real, AT&T version of the Korn shell
ii  pdksh          5.2.14-21ubunt A public domain version of the Korn shell

ksh tem o comportamento "correto" que você espera, enquanto o pdksh não.Você pode verificar o repositório de software da sua distribuição Linux local para obter um ksh "real", em vez de usar o pdksh.Os sistemas operacionais "Real Unix" instalarão a versão AT&T do shell Korn, em vez de pdksh, por padrão, sendo eles baseados no AT&T Unix (System V) :-).

A razão para as diferenças é se o bloco interno é executado no contexto original do shell ou em um subshell.Você pode controlar isso com os comandos de agrupamento () e {}.Usar um arquivo temporário, como você faz na atualização, funcionará na maioria das vezes, mas terá problemas se o script for executado duas vezes rapidamente ou se for executado sem limpar o arquivo, etc.

#!/bin/ksh
flag=false
echo "a\nb" | { while read x
do    
     flag=true
done }
echo "flag = ${flag}"
exit 0

Isso pode ajudar com o problema que você estava enfrentando no Linux ksh.Se você usar parênteses em vez de colchetes, obterá o comportamento do Linux nas outras implementações do ksh.

Aqui está outra solução para o problema de eco " "

Passos:

  1. Encontre o nome do pacote ksh

$ rpm -qa --queryformat "%{NAME}-%{VERSION}-%{RELEASE}(%{ARCH})\n" | grep "ksh" ksh-20100621-19.el6_4.3(x86_64)

  1. desinstalar ksh$ sudo yum remove ksh-20100621-19.el6_4.3.x86_64

  2. baixe pdksh-5.2.14-37.el5_8.1.x86_64.rpm (verifique o sistema operacional para 32 ou 64 bits e escolha o pacote correto)

  3. Instale pdksh-5.2.14-37.el5_8.1.x86_64.rpm

$ sudo yum -y install /SCRIPT_PATH/pdksh-5.2.14-37.el5_8.1.x86_64.rpm

Saída antes da instalação do PDKSH

$ ora_db_start_stop.sh
\n==============
Usage: START
==============\n\n
./ora_db_start_stop.sh START ALL    \n
OR \n
./ora_db_start_stop.sh START ONE_OR_MORE    \n
\n==============
Usage: STOP
==============\n\n
./ora_db_start_stop.sh STOP ALL    \n
OR \n
./ora_db_start_stop.sh STOP ONE_OR_MORE    \n\n

Após a instalação do PDKSH

==============

Uso:COMEÇAR

./ora_db_start_stop.sh START ALL

OU

./ora_db_start_stop.sh START ONE_OR_MORE

==============

Uso:PARAR

./ora_db_start_stop.sh STOP ALL

OU

./ora_db_start_stop.sh STOP ONE_OR_MORE

Não conheço nenhuma opção específica para forçar o ksh a ser compatível com uma versão mais antiga específica.Dito isto, talvez você possa instalar uma versão muito antiga do ksh em sua caixa Linux e fazer com que ela se comporte de maneira compatível?

Pode ser mais fácil instalar uma versão mais moderna do shell amy nas caixas AIX/HP-UX e apenas migrar seus scripts para usar sh.Eu sei que existem versões do bash disponíveis para todas as plataformas.

Seu script fornece a saída correta (verdadeira) quando zsh é usado com o emulate -L ksh opção.Se tudo mais falhar, você pode tentar usar zsh no Linux.

Você tem que ficar dentro de ksh?

Mesmo se você usar o mesmo ksh, você ainda chamará todos os tipos de comandos externos (grep, ps, cat, etc...), parte deles terá parâmetros diferentes e saídas diferentes de sistema para sistema.Você terá que levar em conta essas diferenças ou usar a versão GNU de cada uma delas para tornar as coisas iguais.

O Perl A linguagem de programação foi originalmente projetada exatamente para superar esse problema.Ele inclui todos os recursos que um programador do UNIX Shell gostaria do programa de shell, mas é o mesmo em todos os sistemas Unix.Você pode não ter a versão mais recente em todos esses sistemas, mas se precisar instalar algo, talvez seja melhor instalar o Perl.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top