HIBAKERESÉS, TIPPEK ÉS TRÜKKÖK

Ebben a fejezetben gyűjtöttük össze, lehetőleg témák szerint rendezve, mindazokat a problémákat, amelyek a kezdő Unix felhasználó életét oly gyakran megkeserítik. Az elhangzottak egy részére a könyvben már szerepeltek utalások, mások a sehova be nem illeszthető, "mit tegyünk ha..." kategóriába tartoznak. Szerepelnek itt olyan problémák, amiket a tanfolyamaink hallgatóinál tapasztaltunk, mások viszonylag közismert és gyakran előforduló gondok, melyekre ugyan ott szerepelnek a kézikönyvekben a megoldások és bölcs intenciók, de ezekre a legritkább esetben bukkanhatunk rá céltudatos kereséssel... Mindegy, íme egy csokor az általunk legfontosabbaknak ítéltekből; csak buzdítani tudunk mindenkit e lista saját bővítésére, s ha ezt megosztják velünk a könyv következő kiadására, hisszük, hogy ez mindenki számára hasznos és gyümölcsöző lesz.

Bejelentkezés, terminálkezelés

Bejelentkezés után csupa nagybetűvel ír a rendszer, akár kis-, akár nagybetűt is használunk.

Problémánk gyökere valószínűleg abban rejlik, hogy bejelentkezési nevünk csak nagybetűket tartalmaz (vagy véletlenül a CapsLock gombot lenyomtuk); a login program, amelyik a bejelentkezéseket ellenőrzi, ezek után azt tételezi fel, hogy olyan terminálon dolgozunk, amelyik csak a nagybetűket ismeri (ó, a hőskor...!) - s a továbbiakban ehhez is tartja magát, mindent nagybetűvel ír, a tényleges nagybetűket rendszerint egy eléjük helyezett backslash karakterrel különbözteti meg.

Az egyik megoldás, ha a CapsLock "beragadása" okozta a problémát, a kijelentkezés, és újbóli belépés; ha a ellenben a bejelentkezési nevünk van rosszul megválasztva, cseréltessük le a rendszergazdával úgy, hogy legalább egy kisbetűt is tartalmazzon, ettől a login program "észreveszi magát".

Ha valamilyen okból mégsem akarunk kilépni, az stty parancs megfelelő opcióival próbálkozhatunk: az

 

stty iuclc -olcuc -xcase

opciókombináció rendszerint segít a problémán.

Bejelentkezéskor (s ha sikeres volt, utána is) időnként értelmetlen karakterek szerepelnek a jók helyett.

Ha a rossz karakterek rendszeresen, minden második, harmadik karakterhelyen fordulnak elő, valószínűleg a paritáskezelés van rosszul beállítva. Az stty konfigurálását ilyenkor célszerű a rendszergazdára bízni, ha mégis magunknak kell boldogulni, akkor a parenb parodd cstopb cs7 cs8 paraméterekkel való szisztematikus kísérletezéssel állítsuk be a vonali jellemzőket.

Ha a hiba ékezetes magyar szöveg megjelenítésekor jelentkezik, valószínűleg az a gond, hogy terminálunk hét bites üzemmódra van állítva. Adjuk ki az

 

stty cs8 -istrip

parancsot a nyolcbites üzemmód beállítására.

 

Fájlkezelés, parancsbegépelés

A fájlnév egy '-' karakterrel kezdődik. Hogyan lehet a fájlt átnevezni, vagy kitörölni?

A gond abban rejlik, hogy a '-' karaktert a programok opciókezdő karakternek tekintik, s ebbéli meggyőződésükről elég nehéz lebeszélni őket. Mindazonáltal több módon is megoldható a probléma. A legegyszerűbb, hogy a szóban forgó fájlnevet tetszőleges, akár relatív, akár abszolút elérési út megadással nevezzük meg, a lényeg az, hogy ne a mínusz jel kezdje a nevét. Ha például -xfile a fájl neve, a ./-xfile hivatkozás tökéletesen megoldja a problémát és "kezelhetővé" teszi a fájlt.

A másik megoldás, amit számos segédprogram elfogad, a '--' opció használata. Ez az opció ugyanis azt jelenti az adott programnak, hogy a következő paraméterek már nem tartalmaznak opciót. Így a fenti félresikerült nevű fájlt a legtöbb program jól kezeli a -- -xfile megadással. (Csak a zűrzavar fokozására említjük meg, egyes programok, például az rm egyes régebbi implementációi, az egyetlen mínusz jelet is ilyen értelemben kezelik, nem a standard bemenet vagy kimenet jeleként...)

