posix sh kompatibilitás

Fórumok

Hello Hupperek,

Racionalizálás okán a jövőben szeretnék olyan shell scripteket fejleszteni amik minden un*x-on működnek, ha jól tudom áldoznom kell a kompatibilitás oltárán, azaz POSIX kompatibilisnek (posix-sh) maradni. Mit használhatok amiben ha megírok valamit, és majd egyszer pl. egy Solarison, vagy Cygwin-en fogja futtatni valaki, tuti jól működjön majd? Perl és Python nincs mindenhol, ebbe az irányba nem tudok elmenni.

Lehetőségek Linuxon:
dash - "...virtually compatible with the POSIX standard's specification of the Unix shell"
ksh - "KornShell complies with POSIX.2"
bash - "Bash is a POSIX shell, but with a number of extensions."
zsh - ???
csh - ???

Így elsőre dash vagy ksh. Ok hogy a ksh93 más, de pl. AIX-os kollégák azt mondják hogy a Linux-os ksh és az AIX-os ksh sem ugyanaz. Esetleg ajánlhatnátok valamit, kb. vagy ksh vagy dash.

Köszönöm szépen.

Hozzászólások

A legfapadosabb, legkevésbé komfortos shell, amit próbáltam, a dash. Pl:


trap '' HUP    # ezt megeszi
trap '' SIGHUP # ezt nem

printf '\033'  # ezt megeszi
printf '\x1b'  # ezt nem

f () {          # ezt megeszi
function f () { # ezt nem

A select az pont egy ksh-ban kitalált és POSIX-ba beemelt, gyakorlatilag bugyuta, menüépítésre kitalált ciklusszervező utasítás.


select i in alma narancs szilva ; do
case "$i" in
alma) # ide jön az alma kiválasztása esetén végrehajtandó utasítássorozat
;;
narancs) # ide a narancs
;;
szilva) # ide meg a szilva
;;
esac
done

Lefuttatásakor kapsz egy


1) alma
2) narancs
3) szilva
#?

kinézetű menüt, 1 kiválasztásával eléred "alma"-t, 2-vel ....
És amikor lefutott, akkor újra menükiiratás és adatbevitel. A PS3 változóval a #? - mint prompt módosítható valami értelmesebbre, pl:


PS3="Válassz a fenti számok közül az egyes funkciók eléréséhez "

Solarison ~15 éve van by default bash (talán a 7-esben jött be, ha jól emlékszem). A Cygwin GNU utilitykből áll, tehát ott eleve kéne legyen bash. AIX/HPUX vonalon nem tudok nyilatkozni, de nagyon meg lennék lepve, ha egy mai verziójukban ne lenne bash.

A csh nem is Bourne-kompatibilis, már egy if szintaxisa is tök más.

A szomorú helyzet amúgy az, hogy ha feature-ökre is szükséged van, és a bash alá adod, akkor gyorsan eljuthatsz arra a szintre, hogy az igényt nem fedi le a legnagyobb közös osztó, és elkezded telirakni a scriptet OS-függő hackolásokkal. Akkor meg már inkább a perl...

Off: nemrég a Perl-ben íródott yasql-t telepítettem, örömmel láttam, hogy az újabb Perl már nem futatja, egy-két 'do' kulcsszót ki kellett szedni a programból; ami eddig opcionális volt, az most már tilos.

Még szerencse, hogy a konkurrencia (PHP, Python) sem idegenkedik az inkompatibilis változtatásoktól...

Hát izé, nem sok olyannal találkoztam, amit a bash tud, de a Korn-shell nem (és a programozhatóság szempontjából kihasznált eszköz lenne). HP-UX alatt sokáig nem volt bash, aztán egy darabig igen, de ha jól emlékszem mostanság megint nem része az alaprendszernek. Van helyette Korn-shell (ksh88), meg dtksh néven az újabb verzió (ksh93 alapon), és persze HP-UX-on eléggé régóta eleve a ksh88-ra épülő Posix-shell az alapértelmezett. (Mintha kb ugyanez lenne a helyzet AIX-szel is, de majd kijavít aki pontosan tudja.)
Sokkal nagyobb baj a bashizmek használata - akkor is, ha azt a funkciót le lehet írni másként is (pl. olyan formában, amit évszázadok óta tud a Korn-shell). Sokszor utaltam már rá:
source a . helyett
function x() - a function x illetve az x() forma helyett

