Come superare un'incompatibilità tra ksh su Linux vs.quello installato su AIX/Solaris/HPUX?

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

  •  09-06-2019
  •  | 
  •  

Domanda

Sono coinvolto nel processo di porting di un sistema contenente diverse centinaia di script ksh da AIX, Solaris e HPUX a Linux.Ho riscontrato la seguente differenza nel modo in cui ksh si comporta sui due sistemi:

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

Su AIX, Solaris e HPUX l'output è "flag = true" su Linux l'output è "flag = false".

Le mie domande sono:

  • Esiste una variabile di ambiente che posso impostare per convincere il KSH di Linux a comportarsi come l'altro sistema operativo?In caso contrario:
  • Esiste un'opzione su ksh di Linux per ottenere il comportamento richiesto?In caso contrario:
  • Esiste un'implementazione ksh disponibile per Linux con il comportamento desiderato?

Altre note:

  • Su AIX, Solaris e HPUX ksh è una variante di ksh88.
  • Su Linux, ksh è il dominio pubblico ksh (pdksh)
  • Su AIX, Solaris e HPUX dtksh e ksh93 (dove li ho installati) sono coerenti con ksh
  • I sistemi Windows NT a cui ho accesso:Cygwin e MKS NT sono coerenti con Linux.
  • Su AIX, Solaris e Linux, bash è coerente, fornendo il risultato errato (dal mio punto di vista) di "flag = false".

La tabella seguente riassume i sistemi che presentano il 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

Aggiornamento

Dopo alcuni consigli da parte di persone della mia azienda, abbiamo deciso di apportare la seguente modifica al codice.Questo ci dà lo stesso risultato sia che si utilizzino i ksh "reali" (ksh88, ksh93) o uno qualsiasi dei cloni di ksh (pdksh, MSK ksh).Funziona correttamente anche con bash.

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

Grazie a jj33 per la risposta precedentemente accettata.

È stato utile?

Soluzione 2

Dopo alcuni consigli da parte di persone della mia azienda abbiamo deciso di apportare la seguente modifica al codice.Questo ci dà lo stesso risultato sia che si utilizzino i ksh "reali" (ksh88, ksh93) o uno qualsiasi dei cloni di ksh (pdksh, MSK ksh).Funziona correttamente anche con bash.

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

Grazie a jj33 per la precedente risposta accettata.

Altri suggerimenti

Invece di usare pdksh su Linux, usa il "vero" ksh da kornshell.org.pdksh è una reimplementazione cieca di ksh.kornshell.org è la conchiglia korn originale risalente a circa 25 anni fa (quella scritta da David Korn).AIX e Solaris utilizzano versioni del ksh originale, quindi la versione di kornshell.org è solitamente completa di funzionalità e bug.Avendomi fatto le ossa con SunOS/Solaris, installare kornshell.org ksh è solitamente una delle prime cose che faccio su una nuova macchina Linux...

Ho installato "ksh" e "pdksh" sul mio sistema Ubuntu Hardy locale.

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 ha il comportamento "corretto" che ti aspetti mentre pdksh no.Potresti controllare il repository software della tua distribuzione Linux locale per un ksh "reale", invece di usare pdksh.I sistemi operativi "Real Unix" installeranno la versione AT&T della shell Korn, anziché pdksh, per impostazione predefinita, essendo basati su AT&T Unix (System V) :-).

La ragione delle differenze sta nel fatto se il blocco interno viene eseguito nel contesto della shell originale o in una sottoshell.Potresti essere in grado di controllarlo con i comandi di raggruppamento () e {}.L'utilizzo di un file temporaneo, come nel tuo aggiornamento, funzionerà per la maggior parte del tempo ma si verificheranno problemi se lo script viene eseguito due volte rapidamente o se viene eseguito senza cancellare il file, ecc.

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

Ciò potrebbe aiutare a risolvere il problema che stavi riscontrando su Linux ksh.Se usi le parentesi invece delle graffe, otterrai il comportamento Linux sulle altre implementazioni ksh.

Ecco un'altra soluzione per il problema dell'eco " ".

Passaggi:

  1. Trova il nome del pacchetto ksh

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

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

  2. scarica pdksh-5.2.14-37.el5_8.1.x86_64.rpm (controlla il sistema operativo per 32 bit o 64 bit e scegli il pacchetto corretto)

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

Output prima dell'installazione di 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

Dopo l'installazione di PDKSH

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

Utilizzo:INIZIO

./ora_db_start_stop.sh START ALL

O

./ora_db_start_stop.sh START ONE_OR_MORE

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

Utilizzo:FERMARE

./ora_db_start_stop.sh STOP ALL

O

./ora_db_start_stop.sh STOP ONE_OR_MORE

Non conosco alcuna opzione particolare per forzare ksh a essere compatibile con una particolare versione precedente.Detto questo, forse potresti installare una versione molto vecchia di ksh sulla tua macchina Linux e farla comportare in modo compatibile?

Potrebbe essere più semplice installare una versione più moderna di amy shell sui sistemi AIX/HP-UX e migrare semplicemente gli script per utilizzare sh.So che ci sono versioni di bash disponibili per tutte le piattaforme.

Il tuo script fornisce l'output corretto (vero) quando zsh viene utilizzato con il emulate -L ksh opzione.Se tutto il resto fallisce, potresti provare a utilizzare zsh su Linux.

Devi rimanere entro ksh?

Anche se usi lo stesso ksh chiamerai comunque tutti i tipi di comandi esterni (grep, ps, cat, ecc...), parte di essi avrà parametri diversi e output diverso da sistema a sistema.O dovrai tenere conto di queste differenze oppure utilizzare la versione GNU di ciascuno di essi per rendere le cose uguali.

IL Perl il linguaggio di programmazione originariamente è stato progettato proprio per superare questo problema.Include tutte le funzionalità che un programmatore di shell UNIX vorrebbe dal programma Shell, ma è lo stesso su ogni sistema UNIX.Potresti non avere l'ultima versione su tutti quei sistemi, ma se è necessario installare qualcosa, forse è meglio installare Perl.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top