2008-09-16 9 views
5

Estoy involucrado en el proceso de portar un sistema que contiene varios cientos de scripts ksh de AIX, Solaris y HPUX a Linux. Me he encontrado con la siguiente diferencia en la forma en que se comporta ksh en los dos sistemas:¿Cómo superar una incompatibilidad entre el ksh en Linux y el que está instalado en AIX/Solaris/HPUX?

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

En AIX, Solaris y HP-UX la salida es "flag = true" en Linux, la salida es "bandera = false".

Mis preguntas son:

  • ¿Hay una variable de entorno que pueda establecer para conseguir ksh de Linux se comporte como el otro sistema operativo de? En su defecto:
  • ¿Existe una opción en el ksh de Linux para obtener el comportamiento requerido? En su defecto:
  • ¿Existe una implementación de ksh disponible para Linux con el comportamiento deseado?

Otras notas:

  • En AIX, Solaris y HPUX ksh es una variante de ksh88.
  • En Linux, ksh es de dominio público ksh (pdksh)
  • En AIX, Solaris y HP-UX dtksh y ksh93 (donde los he instalado) son consistentes con ksh
  • Los sistemas Windows NT que tienen acceso a: Cygwin y MKS NT son consistentes con Linux.
  • En AIX, Solaris y Linux, bash es coherente, dando el resultado incorrecto (desde mi perspectiva) de "flag = false".

La siguiente tabla resume los sistemas del 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 

actualización

Después de algunos consejos de la gente en mi empresa hemos decidido hacer la siguiente modificación en el código. Esto nos da el mismo resultado si usamos el ksh "real" (ksh88, ksh93) o cualquiera de los clones ksh (pdksh, MSK ksh). Esto también funciona correctamente con bash.

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

Gracias a jj33 por la respuesta aceptada anteriormente.

+0

¿Qué distribución de Linux está usando? Eso hace una diferencia en cómo obtener el ksh "correcto" – Thomee

+0

Esta pregunta está muy relacionada: http://stackoverflow.com/questions/124167/bash-variable-scope – pixelbeat

Respuesta

3

Después de algunos consejos de personas de mi empresa, decidimos realizar la siguiente modificación al código. Esto nos da el mismo resultado si usamos el ksh "real" (ksh88, ksh93) o cualquiera de los clones ksh (pdksh, MSK ksh). Esto también funciona correctamente con bash.

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

Gracias a jj33 por la respuesta aceptada anteriormente.

+0

Puede usar un conducto con nombre en lugar del archivo temporal. – Demi

0

No conozco ninguna opción en particular para forzar que ksh sea compatible con una versión anterior en particular. Dicho esto, ¿quizás podrías instalar una versión muy antigua de ksh en tu linux box y hacer que se comporte de manera compatible?

Puede ser más fácil instalar una versión más moderna de amy shell en los cuadros AIX/HP-UX, y simplemente migrar sus scripts para usar sh. Sé que hay versiones de bash disponibles para todas las plataformas.

6

En lugar de usar pdksh en linux, use el ksh "real" de kornshell.org. pdksh es una reimplementación ciega de ksh. kornshell.org es el caparazón korn original que data de hace 25 años aproximadamente (el escrito por David Korn). AIX y Solaris usan versiones del ksh original, por lo que la versión de kornshell.org suele ser completa y completa. Habiendo cortado los dientes con SunOS/Solaris, la instalación de kornshell.org ksh suele ser una de las primeras cosas que hago en una nueva caja de Linux ...

+0

ksh de hace el truco ! –

0

Su secuencia de comandos da la salida correcta (verdadera) cuando se usa zsh con la opción emulate -L ksh. Si todo lo demás falla, puede intentar usar zsh en Linux.

1

Instalé 'ksh' y 'pdksh' en mi sistema local Ubuntu Hardy.

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 tiene el comportamiento "correcto" que está esperando mientras que pdksh no lo hace. Puede verificar el repositorio de software de su distribución local de Linux para obtener un ksh "real", en lugar de usar pdksh. El sistema operativo "Real Unix" instalará la versión T AT & de Korn shell, en lugar de pdksh, de forma predeterminada, con lo que se basan en AT & T Unix (System V) :-).

0

¿Tienes que quedarte en ksh?

Incluso si usa el mismo ksh, seguirá llamando a todo tipo de comandos externos (grep, ps, cat, etc ...) parte de ellos tendrá diferentes parámetros y diferentes resultados de sistema en sistema. O bien, tendrá que tener en cuenta esas diferencias o utilizar la versión GNU de cada una de ellas para que todo sea igual.

El lenguaje de programación Perl originalmente se diseñó exactamente para solucionar este problema. Incluye todas las características que un programador de shell unix querría del programa shell, pero es el mismo en todos los sistemas Unix. Puede que no tenga la última versión en todos esos sistemas , pero si necesita instalar algo, tal vez sea mejor instalar Perl.

+0

Los comandos externos generalmente son bastante consistentes siempre que use comandos POSIX. Si configura la variable POSIXLY_CORRECT = 1 en Linux y configura UNIX95 = 1 en HP-UX (generalmente puede establecer ambas en todas las plataformas), todos los comandos externos se comportarán igual. Y si te quedas con ksh93, como opuesto a 88, obtienes un nivel de funcionalidad que rivaliza con Perl. – dannysauer

1

El motivo de las diferencias es si el bloque interno se ejecuta en el contexto de shell original o en una subcadena. Es posible que pueda controlar esto con los comandos de agrupamiento() y {}. El uso de un archivo temporal, como lo hace en su actualización, trabajará la mayor parte del tiempo, pero va a tener problemas si el script se ejecuta dos veces rápidamente, o si se ejecuta sin borrar el archivo, etc.

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

Eso puede ayudar con el problema que estaba recibiendo en el ksh de Linux. Si usa paréntesis en lugar de llaves, obtendrá el comportamiento de Linux en las otras implementaciones de ksh.

+0

Gracias por la sugerencia. Lamentablemente, esto hace lo contrario de lo que quiero :-) Estoy tratando de obtener todas las secuencias de comandos transportadas desde otros Unixes a Linux .... –

1

Aquí está la otra solución para echo "\ n" cuestión

pasos:

  1. encontrar el nombre del paquete ksh

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

  1. desinstalación ksh $ sudo yum remove ksh-20100621-19.el6_4.3.x86_64

  2. abajo carga pdksh-5.2.14-37.el5_8.1.x86_64.rpm (Por favor marque sistema operativo de 32 bits o de 64 bits y elegir paquete correcto)

  3. Instalar 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

de salida antes de instalar 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 

Después pdksh instalación

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

Uso: START

./ora_db_start_stop.sh START ALL

O

./ora_db_start_stop.sh START ONE_OR_MORE

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

Uso: STOP

./ora_db_start_stop.sh STOP ALL

O

./ora_db_start_stop.sh STOP ONE_OR_MORE

Cuestiones relacionadas