Sziasztok!
Egy egyszeru feladatom van es nem birok vele. Van az alabbi scriptem:
#!/bin/sh
SERVER=$1;
IP="127.0.0.1";
LINFILE="/etc/hosts";
sed -i 's/'$IP'/'$SERVER'/g' $LINFILE;
exit 0
A lenyeg a host fileban a 127.0.0.1 reszt kell kicserelni a bejovo argumentummal.
Vegig bongesztem a googlet es ami volt hasonlo megoldas ra en kiprobaltam, de vagy "undefined label", "extra character at the end of h command" vagy "rename" hibt kapok, de nem ertem miert.
Valaki elmagyarazna mi a hiba?
Koszonom!
Hozzászólások
hasznalj "-t a sedben, ne '-t: "s/$IP/$SERVER/g"
--
A vegtelen ciklus is vegeter egyszer, csak kelloen eros hardver kell hozza!
Ha alaposan megnézed, észre fogod venni, hogy a változók kiértékelését nem zavarják az aposztrófok, mert kívül esnek azokon. Itt az '-jelek csak a képet zavarják, egyébként funkciótlanok.
tudom hogy nemzavar az aposztrof, de az a sor mar-mar hasonlit egy szep perl sorra :)
meg az a tapasztalatom magamon, hogy az ilyen apro bizbaszok miatt szokott golyozni az ember szeme amikor nezi miert nemmegy, es a vege egy lamerszamlalos porgetes :D
--
A vegtelen ciklus is vegeter egyszer, csak kelloen eros hardver kell hozza!
Az a pont karakter regexben nem pontra, hanem bármire illeszkedik, ugye tudod? ;)
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
Ha tenyleg csak erre kell akkor ne probald meg ujra feltalalni a kereket.
http://augeas.net/
Semmit se akarok feltalalni csak megerteni miert nem mukodik.
set -x -et tegyel a script elejere es latni fogod mit hogy helyettesit be a valtozokbol, utana mar meg tudod nezni mikent ertekeli ki azt regexp-kent es miert baj ez.
pontosvesszők nem kellenek
Ha az IP értékét "kapja" valahonnan, akkor sincs baj, mert a shell megcsinálja neki a pont cseréjét backslash pont-ra (A ${var/ezt/erre} esetén a var változóban az "ezt" mintát cseréli "erre" - ha az "ezt" /-rel kezdődik, akkor valamennyi előfordulása cserére kerül. A pontot itt nem kell levédeni):
Köszi, ezzel én tisztában vagyok, de ha azt írom neki, hogy ${IP//./\\.}, akkor nem biztos, hogy megérti miről van szó.
nem biztos, hogy megérti
Ilyen esetleges lenne a bash működése? Ennyire nem rosszak a tapasztalataim:
a='127.0.0.1'; echo "${a//./\\.}"
127\.0\.0\.1
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
Nem a shell nem fogja erti, hanem a kerdezo, egyelore eleg alap dolgok hianyoznak, pl. az idezojelek megfelelo hasznalata. Amugy a 127.0.0.1 atirasa localhostrol masra igencsak kellemetlen elmenyeket fog okozni, dehat valahol el kell kezdeni...
Hű, tényleg, ezt nagyon félreértettem. ;)
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
Systemd rendszeren nem akkora lábon lövés, az nss-myhostname a localhost-ot mindig 127.0.0.1-re oldja fel. (na persze ha a localhost-ot átírja egy másik címre... és az ajánlásnak megfelelően az nss-myhostname az utolsó...)
BlackY
--
"en is amikor bejovok dolgozni, nem egy pc-t [..] kapcsolok be, hanem a mainframe-et..." (sj)
Tudom, hogy nem jo jatsani a hosts file-al, de tudom miert kell atirnom es mire, de nem irtam le mert nem az volt a tema. :)
Ez speciel pont nem bashizm, a ksh is tökéletesen érti :-P
A szkripted furcsán van megírva (látszik, hogy az idézőjelezés szabályait nem rágtad át, és valamelyik programnyelvből áthallatszik a pontosvesszőzés és exitezés, ami itt csak a képet zavarja), de ettől függetlenül le kell futnia.
Speciális esetben a 127.0.0.1-címnél több, de azt tartalmazó sztringrészletet is lecserélhet, de azt minimum meg kell tennie.
Szintaktikai problémákhoz nem vezethet - így legalábbis nem, ahogyan most kinéz.
Hogy a próbálkozásaid során esetleg egy pontosvessző kettőspont volt, vagy sikerült a közönséges aposztróf/kötőjel helyett valami unicode-os/utf8-as finomságot belevarázsolnod (webes kopipészteknél előfordul), az megeshet. Sőt, nem tudni, nálad konkrétan mit ismer a fájlrendszer /bin/sh név alatt, de lehet, hogy dos/mac formátumban sikerült mentened a szkriptedet, és az az interpreter valamelyik hibaüzeneteddel hálálta ezt meg.
Kieg.: nem tudom, honnan jön az a "bejövő argumentum", de az okozhat meglepetést, ha nem az van benne, amit hiszel.
Valoban masoltam, mert mar kiprobaltam minden verziot a cserehez amit talaltam. De egyik sem mukodott. Ami erdekes terminalban mukodott az alap sed 's/127.0.0.1/$SERVER/g' is, de shell-bol nem. Ezert nem ertettem.
Nézd meg, hogy az a sed egyáltalán tudja-e a -i paramétert (és ha igen, ugyanazt jelenti-e neki, mint a gnu sednek)*, és hogy mi a búbánatos valami ott az a /bin/sh.
Egyébként nem igazán értem, hogy mit jelent az, hogy "terminálban működött, de shellből nem", viszont ha valami shellféle tényleg cserélt neked a sed 's/127.0.0.1/$SERVER/g' parancsra (így, aposztrófokkal) IP-címet IP-címre, akkor az a valami nagyon távol áll a unixos shellektől, és amíg nem sikerült kideríteni, hogy mi az, mit és miért csinál, addig neked is távol kellene állni tőle, mert időzített bomba a fájlrendszeredre nézve.
*Amit talán nem tudsz, a shellek és az azokban használt programkák UGYANAZON névvel oprendszerről oprendszerre, olykor disztribről disztribre vagy verzióról verzióra változhatnak nüansznyit vagy jelentősen a viselkedésükben.
Azt neked kell belőni, hogy mivel van dolgod, és a tapasztalataid alapján alkalmazkodni vagy váltani (szokni v. szökni).
1
1.txt előtte:
utána (1.sh 192.168.10.10):
sed -i 's/'${IP}'/'${SERVER}'/g' $LINFILE;
Probaltam, nem mukodott. :)
Akkor valami nagyon el van kefélve a gépemen, hogy működik. Milyen disztró, milyen verzió, bash verzió? Kicsit írsz a környezetről?
OS: Windows server 2008 es network shell a futtato kornyezet.
Ugye csak szopatsz? :)
Eszembe nem jutott ;) Network shell.
Megteszed, hogy készítesz egy képernyőképet arról, hogyan futtatnád a fenti szkriptedet, és mi az eredménye, majd kiteszed egy publikus helyre, és idelinkeled?
Csak azért kérem ezt, mert adok annak egy töredékszázaléknyi esélyt, hogy durvára félreértelek...
Hátőőőőőő. Próbáltad már Linuxon futtatni? :D
Nem ismerem a Win lelki világát, Cygwines megoldásokról tudok, de ez a network shell dolog számomra ismeretlen.
Van valami leírásod erre, hogy ez miképp működik? Google nem valami beszédes erre a kulcsra.
Ha ez valami hakkolt megoldás arra, hogy a winen is tudj bash-t futtatni, akkor gyanúsan az implementáció lesz a hibás, nem a scripted.
Itt most linuxos masinákat akarsz elérni, vagy a winen lévő hosts fájlt akarod túrni?
Ergo akkor megkérlek ismét, írj a környezetről egy kicsit :)
(és mindenki integessen a kamerának, tuti kandiznak és a retek klubon leszünk 2 nap múlva)
Nem hackelt megoldas, hanem hivatalos forras.
Akar, hogy probaltam nem jott ossze csak igy:
cat $LINFILE | sed "s/$IP/$SERVER/g" > $LINFILE
Szoval koszonom mindenkinek a segitseget! Atnezem melyebben a sed rejtelmeit. :) illetve mi a diferencia a linux shell es az nsh sehll kozott. Eddig szerencsem volt, mert minden mukodott nsh-ban ami linux kodot probaltam.
Megegyszer koszonom a hozzaszolasokat!!! Sok pontra ravilagitottatok :D
Ezt a modszert (input es output ugyanaz egy pipelineban) nagyon gyorsan felejtsd el, komoly meglepetesek erhetnek kulonben (legalabbis unixokon). Hasznalj helyette tempfilet, es a vegen csereld le vele az eredetit.
sed -i
?
BlackY
--
"en is amikor bejovok dolgozni, nem egy pc-t [..] kapcsolok be, hanem a mainframe-et..." (sj)
Neki nem GNU sed-je van.
Fordítson egyet :)
BlackY
--
"en is amikor bejovok dolgozni, nem egy pc-t [..] kapcsolok be, hanem a mainframe-et..." (sj)
+1
sed "s/${IP//./\\.}/$SERVER/g" "$LINFILE" >"$TEMPFILE"
mv -f "$TEMPFILE" "$LINFILE"
Úgy körülbelül.
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
Igy valoban jobb ;)
Mi van akkor, ha a sed hamarabb nyitja meg írásra a fájlt O_TRUNC, mint a cat olvasásra?
Ez jol esett, koszi! :)
Értem én, hogy véletlenül működik, de fáj, hogy eleve hibás, ami le van írva. A pont karakter továbbra is bármire illeszkedik nem csak a pontra. Ezen felül hiányzik az idézőjel, így ha a filenévben szóköz van, más file-ra fog hivatkozni, mint amire kellene.
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
OK.
Szerintem így jobb lenne az a sor:
sed -i "s/${IP//./\\.}/${SERVER}/g" "$LINFILE"
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
Ez tény.
Milyen más fájlról van szó? A scriptjében világosan meghatározza, hogy milyen fájlban akar turkálni.
Tehát egyetértesz azzal, hogy használjuk ki, hogy éppen most nincs szóköz a file-ban? Véletlenül se törekedjünk olyan írásmódra, amely minden esetben működik?
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
ok, jogos
Megoldás: (bash alatt tesztlve a sed.)
IP="127.0.1.1"
IP2="127.0.1.2"
sed -i -e "s/$IP/$IP2/" /etc/hosts
A Te esetedben ez kellene, hogy legyen:
sed -i -e "s/$IP/$SERVER/" $LINFILE
Még jó, hogy fentebb kibeszéltük, ez miért nem jó. Kezdjük elölről?
(Nem GNU sed, nincs -i kapcsoló. Filenév idézőjelbe kellene, hogy szóközök mentén ne essen szét. A regexpben a . mindenre illeszkedik, nem csak a pontra. Igaz, épp arra is. Tehát escape-elni kell backslash-sel. Fentebb erről mind esett szó.)
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
Köszönöm az észrevételed,de én itt -e kapcsolóra fókuszáltam volna valójában.
Abban igazad van, hogy a pont az egy karaktert jelent, jelen esetben épp a pont karaktert is. Átnézem még a dolgot.
Ezt viszont én nem tudom. Mi a különbség a -e script és a csak natúr megadott script között -e nélkül?
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
Na finomítottam szóköz problémás részén:
Teszt fájl tartalma:
aaaaa 127.0.1.1
bbbbb 127a0.1.1
ccccc 12730.1.1
# Alap paraméterek
LINFILE="liter kola.txt"
IP="127.0.1.1"
IP2="127.0.1.2"
# Konvertálás
IP=`echo $IP | sed 's/\./\\\./g'`
IP2=`echo $IP2 | sed 's/\./\\\./g'`
# Csere
cp "$LINFILE" /tmp/$LINFILE".orig
cat "$LINFILE".orig | sed -e "s/$IP/$IP2/" > "${LINFILE}"
rm -f /tmp/"$LINFILE".orig
Ez így lefut szépen. Remélem ezzel közelebb kerültünk a megoldáshoz.
http://hup.hu/node/140094&comments_per_page=9999#comment-1866114
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
Jó a tied szebb megoldás:)
Próbáld meg úgy, hogy nem a /tmp könyvtárban futtatod :-P
Nana, nem kötekedünk :P