Speciális karakterek kerültek egy fájlnévbe.
Hogyan lehet a fájlt átnevezni, vagy kitörölni?

A legkézenfekvőbb megoldás, hogy keresünk a fájlnévben egy olyan jellemző részt, amelyik ezt és csakis ezt a fájlt jellemzi, majd ezt a mintát a fájlnév behelyettesítési mechanizmus speciális karaktereit felhasználva adjuk meg törlésre, valahogy így:

 

rm *egyedi_minta*

Ha pontosan nem tudjuk, a speciális karakter hol is került bele a fájlnévbe (és általában nem is tudjuk, hiszen ezek egyben rendszerint nem-nyomtatható karakterek is), akkor az

 

od -c .

paranccsal kérjünk egy listát a munkakatalógusról. E listában a katalógusfájl tartalma karakteres formában jelenik meg, a nem nyomtatható karaktereket oktális formában adja meg. A lista alapján egyértelműen eldönthető, hogyan is néz ki valójában a keresendő fájlnevünk, s hogyan tudjuk elkerülni, hogy az egyedi_minta megadásába bekerüljön a galibát okozó karakter is.

Ha valamilyen oknál fogva a mintaillesztést nem használhatjuk, a fájlkezelő parancsok -i (interaktív) opcióját használhatjuk, melynek hatására egyenként visszaigazolást kér, hogy végrehajtsa-e a szóbanforgó fájlok a kérdéses műveletet.

Ha a -i opcióval se boldogulunk, derítsük ki a renitens állomány inode számát (például az

 

ls -il

paranccsal), majd egy célzott find paranccsal, amelyik a kapott inode-hoz tartozó fájlt keresi, töröljük illetve módosítsuk:

 

find . -inum inode_number -ok rm -f {} \;

(A fenti műveletsor végrehajtásakor ne felejtkezzünk el arról, hogy az inode-ok csak egy önálló (becsatolható) állományrendszeren belül egyediek, tehát mivel az egész állományrendszerben több azonos inode is lehet, vigyázni kell arra, vajon tényleg a kívánt állományt töröljük-e – e célból is célszerűbb a –ok opció használata a -exec ellenében.)

Hogyan lehet egy kitörölt fájlt helyreállítani?

A lakonikus válasz az, hogy sehogy, s ez alól bizony kevés kivétel akad. Ha a problémán egy törlés után kezdünk el gondolkodni, bizony késő a bánat; a kitörölt fájlok felszabaduló blokkjai az állományrendszer szabad blokkjainak listájára fűződnek fel, ráadásul olyan szerencsétlen módon, hogy minden új helyfoglalási igénykor a legutoljára felkerült blokkokat osztja ki elsőként a rendszer. Egyetlen, hajszálnál is vékonyabb esély csak akkor van, ha akad a közelben szakértő rendszergazda aki azon nyomban lekapcsolja a gépet, majd többé-kevésbé manuális eszközökkel "visszavadássza" a törölt fájlt. A dolog közel sem triviális, s a sikere még ekkor is igen kétséges.

Egyetlen megoldás a megelőzés. Viszonylag könnyű és általános megoldást jelent az aliasok használata (sajnos ezt a mechanizmust nem minden shell ismeri). Ha viszont rendszerünkben használható, akkor az rm parancsot aliasként definiálhatjuk, az

 

alias rm 'rm -i'

vagy hasonló formában, s a továbbiakban az rm parancs meghívásakor az interaktív opció hatására rákérdez, hogy tényleg törölni akarunk-e. A megoldás (és minden más megoldás) hátránya a széles értelemben vett átvihetőség és szabványosság hiánya: ha egy másik Unixos gép elé ülünk le, nem biztos, hogy akár ez, akár más megoldás működik a gépen, s tévedésünkre rendszerint itt is csak az első törlés után döbbenünk rá...

'Command not found' vagy hasonló hibaüzenetet kapunk a shellscriptünk indításakor, noha végrehajthatóvá van téve és a munkakatalógusunkban van.