Illetve szintén nagy probléma a linuxizmek; tipikusan szkriptekben pl: for i in `seq 1 100` - amivel csak az a baj, hogy seq nem sok nem-Linux rendszerben van. (Konkrétan talán Solarisban, de a többiben amik még egyáltalán léteznek, egyikben sem.)

No megnéztem a man-t:
"The seq command first appeared in Plan 9 from Bell Labs. A seq command appeared in NetBSD 3.0, and ported to FreeBSD 9.0."
Most hogy írod, már kezd derengeni, hogy valamikor olvastam erről, de azért az ilyen felesleges dolgokat azért nem mind szoktam megjegyezni. Mindenesetre kösz, most egy-két hétig megint fogom tudni.

OFF: Hogy utálom, hogy a C-shellben ezt leírhatod:


set a=2
set a = 2

de az már szintaktikai hiba, hogy


set a= 2
set a =2

Amúgy pedig Bourne-shellben ezt így kellene:


a=1
while [ "$i" -le 100 ] ; do
...
i=`expr "$i" + 1`
done

Korn- illetve POSIX-shellben már van rá egy halom gyorsabb és kicsit olvashatóbb módszer is, pl:


i=1
while (( i <= 100 )) ; do
...
(( i = i + 1 ))
done

Azzal persze egyet tudok érteni, hogy a for i in `seq 1 100` rövidebb - de cserébe nem hordozható.

Jav. a while ciklus feltétele.

Az még a kisebbik baj, de rászoktatja a népeket a `backtick` ilyen használatára... aztán ne csodálkozzunk, hogy honnan szedik a kezdők az ilyeneket:

for i in `ls`; do ... done

(Na persze az átirányítással is van gond: az hogy a ciklusmag is át van irányítva:


seq 1 10 | while read n; do echo $n; read m; done
1
3
5
7
9

Hol nincs Perl? A Python-t el tudom kepzelni, hogy regi rendszereken esetleg nincs es nem lehet letolteni, de Perl? Az 25 eve kirobbanthatatlan a Unixbol.

Oke, de mennyire realis, hogy egy olyan rendszeren kell a szkripteket futtatni, amin csak az alaptelepites van fent (amugy mit lehet egy ilyen rendszerrel csinalni?)? Vagy kifejezett ceges policy, hogy Perl le van tiltva az installbol? Mennyire realis ez a kovetelmeny?

Csak azert kerdezem, mert sokszoros a fejlesztes sebessegkulonbsege Perl vs shell szkript. Egyszeruen nem eri meg a szivast, a legtrivialisabb aprosagokat leszamitva. Foleg, ha a szivasba beleertendo, hogy altalanosan mindenhol fusson.

Nálunk a rendszerek jó 10%-án nincs Perl, és nem is lehet kérni, vagy lehet kérni csak akkora macera hogy lemondasz róla. Vagy pl. MVS unix subsys-en se látott Perl-t a kolléga, lehet nem is létezik, de ha létezik is nem volt ott, innentől pont az előző eset.

____________________
echo crash > /dev/kmem

Ismertem nem kis céget, ahol céges policy az volt, h a HP-UX szerverekre pl. nem fordíthattak maguknak szoftvert (így pl. perl-t sem), de ha mondjuk a HP adott egy gyári CD/DVD-t, amin volt perl, akkor az felmehetett.
A fejlesztés sebességkülönbsége meg szerintem leginkább azon múlik, hogy a fejlesztő shell-t vagy perl-t szokott-e gyakrabbn feladatmnegoldásra használni. Még 1x: szerintem.

Sajnos az sh csak az egyik probléma, a második kör az az által meghívott gnu vagy nem gnu tool-ok és azok verziónként és rendszerenkét változható paraméterezései.

Úgy '93-tól (telefonos szolgáltatás) számlázásra előkészítő rendszereket írtunk pont AIX-re. Méghozzá shellben, tarifálást, feldolgozást könyveléshez, göngyölítést, forgalmi kimutatást, részletezőt az előző N napra - max 18 hónap, stb. A script az ügyfélszolgálati munkahelyeket is kiszolgált. Akár egyszerre többet is. Azóta is meg tudok oldani mindent, még szökőévben is. ;)
A dateutils-t meg sohasem használtam.
Tudod, a topic a hordozható scriptről szól!

Ez csak kis bosszú volt a nyílért. :)

