Come superare un'incompatibilità tra ksh su Linux vs.quello installato su AIX/Solaris/HPUX?
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.
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:
- Trova il nome del pacchetto ksh
$ rpm -qa --queryformat "%{NAME}-%{VERSION}-%{RELEASE}(%{ARCH})\n" | grep "ksh"
ksh-20100621-19.el6_4.3(x86_64)
disinstallare ksh
$ sudo yum remove ksh-20100621-19.el6_4.3.x86_64
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)
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.