Néha, ha új környezetben dolgozunk, azt tapasztaljuk, hogy az elindított program nem indul el, pedig a munkakatalógusunkban van, és még végrehajtási jogunk is van rá. Ekkor jusson eszünkbe, hogy a Unix csak azokat a katalógusokat tudja elérni, amelyek a PATH változóban szerepelnek. Így ha az adott környezet PATH változójából hiányzik a mindenkori munkakatalógus, a prog nevű programot a ./prog paranccsal tudjuk elindítani. (A kurrens katalógus PATH változóba illesztését biztonsági okokból nem javasoljuk.)

Nincs history szolgáltatás a csh esetén

Állítsuk be .cshrc fájlunkban az alábbiakat (a számérték természetesen egyéni ízlés dolga, a túl kis értékek az eseménypuffer értelmét kérdőjelezik meg, a nagy puffer pedig a shell indulását lassítja jelentősen):

 

set history=20 # eseménypuffer mérete

set savehist=20 # a kilépéskor megõrzendõ puffer mérete

Változó értékadásánál a 'var: not found' hibaüzenetet kapjuk.

A probléma oka minden valószínűség szerint az, (a standard Bourne és a Korn shell használatát feltételezve), hogy az értékadás '=' karakterét szóközök veszik körül. A shell ugyanis csak akkor ismeri fel, hogy értékadásról van szó, ha az első szón belül szerepel az egyenlőségjel; ha szóköz van az egyenlőségjel körül, a shell a változónevet fogja a végrehajtandó parancs nevének tekinteni, az egyenlőségjelet az első, a változóértéket pedig a második paraméternek. E probléma a C shellnél nem merül fel, ott a szóközök megléte vagy nemléte érdektelen.

A shellscript, amit futtatunk, meg kellene hogy változtassa a kurrens
katalógust (shellváltozót), de ez mégsem történik meg, a shellscript
lefutása után változatlan marad.

A magyarázat a Unix többfeladatos működéséből következik. Amikor egy shellscriptet elindítunk, a shell egy újabb, úgynevezett subshellben indítja el a scriptet. A subshell örökli szülője környezetét, annak egy másolatával dolgozik tovább, de ebből az is következik, hogy a shellscript lefutása és a subshell befejeződése semmilyen hatást nem gyakorolhat az eredeti shellváltozókra, hiszen azoktól teljesen függetlenül kezelte őket a rendszer.

A problémának ha nem is megoldását, de megkerülését úgy érhetjük el, hogy a futtatandó scriptet nem subshellel futtatjuk, s így a script által módosított változók a kurrens környezetet módosítják. Bourne és Korn shell esetén a

 

. shellscript

paranccsal, míg C shell esetén a

 

source shellscript

paranccsal lehet a kurrens shellben futtatni.

Hogyan tudunk Bourne vagy Korn shellben a csh .logout fájljához
hasonlóan, kilépéskor lefutó konfigurációs fájlt létrehozni?

Ha a fájl az egyszerűség kedvéért .logout névre hallgat, akkor a

 

trap ". .logout" 0

parancs hatására, amikor a login shell a kilépést jelző 0 szignált észleli, végrehajtja a trap parancsban definiált parancsot, azaz a .logout fájlban megadott parancsokat.

Segédprogramok furcsaságai

A find parancs a -exec vagy -ok opció használatakor az 'incomplete statement' hibaüzenettel reagál.

Gyakran kapjuk ezt a hibaüzenetet, ha a find parancsot a -exec vagy -ok opciókkal hívtuk meg. A kézikönyv ugyan megemlíti, hogy az ezen opciók után beírandó parancsokat a '\;' karakterekkel kell lezárni, de azt nem, hogy e karakterek és a velük lezárt parancs között legalább egy szóközt is el kell helyezni... Tehát például a

 

find . -name thisfile -exec ls -l {}\;

megadás helytelen, helyette az alábbit kell használni:

 

find . -name thisfile -exec ls -l {} \;

(A probléma nem minden find implementációban fordul elő.)

A test beépített parancs rövidített írásmódja

Gyakran lehet gondunk a test beépített shell parancs rövidített írásmódjával, amikor e shell szerkezetet a [] jelekkel rövidítjük. Noha implementációnként eltérhet a shell reagálása, saját keserű tapasztalataink alapján forrón javasoljuk mindenkinek, hogy a szögletes zárójelek mindkét oldalán helyezzen el szóközöket. Az alább következő példa az esetek többségében szintaktikai hibához vezet:

 

if [-d $dfile];

...