A lényeg lemaradt: mindez megy linuxon is.

Ne egyszerű kérdés!
Úgy 20 év AIX tapasztalat után ksh lenne a szavazat. Sajnos többször hordozni kellett a programot linuxra. Nagyon régi a tapasztalat, de ott a ksh nem igazán bizonyult működőképesnek, ezért maradt a bash.
A bash viszont csak 15 év alatt érte utol a ksh-t, ami végülis nem rossz, mert jelenleg elég hasonlóak.

Szerintem az ökölszabály az, hogy minden rendszeren a default shell-t érdemes használni. Ha tartózkodsz az adott shell specifikus megoldásainak használtától, akkor majdnem hordozható lesz a kód, de nem teljesen. Ráadásul - mint írták - az egyéb toolok használata is eltérhet az egyes rendszereken. Számomra az AIX - OpenSuse - Debian átjárhatóság esetenkén maximum 1 napos munkába került. Természetesen a C shellre ez nem igaz.

További gyakorlati jótanács: Az egyes linux disztrók esetén első dolgod legyen az elmebeteg environment és lokalizáció eltávolítása! Bármilyen hordozhatóság alapfeltétele a LANG=C (POSIX) esetleg en_US.

Rakd fel má' azt a nem hordozható scriptet, amiben a nyilakat nyomkodtad! :))
Bár annyi igazad vagyon, hogy eleinte a line editing funkcióról szóló könyvecske lényegesen vastagabb volt, mint az összes többi. Akik meg vi helyett joe-t használnak egyáltalán nem megbízhatóak! ;)

És mekkora szopás a fent emlegetett bash-t hiányoló rendszereken ;-)
Egyébként fenti aliasok az egyedül üdvözítő megoldás, bár én még raknék oda még pár másik aliast, egyrészt mert vannak olyan elvetemült terminálok/terminálemulátorok/beállítások, amelyek nem [ ABCD szekvenciát küldenek, hanem van olyan, ahol a [ helyett O van, meg olyan is, amelyikben úgy ahogy van ez a második karakter hiányzik ( lásd pl: http://www8.cs.umu.se/~isak/snippets/vt100.txt ). A nagyobbik baj, hogy fenti aliasok beállítása után maga az aliasok lekérdezése elég sok helyen problémát fog okozni, ugyanis a kurzor-le gombhoz rendelt karakter (amúgy Ctrl-N) bizonyos terminálok/emulátorok esetén alternatív karakterkészletre váltja a kijelzést, ami után átlagjúzer (de átlag rendszergizda sem) nem nagyon tudja elolvasni a képernyőn a dolgokat (ugyanis átvált a keretrajzoló karaktereket tartalmazó készletre). Ezért én legalább még egy alias-t be szoktam rakni, aminek a neve a lista végére kerül (ezért tipikusan alias __Z), értéke pedig a karakterkészlet visszaállítására alkalmas érték, azaz a 'tput sgr0' parancs kimenete. Gyengébbek kedvéért: Ctrl-O .)

(Fentieket *ne* a .profile-ba tedd, hanem abba a fájlba, amire a $ENV hivatkozik - tipikusan $HOME/.kshrc -, és akkor minden létező terminálsession-ben és al-al-al-Korn-shellben menni fog a 4 kurzormozgató. És ha még azt is köré teszed, hogy:


case "$-" in
*i*) # interaktív shell
set -o emacs
alias ...
;;
*) # nem-interaktív shell
...
;;
esac

akkor pl. a futtatott shell-scriptek nem kapják meg az aliasaidat :-) A .profile-ba meg mehet az EDITOR=vi ; export EDITOR )

