5 Stimmen

Wie kann man eine Inkompatibilität zwischen der ksh unter Linux und der unter AIX/Solaris/HPUX installierten überwinden?

Ich bin gerade dabei, ein System mit mehreren hundert ksh-Skripten von AIX, Solaris und HPUX auf Linux zu portieren. Dabei bin ich auf den folgenden Unterschied im Verhalten von ksh auf den beiden Systemen gestoßen:

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

Unter AIX, Solaris und HPUX lautet die Ausgabe "flag = true", unter Linux ist die Ausgabe "flag = false".

Meine Fragen sind:

  • Gibt es eine Umgebungsvariable, die ich setzen kann, um Linux's ksh dazu zu bringen, sich so zu verhalten wie die anderen Os' verhält? Wenn das nicht möglich ist:
  • Gibt es eine Option in Linux's ksh, um das gewünschte Verhalten zu erreichen? Wenn das nicht möglich ist:
  • Gibt es eine ksh-Implementierung für Linux mit dem gewünschten Verhalten?

Sonstige Anmerkungen:

  • Unter AIX, Solaris und HPUX ist ksh eine Variante von ksh88.
  • Unter Linux ist ksh die Public Domain ksh (pdksh)
  • Unter AIX, Solaris und HPUX sind dtksh und ksh93 (wo ich sie installiert habe) mit ksh konsistent
  • Die Windows NT-Systeme, zu denen ich Zugang habe: Cygwin und MKS NT, sind mit Linux kompatibel.
  • Unter AIX, Solaris und Linux ist die Bash konsistent und gibt das (aus meiner Sicht) falsche Ergebnis "flag = false" aus.

Die folgende Tabelle fasst die Systeme zusammen, die das Problem verursachen:

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

Update

Nach einigen Ratschlägen von Mitarbeitern meines Unternehmens haben wir beschlossen, die folgende Änderung am Code vorzunehmen. Damit erhalten wir das gleiche Ergebnis, egal ob wir die "echten" ksh's (ksh88, ksh93) oder einen der ksh-Klone (pdksh, MSK ksh) verwenden. Dies funktioniert auch korrekt mit der Bash.

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

Vielen Dank an jj33 für die bereits akzeptierte Antwort.

7voto

jj33 Punkte 7234

Anstatt pdksh unter Linux zu benutzen, sollten Sie die "echte" ksh von kornshell.org verwenden. pdksh ist eine blinde Neuimplementierung von ksh. kornshell.org ist die ursprüngliche korn-Shell, die etwa 25 Jahre alt ist (die von David Korn geschrieben wurde). AIX und Solaris verwenden Versionen der ursprünglichen ksh, so dass die Version von kornshell.org in der Regel vollständige Funktionen und Fehler aufweist. Da ich mir meine Zähne an SunOS/Solaris ausgebissen habe, ist die Installation von kornshell.org ksh normalerweise eines der ersten Dinge, die ich auf einem neuen Linux-System mache...

3voto

Andrew Stein Punkte 12272

Nach einigen Ratschlägen von Mitarbeitern meines Unternehmens haben wir beschlossen, folgende Änderung am Code vorzunehmen. Damit erhalten wir das gleiche Ergebnis, egal ob wir die "echten" kshs (ksh88, ksh93) oder einen der ksh-Klone (pdksh, MSK ksh) verwenden. Dies funktioniert auch korrekt mit der Bash.

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

Vielen Dank an jj33 für die bereits akzeptierte Antwort.

1voto

jtimberman Punkte 8228

Ich habe 'ksh' und 'pdksh' auf meinem lokalen Ubuntu Hardy System installiert.

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 hat das "richtige" Verhalten, das Sie erwarten, während pdksh dies nicht hat. Sie könnten im Software-Repository Ihrer lokalen Linux-Distribution nach einer "echten" ksh suchen, anstatt pdksh zu verwenden. Die "Real Unix"-Betriebssysteme werden standardmäßig die AT&T-Version der Korn-Shell installieren und nicht pdksh, da sie auf AT&T Unix (System V) basieren :-).

1voto

mpez0 Punkte 2689

Der Grund für die Unterschiede liegt darin, ob der Inside-Block im ursprünglichen Shell-Kontext oder in einer Subshell ausgeführt wird. Möglicherweise können Sie dies mit den Gruppierungsbefehlen () und {} steuern. Die Verwendung einer temporären Datei, wie Sie sie in Ihrem Update verwenden, funktioniert in den meisten Fällen, führt aber zu Problemen, wenn das Skript zweimal schnell ausgeführt wird, oder wenn es ausgeführt wird, ohne die Datei zu löschen usw.

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

Das könnte bei dem Problem helfen, das Sie mit der Linux ksh hatten. Wenn Sie Klammern anstelle von geschweiften Klammern verwenden, erhalten Sie das Linux-Verhalten auf den anderen ksh-Implementierungen.

1voto

venkat Punkte 11

Hier ist eine weitere Lösung für echo " \n " Thema

Schritte:

  1. Finden Sie das ksh-Paket nam

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

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

  2. d

  3. I

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

O

$ 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

A

\=

U

./ora_db_start_stop.sh START ALL

O

./ora_db_start_stop.sh START ONE_OR_MORE

\=

U

./ora_db_start_stop.sh STOP ALL

O

./ora_db_start_stop.sh STOP ONE_OR_MORE

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X