helyesen (pontosabban biztonságosabban) így írjuk:

 

if [ -d $dfile ] ;

 
Hogy tagoljuk a shell vezérlési szerkezeteit?

Az alábbiak inkább shellscriptek írása közben zavarnak, de a megfelelő tanulság interaktiv parancsírásra is levonható. A C nyelvhez szokott felhasználók a shell vezérlő utasításait gyakran írják egysorba, elválasztó pontosvessző nélkül, valahogy például így:

 

if date|grep SEPT then echo "Iskolaba megyunk" else echo "szunet van" fi

Biztosak lehetünk benne, hogy a fenti paranccsal jól megzavarjuk a shellt. Ugyanis, amit mi kulcsszónak gondolunk, azt a shell csak adott pozíciókban tekinti kulcsszónak, más helyen csak egy karaktersorozat, amit parancsargumentumként kezel. A kiemelt helyek, ahol a shell kulcsszókat keres: a soreleje, valamint a parancselválasztó pontosvessző utáni pozíció. Tehát a fenti parancs egy helyes alakja:

 

if date | grep SEPT; then echo "Iskolaba megyunk"

else echo "szunet van"; fi

Az általános ökölszabály az, hogy a then, és a do "töltelékszavak" vonhatóak össze egy sorba az őket megelőző if, for vagy while szintaktikus elemekkel. Az összevonás feltétele, mint a fenti példán láttuk, a pontosvessző használata, mert ez parancsszeparátorként a kiváltott újsor karaktert helyettesíti. Tehát például az

 

if expr; then

while expr; do

for var in wordlist; do

rövidítések biztonsággal használhatóak.

Negált minták a grep parancsban

Milyen mintát kell adnunk a grep parancsnak ha egy állományból olyan sorokat szeretnénk kiválasztani,amelyek nem tartalmaznak egy adott karaktert, mondjuk a 9-es számot? Ez a kérdés minden alkalommal megizzasztja a hall-

gatókat. Ugyan is, ha olyan sorokat akarunk kiválasztani, amelyekben van 9-es szám, a dolgunk egyszerű, a minta maga a szám. Ha ennek negáltját adjuk meg mintának, ([^9]), az meg fogja találni az összes olyan sort, amiben van legalább egyetlen nem 9-es karakter. A helyes megoldás szavakban így fogalmazódik meg; keressük azt a sort, amelyben az elsőtől az utolsó karakterig nincs 9-es. Jelekben:

 

grep '^[^9]*$' file(s)

A vi (ed, ex) editor használata közben leállt a rendszer és elveszett az éppen szerkesztett fájl.

A vi egy külön könyvtárban biztonsági másolatokat tart fenn a szerkesztés menetéről. Rendszerhiba esetén a vi -r opcióval tudjuk megismételtetni a teljes előző szerkesztési menetet. A visszajátszás befejeztekor mentsük el a fájlt valamilyen néven, s máris továbbdolgozhatunk, nagy valószínűséggel csak az utolsó pár karakter hiányzik munkánkból.

Gyakoribb hibaüzenetek

Az alábbiakban a leggyakrabban előforduló hibaüzenetekből "mazsolázunk", a lehetséges gyakoribb kiváltó okokra rámutatva. Válogatásunk többé-kevésbé önkényes, hiszen alapvetően csak a minden rendszerben felbukkanó közös hibaüzenetekkel van értelme itt foglalkozni.

...arg count

Túlságosan sok, vagy túlságosan kevés argumentumot adtunk meg a program által várthoz képest. Az adott program manuál oldalain nézzük meg a pontos szintaxist, de gyakran a parancs által kiírt online 'Usage:' ismertető is kisegít.

 
Arg list too long

A meghívott programnak átadott argumentumlista túl hosszú. Rendszerint nem az általunk begépelt argumentumok okoznak túlcsordulást, hanem a parancssorban szereplő fájlbehelyettesítések (egy nagy könyvtárban kiadott * fájlnév stb) (a `...` parancsbehelyettesítési mechanizmus is szolgálhat hosszú argumentumlistákkal).

Broken pipe

A pipeline-ba szervezett parancsok közül valamelyik időnek előtte elhalt, mialatt valaki még adatokat küldött neki.

File exists

A futtatott program már létező fájlt akar felülírni.

File not found

A program nem találja az általa keresett fájlt. A find paranccsal nézhetünk utána, ténylegesen hol is találhatóak a keresett fájlok.