Köszi mindenkinek, elindulok ksh irányba, feltérképezem mik lehetnek az eltérések. Nem szorosan de idevág: echo vs printf, és még bele se ástam magam :)
Ha nagyon nyűgösnek néz ki (számomra) akkor meg Perl.

____________________
echo crash > /dev/kmem

Rendes ksh-ban van egy kb alias echo=print szintű beállítás, azaz noha a ksh saját parancsát print-nek híjják, használhatsz echo-t is benne. Ha viszont az egyes echok közti különbséget el akarod felejteni (Hogy kell soremelés nélküli kiírást kérni? 'echo -n valami' vagy pedig 'echo valami\\c'), akkor valóban el kell indulni a printf irányba, az kb mindenütt van - igaz, többségében nem shell belső parancsként, de legalább közel azonos szintaxissal.

Hát a function, és a select hiánya miatt nem annyira POSIX. Lehet még tesztelni a (( aritmetikai-kifejezés )) parancsot, a $(( aritmetikai kifejezés )) helyettesítő mechanizmust (*), van-e $( parancshelyettesítés ) - vagy csak a `parancs` forma, ellenőrizhető a tömbváltozók kezelésése (és az, hogy


set -A tomb 1. 2. 3.
vagy épp
tomb=( 1. 2. 3. )

formában tud egyszerre inicializálni több elemet is, mert a POSIX csak a


tomb[0]=1.
tomb[1]=2.
tomb[2]=3.

formát írja elő). Ellenőrizhető, hogy van-e a változóknak tipusa (pl. integer/float - tudtommal az utóbbi ksh93 egyedül), readonly, létezik-e ugye az a mechanizmus, hogy "aritmetikai környezetben" pl. nem kell $i-t írni, elég csak simán i; és í. t. Szóval azért nem biztos, hogy a dash annyira POSIX, egyelőre két negatívumot már mondtál :-)

(*) Ehhez is van bashizm: $[ aritmetikai kifejezés ] formában (persze ismeri a ksh/POSIX-félét is, de a különböző leírások ezt a formát sulykolják - tök értelmetlenül amúgy)

Akkor viszont marad kb a UNIX V7-es shell funkcionalitás - hisz simán lehet még olyan (múzeumi) rendszert találni, aminél az alap /bin/sh nem POSIX/BA(SH)/K(SH), hanem jó öreg Bourne-shell. (Ja már az alias parancs megléte is "modern" shell-re utal, mármint a Bourne-shell kompatibilisek esetében.)

Csak follow up, shell scripting jobban bejött mint Perl. Utóbbi tényleg jó cucc, de ha az ellátandó feladatok leginkább olyanok hogy futtass valami un*x utility kombót, és elemezd a kimenetét, a shell scripting kényelmesebb (nekem).
Pár útmutatót követek (http://mywiki.wooledge.org/Bashism pl.), eddig bash/ksh/dash vonalat sikerült tartani. Ha minden megy még zsh, csh, tcsh, mksh alatt is, akkor szerintem eléggé portable lesz a motyó. Ofkoz tesztelni, tesztelni, tesztelni.

Egyébként érdekes látni, hogy bár a Perl nyilván sokkal-sokkal több mindent tud, több mindenre jó, ha a shell scriptingbe belemerül az ember akkor azért az is mutat pár lehetőséget :)

Mostmár csak Perl5 jövőjére vagyok kíváncsi, ha lesz neki akkor azért azt se kellene hanyagolnom.

____________________
echo crash > /dev/kmem

Ha minden megy még zsh, csh, tcsh, mksh alatt is, akkor szerintem eléggé portable lesz a motyó.

A nagyon egyszerűeken kívül szerintem a szkriptjeid csh és tcsh alatt nemigen mennek. Eleve pl. a for-ciklus máshogy néz ki, meg persze arról nem is szólva, hogy függvények pl. nincsenek.