File too large

A fájl kimerítette a rendelkezésre álló mérethatárt. (Az érték rendszerenként változhat.) Ilyen esetben forduljunk a rendszergazdához, mert számos esetben viszonylag könnyen lehet emelni a felhasználó számára rendelkezésre álló határokat.

Is a directory

A katalógusfájlt úgy próbáltuk meg írni/olvasni, mintha közönséges fájl volna.

No such file or directory

A megadott fájlnév paramétert (akár katalógust, akár közönséges fájlt) nem találja a shell. Ellenőrizzük a megadott fájl- illetve katalógusnevet.

Not a directory

Katalógusnevet váró programnak nem katalógusnevet adtunk meg (például cd).

Not owner

Olyan fájlt próbáltunk meg elérni vagy módosítani, amelyikre nincs meg a megfelelő jogunk. Ugyanezt a jelzést kapjuk, ha nem általunk indított folyamatot próbálunk meg törölni a kill paranccsal.

Out of memory

Túlságosan sok folyamat fut és elfogyasztották a rendelkezésre álló memóriát. A más által indított folyamatokkal persze nem sokat kezdhetünk, de a ps paranccsal megkereshetjük esetleges saját, már nem szükséges processzeinket, s törölhetjük őket. (Gyakran előfordul, hogy egy folyamat számos más folyamatot indít el, s ezek időnként "bentragadnak" a rendszerben, noha már nem futnak. (Kiváltképpen az X Window alapú, grafikus ablakfelülettel ellátott rendszereken szaporodnak minden mértéken felül.)

Permission denied

Megfelelő jogok hiányában próbáltuk meg olvasni, írni vagy végrehajtani a fájlt.

Too many arguments
Too few arguments

Túlságosan sok, vagy túlságosan kevés argumentumot adtunk meg a hívott programnak. (Például egynél több argumentum a cd parancsnál, vagy kettőnél kevesebb az mv-nél stb.)

Usage: ...

Számos program, ha rossz argumentumokkal hívták meg, kiír egy rövid emlékeztetőt, hogy hogyan is kell helyesen használni. Ha e tájékoztató által nyújtott információ nem elég, akár az online, akár a nyomtatott kézikönyv ad részletesebb információt.

... Unknown option

A programnak átadott opció ismeretlen a program számára.

Rendszerállapot változásai

Disk quota exceeded

Betelt a számunkra kijelölt kvóta, miközben új fájlt akartunk létrehozni, illetve már meglévőt módosítani. A kvótaértéket csak privilégizált felhasználó módosíthatja.

 
Read only file system

A fájlrendszer, amin írni próbáltunk, írásvédett. Önmagában álló, hálózatos kapcsolatok nélküli rendszeren ez rendszerint akkor fordul elő, ha a CD-ROM-ot, vagy az írásvédett floppyt az írásvédettség deklarálása nélkül próbáltuk a mount paranccsal becsatolni. Hálózaton lévő Unix rendszereknél gyakori, hogy a hálózaton keresztül, az NFS protokollal hozzáférhető fájlrendszerek is csak olvashatónak vannak deklarálva.

... write failed, file system is full
File system full

A megnevezett fájlrendszeren nincs több szabad hely. Noha ez általában több felhasználó szerencsés együttműködésének "gyümölcse", az esetlegesen általunk indított nagyméretű nyomtatási feladatok, "szemét" (junk) fájlok, átmeneti anyagok, core fájlok stb. törlése segíthet a helyzeten. Ha nem, meg kell várni, amíg a rendszergazda helyet nem csinál, illetve a nyomtatások befejeztével a spooler által igényelt hely felszabadul a lemezen.

Segmentation fault
Core dumped
Bus error
Core dumped

Váratlan belső hiba, rendszerint a program számára kiosztott memóriahatárok megsértésekor jelentkezik. Akár saját programjaink hibás működése, akár valamelyik rendszerprogram hibája eredményezheti. A 'core dumped' üzenet jelzi, hogy az esetleges nyomkövetés céljaira egy core nevű állomány keletkezett, amelyik a rendszer memóriaképét és egyéb nyomkövetési információkat tartalmazza. (Ha nem használjuk fel hibakeresésre ezeket a fájlokat, célszerű rendszeresen irtani őket, mert kivált a mai terjedelmesebb Unixokban igen nagy helyet foglalnak el.

 

Tartalomjegyzék