Adott egy lista:
Adott egy lista, amiben több ezer gép mentéséről van információ, ilyen formában:
1716226178 dbs01
1716232046 dbs01
1716312666 dbs01
1716318416 dbs01
1716398846 dbs01
1716404845 dbs01
1716485330 dbs01
1716491210 dbs01
1715965107 vcenter01 web99
1716051341 vcenter01 web99
1716137815 vcenter01 web99
1716224247 vcenter01 web99
1716310498 vcenter01 web99
1716396981 vcenter01 web99
1716483542 vcenter01 web99
Azaz időbélyeg, a vcenter neve ha VM, és a host neve. Az oszlopok sorrendjén tudok változtatni.
Ebből kellene ilyet csinálni:
UPDATE servers set backup='1716491210' WHERE hostname='dbs01';
UPDATE servers set backup='1716483542' WHERE hostname='web99';
Azaz frissíteni a táblát az utolsó mentés idejével.
Ami jelenleg van:
while read HostName
do
BTIMESTAMP=$(awk -v HNAME="${HostName}" 'BEGIN{C=0} {if ($NF == HNAME && $1>0+C) C=$1} END{print C}' "${CACHEFILE}")
if ! [ -z ${BTIMESTAMP} ];
then
echo "UPDATE servers set backup='$BTIMESTAMP' WHERE hostname='$HostName';" >> "${SQLFILE}"
fi
done < "${SERVERNAMES}"
az nem tetszik, mert gépenként végigmegy a listán, meg egyáltalán, nem elegáns, jó lenne egyetlen awk paranccsal megoldani.
Nem őrület fontos, már így is vagy ezerszer gyorsabb, mint amit megkaptam, hogy írjam át.
A probléma adott, nem tudok pl. olyan listát gyártani, ami csak az utolsó mentéseket tartalmazza. Persze lehet egy lépes az, ami ezt leválogatja a meglévőből.
Amiből lehet válogatni, az az, ami a "szokásos" Centos 7 (nemsokára RHEL9) telepítésben rendelkezésre áll.
Előre is köszönöm az ötleteket :)
Hozzászólások
ilyen feladatokat siman megold a ChatGPT, just sayin'...
Az adott problémát valóban meg lehet oldani egyetlen
awk
paranccsal. Azawk
parancs segítségével egyszerre beolvashatjuk a fájlt és előállíthatjuk a kívánt SQL parancsokat. Az alábbi megoldás azawk
parancsban végzi el az összes szükséges műveletet:bash
awk ' { if ($2 == "dbs01" || ($2 == "vcenter01" && $3 == "web99")) { if ($1 > backup[$2 " " $3]) { backup[$2 " " $3] = $1 } } } END { for (h in backup) { split(h, arr, " ") hostname = (arr[2] == "dbs01") ? arr[2] : arr[3] print "UPDATE servers set backup='\''" backup[h] "'\'' WHERE hostname='\''" hostname "'\'';" } }' input.txt > updates.sql
Az
input.txt
tartalmazza az eredeti adatokat. Az awk parancs végrehajtása után azupdates.sql
fájl tartalmazni fogja az összes szükséges SQL frissítést.Működés részletesen:
awk
soronként olvassa be a fájlt.dbs01
vagyweb99
tartalmaz-e.END
blokkban létrehozza az SQL frissítési parancsokat.Használat:
awk
parancsot egy shell scriptbe vagy futtasd közvetlenül a terminálban.updates.sql
) tartalmazni fogja az SQL frissítési parancsokat.Ez a megoldás egyszerűbb és hatékonyabb, mivel az
awk
segítségével egy lépésben megoldja a feladatot, és nem szükséges több iterációt futtatni a lista feldolgozásához.4 és fél éve csak vim-et használok. elsősorban azért, mert még nem jöttem rá, hogy kell kilépni belőle.
Jogos, kihagytam belőle, hogy a teljes lista az több ezer soros, lehet hogy akár tízezres is, és nem csak ez a két gép van benne.
vissza lehet kérdezni tőle. nekem csak kíváncsiságból megcsinált kb 10 perc alatt egy olyan feladatot, amin pár éve két napot otthon elbütyköltem (persze hobbi projekt, és közben azért folyt a sör, na de mégis)
4 és fél éve csak vim-et használok. elsősorban azért, mert még nem jöttem rá, hogy kell kilépni belőle.
Na, ezt tuti nem tudja egyik LLM sem jelenleg.
Hogyhogy? Ugy tudtam, hogy mindegyik sorfolytonos modon adja a valaszt! :-)
Jogos, és minden averzióm ellenére egészen épeszű ötletet adott... akkor eddig AI - human 1-0.
Mi a pontos specifikáció? Első és utolsó oszlopot nézzük (ha van közbülső, az nem érdekes)? Minden gépnévre az utolsó őt tartalmazó sor? Vagy a legnagyobb időcímkéjű? Vagy mindegy?
Én személyes véleményem:
awk-t már rég elfelejtettem, nyakatekert és számomra természetellenes szintaxis egy roppant limitált funkcionalitásért. Szerintem: ha shell szkriptben egyszerűen megoldható (nagyjából natívan, tehát nem awk-t hivogatva), akkor az; ha nem, akkor python.
Legyen egy asszociatív tömböd / szótárad / ki minek hívja, kulcs a gépnév, érték az időcímke. Ciklusban olvasod a sorokat, minden sorra azt parse-olod (szóközök mentén robbantva, stb.), majd bekorad az értéket a tömbbe. Ha ezzel megvagy, akkor újabb ciklus a tömb összes elemét kiírja a megfelelő szintaxisban.
Bónusz: Python asszem 3.6-tól kezdve a dictionary megjegyzi a beszúrási sorrendet, ebben a sorrendben fogsz végiglépni rajta amikor kiírod az értékeket.
Inkább awk milliószor ilyenre mint python. Nekem a python nyakatekert hovatovább értelmetlen funkcionalitással bír. :-) Ha már ilyen veleményekkel dobálózós nap van. Ezért is írtam meg tisztán awk-ban.
Sajnos nincs meg az a luxus, hogy tabulátor legyen az elválasztókarakter. Szóközök vannak, és nem nagyon van rá hatásom (de ezt még megnézem, mert ezen még tudok alakítani, és hátha).
Hmm, ma is tanultam valamit, szóval tudom állítani az elválasztókaraktert.
Viszont ez azt is jelenti, hogy esélyes, hogy jobb lenne az egészet betolni a céladatbázisba egy ideiglenes táblába, és abból frissíteni a szerverek adatait.
Szóval a probléma átalakul sql kérdéssé, ezt viszont még át kell gondolnom.
A nyers lista 18k sor, és a végén csak 746 szervert kell frissíteni. Az arányok kb. ilyesmik lesznek később is, szóval a kérdés, hogy melyik tetszik jobban:
Egyelőre a második tűnik elegánsabbnak.
Ejj, nem kellett volna kapkodni a válasszal.
Szóval eredetileg úgy van, hogy egy ilyen reportot kérek:
-r "nsavetime,client,vmname"
Ebból az lesz, hogy ha VM, akkor a második oszlop a vcenter neve, és utolsó/harmadik oszlop a VM neve. Ha fizikai, akkor a második oszlop a kliens/gép neve. Szóval így mindig az utolsó oszlop a az érdekes. Meg persze az első.
Ha állítok elválasztókaraktert, akkor ez bonyolódik, mert vagy a második, vagy a harmadik.
Viszont az még egy vállalható kompromisszum lenne, ha két listát generálnék, egyet a VM-ekről, egyet meg a fizikai gépekről, és összefűzném őket.
Akkor ilyen lenne:
Vagy akár veszővel (viszonylag bármilyen karakter lehet) elválasztott.
Én 3x elolvastam, de nem értem hogy mi a feladat és mi a probléma...
Ez a lista eleve SQL-ből jön, nem? Miért kell kiszedni, és legyártani a queryket, amit majd visszatolsz? Miért nem direktben az SQL-ben?
"Sose a gép a hülye."
"Ez a lista eleve SQL-ből jön, nem?"
Nem. Illetve valahol mélyen nyilván igen, de a DB-hez nem férek hozzá közvetlenül. És nem is akarok.
Az mminfo-t tudom használni a backupok lekérdezéséhez.
Én nem sz@roznék azzal, hogy a max(timestamp) keresgélése - betolni mindet egy táblába, és onnanmár egy query kiszedi neked a hostonkénti max(timestamp) értékeket. a vcenter nevét én vagy olyan oszlopba raknám, ami default null, vagy simán két oszlopra konvertálnám az adatokat: a vcenter és a host adatokat összeraknám egy oszlopba, mondjuk egy "#" vagy "|" vagy olyan karakterrel elválasztva, ami sem a vcenter, sem a host mezőben nem szerepelhet. De lehet akár host@vcenter is... Illetve uniq constraint az időbélyeg-host (vagy host@vcenter) párosokra, hogy később futtatott mminfo kimenetből értelmesen tudd tölteni a táblát (ami már benne van, az ne menjen bele fölöslegesen újra).
A DB-d mérete még 123456 sor esetén is lófütty lesz - és nem kell a betöltéskor sajtreszelőzni azon, hogy mi az új/legutolsó adat...
Nade a cél a hatékonyság lenne.
A nyers adat ~20x annyi, mint a hasznos. Az adatokat be lehet tölteni egy temp táblába, amit utána el is lehet dobni.
Hacsak ezt nem lehet nagyon optimalizáltan megoldani (sík hülye vagyok az sql-hez, illetve a mysql-hez, nem titok, ez a db motorja), mert rémlik olyan, hogy a soronkénti insertnél kb. csak jobb megoldások vannak, akkor ez több kakaót fog elvinni, mint az update (amin valszeg megint lehetne okosítani, hogy ne 700 update legyen, hanem csak egy).
A többi részét nem igazán értem, a vcenter nem kell, de az mminfo olyan, hogy a kliens neve a vcenter neve, ha vmware mentésről van szó. De ez apróság, az utolsó oszlop mindig az, ami nekem kell.
Update: közben rájöttem, miért nem jó az insert. A mentéseket két hétre visszamenőleg kérdezem le (tudom, ne kérdezzem két hétre, de nem minden gépről készül mentés minden nap, van, amiről csak heti, havi egy, és nem lenne jó, ha minden backup policy váltáskor matatni kéne ezt a scriptet is). Nade ha egy gépet decommolunk, akkor az egyik lépés az az, hogy el kell távolítani ebből a listából. Ha ez még automata is lesz, pl. a vcenter alapján, akkor a script visszateszi, mert két hétig mindig lesz egy utolsó mentése.
Hat, ha az elvart uzleti logika bonyolultabb, mint a topicnyitoban leirt kerdes, akkor nem art gondolkozni picit.
Elsosorban fel kell deriteni a kovetelmenyeket, leirni, egyeztetni, jovahagyni, verszerzodest kotni stb. Utana minden valtoztatasi kerelemert kulon lehet szamlazni :)
Ha fix a szerkezet akkor ez is jó lehet ha csak awk játszik:
#!/usr/bin/awk -f
# Az utolso 24 oraban elkeszult mentesek idopecsetjet frissiti, ertelemszeruen modosithato
BEGIN{
yesterday = sysdate() - 3600 * 24
}
$1 >= yesterday {
if ($2 == "vcenter01") print "UPDATE servers set backup=\047" $1 "\047 WHERE hostname=\047" $3 "\047;";
else print "UPDATE servers set backup=\047" $1 "\047 WHERE hostname=\047" $2 "\047;"
}
De ha az bejön lecserélheted a printet system()-re és akkor egyből végre is hajtja.
A mentések között van olyan, ami havonta (sőt, évente, bár az NDMP) egyszer fut le, és van, ami óránként. Mindenképp a legutolsó az érdekes.
Érdekességképp itt van, amit nekem dobott, és ez tetszik is, alighanem erre megyek majd:
You can replace the loop with a single
awk
command to streamline the process. Here is an approach to achieve that:HostName
values into an array.awk
to process theCACHEFILE
for all hostnames at once.awk
to generate the SQL update statements.Here's how you can do it:
Explanation:
BEGIN Block:
hostnames.txt
), where each line contains aHostName
. Store these hostnames in an array.Main Block:
CACHEFILE
, check if the last field ($NF
) is in the array of hostnames.$1
) is greater than the current maximum timestamp for that hostname, update the timestamp for that hostname.END Block:
SQLFILE
.Replace
"hostnames.txt"
with the path to your file containing the list of hostnames. This approach ensures that you process all hostnames and generate the SQL update statements in one go, avoiding the need for a loop.Ez igy eleg gyasz. Ha ennyit tud az LLM, akkor meg a hobbista szintemet sem veszelyezteti :)
Ennyi kell (nem shelyes szintaktikailag):
Lehet, hogy lehet optimalizalni, de nem tudom fejbol a nem letezo tombelem viselkedeset.
Az AWK tombje asszociativ. Folosleges extra koroket futni miatta. Persze, ha tobb hostneved van, mint egen a csillag, akkor kifuthatsz a memoriabol. De akkora halozathoz fizessenek meg hozzaertobb szakembert, mint en :)
Aha, aha, alakul ez. A timestamp mindig az első, a hostname mindig az utolsó, szóval marha könnyű kiválasztani.
Jó ez így, annyira csőlátásom lett a megszokott megoldásaimtól, hogy ilyesmire nem is gondoltam.
Esetleg ez egy "vmi" nevű fájlba:
{ printf ("UPDATE servers set backup='%s' WHERE hostname='%s'\n", $1, $NF )}
Majd
awk -f vmi input.txt
Ja, hogy az utolsó mentés... ok, azt nem láttam.
Kiválasztja a legutolsó mentés sorát a hostname groupban,
a HOSTNAME egyedi ,de lehet bontani, ha jól értem a dolgot .
kapsz egy 746 soros listát.
https://blog.claryel.hu
Beolvasás snq- javaslatával kiiratás, sqllite3-ban
https://blog.claryel.hu
Köszi.
Most már böki a csőrömet, egyre kíváncsibb vagyok, elvileg csöndes péntek lesz, akkor kipróbálom a "natív" sql-t és a preprocesszáltat is, hogy melyik hogy viselkedik.
Lehet, hogy csak nekem kérdéses, de ehhez minek AWK?
Meg lehet oldani extra szintaxis nélkül is, csak tr + cut kell hozzá.
sort, uniq, grep, last segitsegevel is megoldhato, de en az AWK-ot valasztanam.
Hajrá :)
Két okból:
Plusz nem kötelező az awk, lásd a címet, lehet bármi, de ne legyen rosszabb, mint amit én írtam :)
Eredmény:
dbs01 1716491210
web99 1716483542
Szóval akkor egy awk helyett van egy cat (abszolút feleslegesen), egy grep, egy sort, egy tail és egy cut. Jól értem?
Nem értem a kérdésedet :)
Nálam annyi a motiváció, hogy nem szeretem az awk-t, a saját ezoterikus szintaxisával. És már nem is akarom megtanulni, ha kell valami komolyabb, akkor jön a Python.
Én több részre szedném a feladatot.
Időnként jön egy lista, ami pár sorral több mint az előző.
Mivel a (már) felesleges sorok teljesen azonosak az előző állományban lévővel, egy diff pillanatok alatt kidobja a zaj nélküli állományt.
A zaj nélküli állományon pedig már nem ügy végigmenni, hiszen minden sora kelleni fog.
Igen, át lehet definiálni a problémát, de akkor az másik topic lesz.
"Időnként jön egy lista, ami pár sorral több mint az előző."
Ezt azért kétlem, ilyenről én nem tudok. És innentől borul az egész.
Hát akkor lépésről lépésre. A jelenlegi listából összegyűjteni azt a pár százat, az 21 karakter awk-ban (igazából 19, mert nem kell a feltétel köré a zárójel):
awk '( $1 > m[$NF] ) {m[$NF]=$1 } '
Itt kihasználod hogy asszociatívak a tömbök, tehát a mindenkori utolsó mező ( awk-nyelven $NF ) pont jó lesz indexnek, és eltárolod értékként az időbélyeget; valamint kihasználod, hogy nem létező változó értéke az üres sztring, ami aritmetikai műveletben nulla értékű. Így ha még nem volt a gép, akkor 0 lesz a (nem-létező) tömbelem értéke, aminél kb bármilyen timestamp nagyobb. Ha meg már volt ilyen gép, akkor amelyik ts az újabb, az tárolódik.
Hátramarad a DB-nek szóló parancs, ez sokkal hosszabb, és sokat kell szarozni az aposztrófokkal és idézőjelekkel. Itt és most az egyszerűség kedvéért csak kiírom az általad adott UPDATE parancsot gépenként, erre meg pont jó az END mintában egy for ciklus. Azaz fentihez még hozzá kell rakni:
'END { for ( i in m ) { print "UPDATE servers set backup=" m[i] " WHERE hostname=" i " ; " }'
És ezt megeteted azzal az SQL-t tudó akármivel, azaz:
awk '$1 > m[ $NF ] { m[ $NF ] = $1 }
END { for ( i in m ) { print "UPDATE servers set backup=" m[ i ] " WHERE hostname=" i " ; " }' < szövegfájl_nevekkel_és_ts_sel | SQL_parancs
tl;dr
Egy-két mondatban leírnátok, hogy lehet ellopni egy bitcoin-t?
Nagyon köszi!
Az AI vesztésre áll :)
Az awk és az sql, ez már nem lesz őrülten jobb:
real 0m0.010s
user 0m0.009s
sys 0m0.001s
real 0m1.331s
user 0m0.014s
sys 0m0.008s
Ha az SQL parancsban a
set backup='xyz' WHERE hostname='ABC'
részbe tényleg kellenek az aposztrófok (márpedig valszeg igen), akkor azt parancssorban beírni nagyon kacifántos lesz. Igazság szerint baromi sokat nyersz az olvashatósággal, ha egy awk-parancsfájlba írod (mert ott legalább a shell elől nem kell takarni a dolgokat), és awk -f fnév.txt formában indítod.
$ cat fnév.txt
$1 > m[ $NF ] { m[ $NF ] = $1 }
END { for ( i in m ) { print "UPDATE servers set backup='" m[ i ] "' WHERE hostname='" i "' ; " }
Ha jobban megnézed m[ i ] előtt van egy aposztróf-idézőjel, a WHERE előtt egy idézőjel-aposztróf, a hostname után pedig megint egy aposztróf-idézőjel, és i után megint egy idézőjel-aposztróf sorozat. (És ezt most képzeld el shellben begépelni :-) )
tl;dr
Egy-két mondatban leírnátok, hogy lehet ellopni egy bitcoin-t?
Aztán ha új szerver érkezik a mentésbe, akkor annak az adata megy a levesbe az update where feltétele miatt...
Mondjuk MySQL esetén a host oszlopra uniq constraint, és az update helyett valami ilyen insert:
"INSERT INTO mentesek (host, mikor) VALUES ('"i"','"m[i]"') ON DUPLICATE KEY UPDATE mikor='"m[i]"';"
Igen, ki lehet találni még ilyen "ha" dolgokat.
Viszont a tábla rendszeresen frissül a vcenterből. Is. Meg máshonnét is.
Ennek ellenére ez nem annyira rossz ötlet, mint elsőre gondoltam.
Azt hiszem ezt ide akartam inkább:
Update: közben rájöttem, miért nem jó az insert. A mentéseket két hétre visszamenőleg kérdezem le (tudom, ne kérdezzem két hétre, de nem minden gépről készül mentés minden nap, van, amiről csak heti, havi egy, és nem lenne jó, ha minden backup policy váltáskor matatni kéne ezt a scriptet is). Nade ha egy gépet decommolunk, akkor az egyik lépés az az, hogy el kell távolítani ebből a listából. Ha ez még automata is lesz, pl. a vcenter alapján, akkor a script visszateszi, mert két hétig mindig lesz egy utolsó mentése.
Ha az összes új gép még az első mentés előtt _garantáltan_ bekerül ebbe a táblába, akkor jó az update. De ez az infó, hogy ide bekerül _elvileg_minden gép, ez az elején nem volt meg.
Dehogy kerül bele, mi a francnak?
Az esetünkben update kell. Ki lehet találni dolgokat, hogy "igen, de ha", viszont akkor az már másik topic lesz.
ha van egy gép, aminek a neve abcd, és nem kerül bele ebbe a táblába, de van róla mentés, akkor az update ... where gepnev='abcd' egészen pontosan nulla sort fog update-elni, azaz amíg máshonnan nem kerül egy insert into -val a táblába a gép neve, addig a mentést sem fogja benne rögzíteni semmi.
Neked a hostneveket és az utolsó mentés dátuma adatokat is merge-elned kell, ami a már ismert, db-ben lévő host-mentés ideje párosoknak a megfelelő összefésülését jelenti a mentőrendszerből lehúzott listával, amit célszerű berakni egy átmeneti táblába, mert sql-ben sokkal egyszerűbb összefésülni a két adathalmazt.
"ha van egy gép, aminek a neve abcd, és nem kerül bele ebbe a táblába, de van róla mentés, akkor az update ... where gepnev='abcd' egészen pontosan nulla sort fog update-elni, azaz amíg máshonnan nem kerül egy insert into -val a táblába a gép neve, addig a mentést sem fogja benne rögzíteni semmi"
Igen. Ez az elvárt működés.
Tehát a táblázat a "valahonnan ismert gépek utolsó mentésének időpontját" tartalmazza. Oké, ez mondjuk érdekes válogatás, de legyen...
Nem egészen. A táblázat a fontos(*) gépek listáját tartalmazza, és szeretnénk láttatni, hogy van-e, és ha van, akkor mikori a mentés. Sok egyéb dolog mellett.
*) vagy épp nem fontos, de valamilyen szempontok alapján összeválogatott
Hint: \047 Most nem nyitok megint vpn-t, de egész kényelmesen lehet így aposztrófokat írni.
De ha már itt vagyok:
Csak úgy viccből:
Nagy file esetén extra kávé ivásra ad ürügyet, illetve a századik vcenter után törni fog, kivéve ha hexadec az indexelés.
Ó, nem, az előző kolléga úgy oldotta meg, hogy a script minden géppel átballagott ssh-val a management gépre, ott lekérte az adott gépre vonatkozó backupokat (két hétre visszamenőleg), aztán az sort, tail, cut, újra.
Ehhez képest az én megoldásom, hogy egyszer lekéri az összeset, majd abból ügyeskedik, helyből hozott tényleg kb. ezerszeres gyorsulást, és őszintén szólva itt már nekem nem érte meg, hogy tovább matassak vele, viszont idegelt, mert biztos voltam benne, hogy van valami sokkal elegánsabb megoldás is.
Valószínűleg messze ült a kávégéptől, és el kellett látnia a gépet munkával, hogy legyen ideje kávézni.
Ilyenkor az ember muszáj, hogy felesleges ssh -val duzzassza fel a kódot, mert a sleep kislányoknak való.
Nekem hobbim, hogy melóban ilyen bash/awk csatakígyókat rakok össze, mondjuk a fenti nem valami szép, ez csak ilyen első draft. Azt a sed -es vcenter kiszedést egyenesen szégyellem, de egyszerűbb volt begépelni, mint elgondolkodni más módszeren.
Szerintem Zahy awk -s megoldása a legjobb, az egy mestermunka, egyedül csupán abba tudnék belekötni, hogy túl jó. Ezalatt azt értem, hogy annyira jó, hogy már én sem értem, legalábbis eltöprengenék rajta ha komment nélkül kerülne elém, hogy na ez most mi a csudát akar csinálni, mert nem látom benne, hogy hol különbözteti meg a két illetve három részből álló sorokat, és hogy hogy jön ki az állományból a host neve és az időpont. :-)
Én úgy vélem, hogy a scriptek terén a legjobb megoldás az, amit a padtársam is ért, hogy ha hozzá kell nyúlnia, akkor ne kérdezzen bele, mert akkor kiderül, hogy már rég elfelejtettem, hogy azt miért pont úgy írtam. :-)
Itt jon elo a Python olvashatosaga. Az meg, hogy par millisec-cel lassabb (bar awk-hoz kepest lehet, hogy az sem) meg kb. mindegy erre a felhasznalasra. Ez mindenben megirhato, amiben van filekezeles meg asszociativ tomb, es a kod is nagyjabol azonos lesz: beolvasod soronkent, ha ujabb a timestamp a letaroltnal, vagy uj a host, akkor eltarolod, a file vegen meg kiirod az egeszet.
Lehet meg cizellalni, de kb. ennyi:
Szerintem olvashatobb, mint a perl, awk, meg hasonlo szornyusegek - meg ha nem is ismered a konkret szintaxist, akkor is.
Ha picit hosszabb, lehet clean code-ozni, de itt az egesz program ennyi, nem szorakoznek vele.
A strange game. The only winning move is not to play. How about a nice game of chess?
Pájtonban is láttam botrányosan rondán formázott kódot, és perl-ben is nagyon szépet és jól olvashatót. Attól, hogy a pájtonra azt mondják(!) hogy abban csak szépen lehet kódot elkövetni...Nos az akkora bullshit, mint ide Lacháza...
Ja, és ha véletlenül valaki rosszul kopipaste a kódot, és itt-ott elcsúszkálnak a dolgok, akkor nagyjából kuka az egész...
> nem látom benne, hogy hol különbözteti meg a két illetve három részből álló sorokat
Sehogy. Mind a két esetben az utolsó oszlopban van a hostname, ez a $1, $2, $3, ... mintájára a $NF (NF = number of fields, adott sorbeli oszlopok száma, előtte egy $-ral az annyiadik - azaz - utolsó oszlop a sorban)
> nem látom benne, .... és hogy hogy jön ki az állományból a host neve és az időpont. :-)
Az első oszlop pedig az időpont, azaz amikor az első felében azt mondom: m[ $NF ] = $1, akkor az m (machine) nevű tömb $NF nevű eleme - azaz a gépnév az index - értékül kapja a $1-ben levő timestamp-et. Utána az "END { for ( i in m) ..." ciklus az END miatt a feldolgozás után végigmegy a tömb indexein - azaz a gépneveken - ez van az i változóban valami random sorrendben; és kiírja az m[ i ] és az i értékeket. i értéke a gépnév, m[i] a TS.
Azaz ugyanaz, mint amit a python kódban ír a kolléga, de neki fájlokat kell nyitogatni, meg minden csacskaságot, nekem meg gyárilag megcsinálja az awk :-)
tl;dr
Egy-két mondatban leírnátok, hogy lehet ellopni egy bitcoin-t?
Mondjuk annak is jar a tockos, aki olyan filet rak ossze, ahol az opcionalis mezok nem a sorok vegen helyezkednek el.
Szerencse, hogy az AWK gondolt az ilyen elvetemultekre is :)
Ahá, így már világos!
Ez a $NF nagy jóság, és ez a példa gyönyörűen mutatja, hogy milyen szép logika építhető vele.
Marha irigy vagyok most rád, lehet, hogy jobban meg kéne tanulnom az awk -t! :-)
Szerintem egy csomó kódomon javítana, mert nekem szokásom az üzleti logikát bash -ban megírni, és az awk -t csak string műveletekre használni, nagyon ritkán írok bele if -et. Pedig mennyi mindent tud...
Kezd talán ezzel a tamulást:
https://www.gnu.org/software/gawk/manual/
"Share what you know. Learn what you don't."
Igen, nekem (is) nagyon tanulságos, hogy mennyire pici részét használom úgy általában.
,,Én úgy vélem, hogy a scriptek terén a legjobb megoldás az, amit a padtársam is ért, hogy ha hozzá kell nyúlnia, akkor ne kérdezzen bele, mert akkor kiderül, hogy már rég elfelejtettem, hogy azt miért pont úgy írtam. :-)''
Lehet, hogy képzettebb vagy tapasztaltabb padtársakat kellene választanod... ;-)
"Share what you know. Learn what you don't."
Értem, hogy vicc, de rossz. :-D
1) print $1"="$2"\n"
mivel a print a - szóközökkel(és nem vesszővel) elválasztott - paramétereit "összeragasztva" írja ki, ezért írható így, de ez már olvasható is:
print $1 "=" $2 "\n"
2) mivel a print - ha csak le nem tiltod, vagy át nem állítod - automatikusan küld egy ORS-t (alapérték "\n"), ezért minden kiírás után 2 soremelés lesz (azaz szöveg, üres sor, szöveg, üres sor, ... ). Ez nem nagyon látszik, hogy miért kell. Ha ehhez még azt is hozzáteszem, hogy ez az egész bekerül egy shell for ciklusának "lista" részébe, ahol viszont definíció szerint az elválasztó karakterek (szóköz, tabulátor, soremelés!!!!) darabszáma rohadtul nem számít (mert lenyeli őket a shell), én ezt betudom annak, hogy azt hitted, kell a print végén kérni soremelést. De nem, szóval szerintem felesleges.
3) egy cat | tr erősen szószátyár, helyette erőforrás-spórolósabb a "tr < indata.txt" forma. (Más parancsok viszont fájlnév paramétert is elfogadnak, tehát az átirányítás is valószínűleg megspórolható.)
4) Ha jól sejtem, MS-környezetből jön a szöveges fájl, ezért dobod ki a UNIX/Linux alatt felesleges kocsivissza jeleket. Szintén spórolásból érdemes elgondolkodni, hogy ha már úgy is meghívsz egy sed-et, akkor nem olcsóbb-e azzal megcsináltatni ezt is (a tr helyett), ehhez csak annyi kell, hogy a sed kapjon még egy -e 's/\r//g' opciót, és csak ez után jöjjön a -e 's/vcenter' rész.
5) a sort | grep olcsóbb, ha felcseréled őket - ekkor nem kell még a később eldobandó üres sorokat is rendezgetni - viszont ha sed | grep | sort van, akkor megint olcsóbb a grep -v helyett szintén egy plusz sed opcióval megcsináltatni ugyanezt a vcenteres opció után azaz
sed .... -s 's/vcenter...' -e '/^$/d' |
6) mindazonáltal, a grep-nek odaadott regexp közönséges (basic) regexp, felesleges a -E (extended) opció (mármint az lenne, ha maradna)
7) legvégül pedig minek rendezed a sed kimenetét, ha amúgy az x=y formájú elemekől asszociatív tömb x indexe és az ahhoz tartozó y érték lesz, és magával a tömbbel se csinálsz semmi olyasmit, ahol fontos lenne ez a bizonyos sorrend. Tudtommal dokumentáció szerint az asszociatív tömb indexeit *valamilyen* sorrendben kapod vissza, egyáltalán nincs definiálva, hogy abba a sorrendben, ahogy bevitted, de még ha úgy is kapnád, a felhasználásánál kb tök mindegy a sorrend. E miatt én a sort-ot ki is hagynám az egészből.
Szóval én kicsit kevesebb erőforrást használva így írnám:
tl;dr
Egy-két mondatban leírnátok, hogy lehet ellopni egy bitcoin-t?
Hehe, mondom, hogy ez csak egy draft, nem túl sok átgondolással, csak ahogy jött a "mi kell még ide". :-)
Ment a plusz egy!
csak egy megjegyzés:
UPDATE servers set backup='1716491210' WHERE hostname='dbs01';
ha jól értem akkor ez nem valami optimális update, van 18 ezer sorod, és marad 18 ezer a 700 helyett, 17 ezer redundáns sorral.
https://blog.claryel.hu
Ha van mysql , és másik táblába teszed pl, akkor hurrá, tudsz magadnak gyártani egy csomó plusz munkát :-),
pl, nem volt mentés, régi a mentés .
https://blog.claryel.hu
Jo, de a mellékelt update minden sort updatelni fog az meg 17000.
Ez pl 8 sort:
UPDATE servers set backup='1716491210' WHERE hostname='dbs01';
https://blog.claryel.hu
Máshogy gondoltam, igy ok. Viszont az updat-tel mi van, ha űj VM kerül a mentésbe ?
https://blog.claryel.hu
A sima update esetén 0 row lesz érintett az update-ben, és megy a levesbe - fentebb írtam, hogy a hostname oszlop legyen uniq, és a MySQL/MariaDB "INSERT INTO ... ON DUPLICATE KEY UPDATE ..." okosságát használja yool.
https://hup.hu/comment/3064739#comment-3064739
Illetve lehet (sőt, van is) a mentésben sokkal több host, de csak az számít, ami ebben a DB-ben benne van.
Na ez sem volt meg az elején,mint infó... Akkor a sima update jó, legfeljebb lesz n darab olyan, ami nulla sort fog update-elni...
Ez egy nagyon egyszerű programozási feladat, nem adnék rá megoldást, mert biztos vagyok benne, hogy több jó megoldás is van a hozzászólások között, amiket nem olvastam teljesen végig. Bármilyen programozási nyelven ami nem indít soronként új processzt a párezer sor feldolgozása nevetségesen rövid idő lesz, kulcsonként ki kell gyűjteni a maximumot és azt betenni az adatbázisba a végén lehetőleg 1 vagy kevés tranzakcióban. De még az is lehet, hogy ha az eredeti megoldásnál maradsz, csak több update-et csokorba szedve csinálsz csak tranzakciót, már akkor is sokkal gyorsabb lesz.
Ami eszembe jutott róla, hogy volt idén a billion row challenge, ahol hasonló volt a feladat: CSV-szerű szövegfájlból kellett kulcsonként minimumot, maximumot és átlagot számolni (vagy ilyesmi). A győztes megoldás (lásd: https://github.com/gunnarmorling/1brc?tab=readme-ov-file#results ) a 1E9 sort (ez a billion angolul, ugye?) 01.535 másodperc alatt dolgozta fel. És ez a Java megoldás volt, több más programnyelven is készült pályamű, lehet hogy van ami még gyorsabb. Szóval ez legyen a benchmarkod a feladatodra!
Például 10 ezer sorral egyszerűen arányítva a számokat az jön ki, hogy 0,00001535másodperc alatt illene végezni. Érdemes belegondolni, hogy az eredeti megoldással ez a probléma annyira lassú volt, hogy egyáltalán szóba került, hogy optmimalizálni kell. Hányszoros optimálatlanság volt az eredeti megoldásban? Elgondolkodtató.
Az én, egyébként távolról sem optimális megoldásom már eleve úgy ezerszer gyorsabb volt mint az eredeti. És volt, van fontosabb dolog is, mintsem hogy kb. 4 másodpercről levigyem másfélre (ebben az update-k is benne vannak, erre még esetleg szánok időt, hogy egy tranzakció legyen a ~700 helyett).
Viszont, mivel biztos voltam benne hogy van jobb, így feldobtam ide, és sokat tanultam belőle.
Nem merem megkérdezni, hogy mit csinált az eredeti? De muszáj megkérdeznem: mit csinált az eredeti, hogy tudott 1000x lassabb lenni? (még ha az 1000 költői túlzás is, akkor is érdekes.)
Jól gondold meg, mielőtt megnézed... https://hup.hu/comment/3064668#comment-3064668
Így már egész érthető. Van ilyen, hogy valamit megcsinálunk 1 db-ra, aztán egyszerűen csak ismételgetjük gondolkodás nélkül. Ugye SSH kapcsolatból is felépít párezret ahelyett, hogy csak egyet csinálna, így jön ki az elképesztő lassúság.
Szoktam mondani, hogy ha valami csak 1000x lassabb mint lehetne, akkor az már az esetek többségében jó megoldás. Van aki hüledezik erre, de ha mondjuk egy Arduino program egy pint a digitalWrite() paranccsal ír, akkor máris megvan 100x. Pedig az Arduino úgy él a többség fejében, hogy az valami alacsonyszintű programozás. Itt meg volt még egy kb ezerszeres szorzó még egyszer, ami együtt már egy milló, az már kicsit sok lett.
De miért nem egyszerűbb egy subselectből beupdatelni a max(timestamp)-et?
Vagy ez már ósdi megközelítés?(: valamikor 20+ éve láttam sql-t)
https://hup.hu/comment/3064475#comment-3064475
Nyilván volt már bash-megoldás, de csak úgy hobbiból megpróbáltam:
Ha a bash használók hozzászoknának, hogy a declare helyett a bash-ban natívan meglevő, a bash előtt egy évszázaddal a ksh-ban bevezetett typeset parancsot használnák, már eggyel hordozhatóbb lenne a kódjuk :-)
Az első if-ben nem kell az x után a "" :-)
De hogy mi a francnak rendezed te is ....
tl;dr
Egy-két mondatban leírnátok, hogy lehet ellopni egy bitcoin-t?
Miért jo ksh-t használni bash helyett?
Nem azt írta, hanem azt, hogy egy bashism helyett lehet hordozhatóbb megoldást is használni. Egyébként én anno c-shellel kezdtem (Irix), aztán ksh jött (AIX, Solaris) - bash csak jóval később érkezett, de annak is soksok éve már... Ha csak egyszerű dolgok kellenek, akkor (szinte) észre sem veszed a különbséget, ha viszont scriptelni kell, akkor azért igen :-)
Volt olyan környezet, ahova adott verziójú pdksh-t kellett telepíteni, mert az xyz rendszer köré épített scripteknek arra volt szüksége... (Meg egy ócska ls binárisra, ami aztán okozott "érdekes" dolgokat...)
Orom lehet ilyen szarokat mukodokepesen tartani. Egyaltalan nincs ra bash portolva?
A strange game. The only winning move is not to play. How about a nice game of chess?
Ezek a "szarok" azért elég durva rendszerek tudtak lenni. Ami a portolást illeti: sok esetbena céges policy nem engedett mindenféle jött-ment szoftvert feltelepíteni - így bash nem mehetett rájuk (de az emlegetett ksh az van/volt rájuk natívan). És sokszor a hivatalosan megportolt és telepíthető szoftverek sok verzóval voltak lemaradva egy átlag Linux-terjesztésben levőhöz képest.
tl;dr
Egy-két mondatban leírnátok, hogy lehet ellopni egy bitcoin-t?
Van. Amikor ksh-ban írt dolgokkal volt "körberakva" a cucc, akkor valahol RHEL6 környékén tartott a világ. Szóval volt bash, csak épp semmi nem indokolta a bash-ra átírást, mert működött minden, akik azzal foglalkoztak/foglalkoztunk tudtunk vele dolgozni.
Hát pl. mert az az egyetlen, ami képes értelmezni a .sig -emet :-)
De amúgy zellernek igaza van, a hordozhatóságot próbáltam hangsúlyozni.
Hülyét tudok kapni attól, hogy a bash-fejlesztők - nagyjából totál értelmetlenül - olyasmiket is belefejlesztettek, ami kb. csak arra volt jó, hogy könnyen lehessen inkompatibilis kódot írni. Tehát nem arról beszélek, ami náluk lett először (vagy csak náluk van azóta is egyedül), hanem arról, amikor a Ksh-ban már évek (évtizedek) óta meglevő funkciókat implementáltak inkompatibilis módon. Ide tartozik ez a declare / typeset (kb. csak annyit kellett volna, hogy nem a declare formát hangsúlyozni mindenhol, hanem a typeset-et). Ilyen a függvények kezelése: kezdetben vala az x() forma, aztán a ksh-ban bevezették e mellé a function x formát, majd a bash fejlesztők kitalálták azt, hogy akár function x() formában is lehessen írni. (Eredménye, nagyon sok kódban szerepel ez az utóbbi forma.) De ilyen a . parancs C-shellesítése source néven. Vagy éppen a ksh-ban set -A array 1 2 3 formában bevezetett tömbváltozó kezelés helyett bevezetett array=( 1 2 3 ) forma. (De ha a typeset-nél és a .-nál van másik - kompatibilis - forma, akkor pont ezt miért nem vették át ugyanígy, hogy legyen jó mind a 2 szintaxis????) Vagy ahogy a Ksh-ban bevezetett aritmetikai helyettesítés - azaz a $(( 5 * 3 )) formát átvették, de azért mellécsapták (és promótálják, hogy ezt javasolt használni) helyette a $[ 5 * 3 ] formát. De hasonlóan, kb. 25 évvel a ksh után, bash-ban is megjelent a koprocessz kezelés lehetősége - és puff, egy teljesen a ksh-étól eltérő szintaxissal, még csak könnyedén átírni sem lehet. (ksh: p |& és utána read -p / echo -p szolgál a kommunikációra; bash-ban coproc kulcsszó, és egy, a koprocessz nevével megegyező nevű tömbváltozó 0-s és 1-s indexű elemén keresztül elérhető pipe-ok.)
A furcsa, hogy a bash doksikban egyértelműen benne van, hogy az un. POSIX-shell egy implementációjáról van szó. Azt pontosan lehet tudni, hogy a POSI-shell mint olyan pedig az akkor már évek óta létező (ksh88-as verziójú) Korn-shell alapján lett kitalálva (itt-ott módosításokkal) - no akkor ugyan miért nem lehetett a POSIX-shellben nem deklarált - de a ksh-ban létező funkciók újraimplementálásakor tartani a "őssel" a kompatibilitást.
Valószínűleg még lehetne találni pár ilyet - azaz olyat, ahol a "világuralomra törekvés" kivételével nem nagyon találni épelméjű magyarázatot a "miért így"-re.
(Ja, elvetemültebbek elkezdhetnek játszani a yash-sal - ami öndefiníciója szerint: a POSIX-compliant command line shell - persze nem 100%-ig kompatibilis se a ksh-val, se a bash-sal, se a zsh-val.)
tl;dr
Egy-két mondatban leírnátok, hogy lehet ellopni egy bitcoin-t?
Értem, sőt nagyrészt egyet is értek vele, csupán a kérdésem nem erre irányult, hanem azon túl, h a értelmezni tudja a sigedet, miért jó ksh-t használni.
Azért kérdezem, mert ha van egy linux-only rendszer, akkor nem látom, h a portolhatóságnak lenne érdemben hozzáadott értéke.
Van ennek ráadásul egy másik oldala is. Teccik v. nem, a bash kb. monopol helyzetben van. Nem látom, mi előnye származhat bármelyik OS-nek, h ne lehessen alapból telepíteni. Azt szóba sem hozom, h miért nem az a default shell.
Hangsúlyozom, nem arról van szó, h jó vagy nem akár maga a shell, akár a monopol helyzet.
Még jelenleg is léteznek olyan UNIX-szerű operációs rendszerek -- pl. a BSD-k --, amelyeken az alaptelepítésben nincs bash shell.
Ezeknél a rendszerfolyamatokat valami más shell intézi (pl. sh, ksh, csh).
(De még talán Python vagy Perl sincs alapból...)
"Share what you know. Learn what you don't."
afaik a Debian is ilyen, ahogy Zahy is irja.
És akkor mi van? Ott van mellette a bash is telepitve.
Nem értem a BSD v. bármelyik másik problémáját, miért nem tud megoldani ennyit, ha erre van szüksége a userek többségének.
Nem fordítva ülnek ott a lovon?
> Nem értem a BSD v. bármelyik másik problémáját, miért nem tud megoldani ennyit, ha erre van szüksége a userek többségének.
Nem, nincs. A felhasználók (már ha egyáltalán eljutnak parancssorig) kb annyit igényelnek, hogy a 4 kurzormozgató billentyű működjök a parancssor szerkesztése közben. Nem pedig arra, hogy declare -i formában hozzon létre a fejlesztő egy csak egészek tárolására alkalmas változót.
tl;dr
Egy-két mondatban leírnátok, hogy lehet ellopni egy bitcoin-t?
Mármint mi nincs?
Szerintem te azt írtad, h a felhasználók többségének bash-ra (és a bash összes tudására) van szüksége. Erre írtam, hogy szerintem nem.
tl;dr
Egy-két mondatban leírnátok, hogy lehet ellopni egy bitcoin-t?
Azt irtam, miért nem tudják megoldani a bsdk és a tobbi unix like akarmi, h a /bin/bash az alap telepítés része legyen.
Teccik v. nem (nekem sem, de ez van), a bash a defacto script nyelv lett.
Miért, nem tudják? :)
Szerintem nem nem tudják, hanem nem akarják. Erre tudnék számos indokot, de az nettó találgatás lenne, semmi értelme.
Én szimplán sh, csh, ksh utat jártam be, és mivel a Korn-shell kb 99%-ban tudta és nagyjából a mai napig tudja azt amire nekem szükségem van, ezért sosem éreztem késztetést a bash-ra váltásra. Többé-kevésbé felismerem a bashizmeket, viszont mivel eddigi életemben jóval több időt töltöttem el a klasszik UNIX-világban mint Linuxok között, nekem az volt a természetes. Olyasvalakinek, aki Linux-only rendszerben dolgozik, értelemszerűen ez nincs. Viszont mivel még ma is simán bele lehet futni egyéb *X-rendszerbe, szerintem nem hátrány, ha egyszerűen tudatosítjuk azt, hogy "ván máásik". Ráadásul ha egy - hordozhatóság szempontjából - hibás beidegződésre felhívjuk a figyelmet, akkor később esetleg kisebb, vagy épp semennyi probléma nem lesz egy rendszerbeli változástól. (Nyilván a könyöködön jön ki, de attól még valós a hivatkozás arra, amikor a Debian valamiért úgy döntött, hogy dash lesz a default shell, és az első időben más se történt, mint a bashizmek kitakarítása a rendszerscriptekből.) És ahogy légrádi kolléga utalt rá: a BSD-k ugyan elérhetővé teszik a basht is, de a mai napig az sh / csh az amit alapból adnak. FreeBSD-ben az utóbbi években baromi sokat szöszöltek azzal, hogy az eredetileg tényleg inkább a Bourne-shell-re hajazó shell szépen kapja meg a POSIX-beli "extrákat". Ettől persze nem lesz Korn-shell, de erősen közelít. De pl. az OpenBSD ha jól tudom natívan ad egy pdksh-ból forkolt, asszem Mirksh nevű - hopp -, Korn-shell implementációt. És ha az ember megszokja használni ezeket a (Korn-shellből jövő) POSIX extrákat, akkor a végén kiderül, hogy nem is nagyon kell neki bash. Kivéve amikor egy szoftver fejlesztője (feleslegesen) teleszórja a szkriptjét bash-specifikumokkal.
tl;dr
Egy-két mondatban leírnátok, hogy lehet ellopni egy bitcoin-t?
Nekem ez a széllel szembe pisálás. Leírtad, h miért jelentéktelednek el. Persze ez csak egy szög.
Nekem ez az egesz ugy hangzik, mint ha valaki azert hisztizne, hogy miert hasznal valaki a Javas programjaban generikusokat, mert az csak a Java 8-ban (2014) jelent meg, o meg a mainframe-jere a Cobolos vacka melle csak 1.3-at tudott feltakolni, ugyhogy mindenki lesz szives 1.3-as feature set-et hasznalni. (Most a 22 korul jarnak.)
Ja, es kozben mar Win10-en sem jelent problemat egy bash script futtatasa. "hibás beidegződés".. hmm..
Egyebkent P>0 valoszinuseggel egy jobb LLM at tudja konvertalni a bash scriptet a honfoglalaskori megfelelojere, ha valakinek ez a becsipodese.
A strange game. The only winning move is not to play. How about a nice game of chess?
Azt érzem, hogy nem ment át amit mondani akarok,
Nem a a cél, hogy tessen ksh-scripteket (inkább: POSIX-shell nyelven) írni. Nem azt mondom, hogy ne használjuk ki a bash specialitásait akkor, ha annak van értelme. Azt mondom, hogy ha van a bash-ban 2 (3 -4 - ...) - egymással kompatibilis megoldás, akkor hosszú távon több értelme egy csepp odafigyeléssel azt a formáját használni, amit a világon sok más helyen meglevő eszközök is natívan megértenek, nem csak a bash. És a hangsúly azon van, hogy ha van kompatibilis forma, akkor azt használd (nem pedig azon, hogy ha van egy senki más által implementált egyedi dolog, azt ne használd, ha segít megoldani a feladatodat).
Pont erre volt példa a declare. Nyilván magamból indulok ki, de a typeset -i j és a declare -i j között nem látok érdemi különbséget Ránézésre mind a kettő homályos hogy mire is jó, de a második forma egy másik parancsértelmező (ksh) számára is ugyanúgy érthető, nem csak a bash számára - én ezért ezt preferálom, és ennek használatára buzdítok mindenkit. Ha pedig felhasználói szemmel nézem, akkor meg mind a kettőt kenterbe veri az integer j, mert ránézésre látszik, hogy mit takar. Mondjuk ennek meg az a nagy hátránya, hogy csak a ksh érti, de a bash (meg a yash) nem.
Egy lépéssel továbbmenve:
Fent emlegetett .sig -emben nem azért van typeset -i, mert ez hordozható, hanem mert be akartam mutatni a Korn-shell egyedi funkcióját - ott ugyanis lehet alapértelmezett számrendszert is beállítani a (z integer tipusú) változókra, és ezt kihasználva játszottam a számrendszerek közti konverzióval - 8-as és 40-es alapú számrendszereket használva.
Konklúzió: ha az a célom, hogy egy kódot *erőszakosan* hozzákössek egy környezethez, akkor ha integer j -t írok, akkor ettől ksh-hoz lesz kötve, ha meg declare -i j -t, akkor a bash-hoz. Ha pedig az a cél, hogy kevesebb legyen a portolási szopás, akkor azt, hogy typeset -i j.
Kérdés: egy Linux-only környezetben mit izgasson a portolhatóság? Mivel keveseknek van varázsgömbjük, ezért a következő - múltban egyszer vagy többször már megtörtént események alapján - nem kizárható dolgok miatt *nekem* ésszerűnek tűnik a portolást nem igénylő forma:
- olyan rendszer szintű váltás, mint volt a Debian bash-dash. Ha nincs bashizm, csak "POSIXizm", akkor 0 költsége van a váltásnak.
- a Linux-only környezetbe bekerül egy-két cél-BSD (BSD-alapú tűzfal, BSD-re épített NAS pl.), vagy épp egy dinoszaUNIX. Lehet, hogy telepíthető ugyan a bash, de nem biztos hogy célszerű - mondjuk egy tűzfal esetén inkább minimalizáljuk a fent levő szoftvereket, mint bővítsük a listát (csak a kényelem / megszokás lrdekében).
- megváltozó gondolkodás. Sok ember váltott már OS-t, Win - Linux - Win - Linux. Nem nagyon sokan,. de Linux - BSD váltás is történt, és milyen egyszerű is, az évek alatt - odafigyeléssel előállított vackaink vihetők, és semmit nem kell módosítani.
(Funfact: a shellshock nem működött ksh alatt, mert azt a baromságot amit a bash-fejlesztők kiagyaltak az exportált függvények *megvalósíthatósága* érdekében, azt ksh-ban egyszerűen nem implementálták. Holott akit érdekel, megfigyelheti, hogy a ksh93-ban rendszeresen jelennek meg olyan funkciók, amik nincsenek POSIX-ban, de bash-ban igen - és hasznosnak is tűnik.)
tl;dr
Egy-két mondatban leírnátok, hogy lehet ellopni egy bitcoin-t?
Ezek is jó dolgok, de azért érdemes megnézni a script legelső sorát is: oda van írva az elvárt interpreter neve.
Mondjuk beleírhatom én a scriptbe, hogy `export LC_CTYPE=hu_HU.ISO-8859-2` egyes egzotikus (nem-bash) shellek simán rámondhatják, hogy "ja, ez rám nem vonatkozik, én a saját indulásomkor érvényes LC_CTYPE-pal dolgozom tovább". (Saját mérési adatom Aix+ksh)
Speciel a POSIX azt mondja, hogy #!/bin/sh legyen az első sor. Továbbá olyan is előfordul, hogy a script valamiért noexec-es FS-en van, ekkor a ./izémizé tipusú futás - ahol a sheebang számítana - nem működik, ilyenkor az emberek jelentős többsége simán sh ./izémizé formában futtatja. (Nyilván van olyan is, aki bash izémizé - ként) Máris megvan a baj, mert ilyenkor már a sheebang nem számít.
Ha egy interpreter felülbírálja a benne előírt utasításokat, akkor ott már mindenféle egyéb baj is lehet, azt a programot ki kell dobni. :-) Kérdés: ha már AIX, nem lehet, hogy az ott nem ksh, hanem az ő csodás POSIX-shelljük volt (a'la bsh)? Én egyébként az ilyenek miatt 2 dolgot szoktam csinálni (már az anyázáson kívül, mert az kevéssé hatékony) :
- a nyelvi beállításoknál *mindig* a hagyományos szintaxist használom, példádban:
LC_CTYPE=hu_HU.ISO-8859-2
export LC_CTYPE
- és ha véletlenül neki az induláskori érvényes beállítás számít, akkor pedig így futtatom:
$ env LC_CTYPE=hu_HU.ISO-8859-2 ksh izémizé
és igen, sh-szintaxis esetén az "env" kihagyható, de ebben a formában viszont minden értelmes shell megeszi, lehet az Bourne, C, Korn, stb. No így már mindenhol azt látja, hogy magyart szeretnék.
tl;dr
Egy-két mondatban leírnátok, hogy lehet ellopni egy bitcoin-t?
"Kérdés: ha már AIX, nem lehet, hogy az ott nem ksh, hanem az ő csodás POSIX-shelljük volt (a'la bsh)?"
És lassan eljutunk oda, hogy kinek a "ksh"-ja kompatibilisebb az eredetivel, az IBM posix shell, vagy a pdksh, vagy épp a Microsoft-os verzió... :-D
Pontosan. Hiszen amikor valaki újraimplementál egy már létező szoftvert, akkor ritkán szokott sikerülni pontosan ugyanolyanra. (*) Korai unixos életem eléggé meghatározó élménye volt, amikor egy addigra "befejezett" állapotúnak minősített scriptem eljutott abba a fázisba, hogy akkor most mehetnek bele a külvilágnak szóló megjegyzések, hogy egy hét múlva is érthető legyen, És meglepődve konstatáltam, hogy az addig működő program a kommentek elhelyezése után nem hogy nem jól működött, de eleve el se indult valami "Illegal EOF"-jellegű üzenettel. Eltartott egy darabig, mire kiderült, hogy az adott shell egy érdekes hibával rendelkezett: azt ugyan tudta, hogy a # -től a sor végéig levő dolgok nem számítanak, de úgy volt vele, hogy ennél sokkal fontosabb, hogy az aposztrófoknak "párban" kell állniuk, és abba döglött bele, hogy betettem valami ilyen megjegyzést egy sor végére:
blablabla # it's working .....
Viszont nem meglepő módon nem "zártam be" a "nyitó" aposztrófot. Valószínűleg ez se minden shell-implementációban volt / van létező hiba.
(*) nvi: "a bug-to-bug compatible reimplementation to the original Berkeley-vi"
tl;dr
Egy-két mondatban leírnátok, hogy lehet ellopni egy bitcoin-t?
Amúgy ha ennyire zavar, kérdezted már a bash maintainereket, h miért van így és miért nem oldják meg?
off: Igazából 1.5 óta vannak generikusok, 1.8 óta lambdák és új dátumidő osztályok (ezeket a jdbc még nem támogatja 100%-ra, de majd idővel).
Röviden és egyszerűen:
De ruby-ban lényegesen kényelmesebb:
És awk-kal is lehet szebben. Lehet pipe végére tenni, vagy paraméterként is megeszi a fájlnevet.
És ebben a formában még az aposztrofokkal sem kell bajlódni:
Basszus... sok lett a kávé:)
Leráztam a rozsdát a perl emlékeimről.
Sok lett, de miért nem olvasol is közben :-) ? Az awk kódod szerda óta ott van (igaz egyszerűbben ;-) )
Amúgy ez a perl kód mit csinál akkor, amikor 3 tagból áll a sor? Én ugyanis úgy tudom, hogy a regexp illeszkedésnél az a szabály, hogy a sorban előrébb levő szövegre fogja illeszteni a mintát, azaz a timestamp virtualmachinehost virtualmachinename hármasból TS és VMhost illeszkedés lesz e miatt.
tl;dr
Egy-két mondatban leírnátok, hogy lehet ellopni egy bitcoin-t?
Az első n válasz közt nem láttam megoldást, viszont láttam hagy van még millió hozzászólás, ebből hibásan arra következtettem, hogy még mindig nincs válasz. Gondoltam jó fej leszek :)
Az awk kódban tényleg el lehet hagyni a feltétel első felét. Furcsa, hogy először én is úgy írtam meg, de valami miatt nem ment, utána bővítettem. Már kinyomozhatatlan, mit szúrhattam el elsőre.
Perl: mindig a leghosszabb illeszkedést keresi a regexp, így itt az egész sorra illeszkedik, vagyis a $2 értéke VMname lesz mindenképp.
> Perl: mindig a leghosszabb illeszkedést keresi a regexp, így itt az egész sorra illeszkedik, vagyis a $2 értéke VMname lesz mindenképp.
Khmmm.
$ echo alma korte szilva | perl -ne 'print "$&\n" if ( /[a-z]*/ ); '
alma
$
Szóval altalában regexp-ek kapcsán:
1) a legelső (pozíció szerint) találat számít
2) ha azonos pozícióban van több különböző hosszúságú találat, akkor a leghosszabb illeszkedő találat "nyer"
Ha fenti 1) nem lenne, akkor a szilva kéne kiírva legyen.
tl;dr
Egy-két mondatban leírnátok, hogy lehet ellopni egy bitcoin-t?
No rájöttem, hogy mi az amit nem sikerült elég érthetően megfogalmaznom.
Amikor
TS vhost vguest
formájú a sor, akkor szerintem két lehetséges kimenete lesz fenti regexp-nek:
1) az elvárt működés, hogy a nem megjegyzett középső tag - azaz a ".* " begyűjti az első szóköztől az utolsóig plusz vhost sztringet, és a végén álló megjegyzett tagnak - azaz a "(.+)" - marad $2-be gyűjtendőnek a vguest. Ekkor jók vagyunk.
2) nem elvárt működés, de szerintem semmi nem zárja ki, hogy a ".*" (szóköz nélkül) nulla hosszúságú illeszkedést produkál (ilyen van), azaz megmarad a " vhost vguest", amit begyűjt a " (.+)" minta (amiben ott a szóköz az elején), azaz $2 a bevezető szóköz nélkül megkapja a "vhost vguest" sztringet,ami nem annyira jó eredmény.
Azt nem tudom, hogy ez valahol explicit le van-e írva, hogy a perlben ez sosem fordulhat elő, vagy csak a gyakorlati tapasztalatokból indulunk ki. Mert ha utóbbi, azaz sima UB (undefined behaviour - nem definiált viselkedés), akkor én nem építenék rá. Helyette szimplán csak annyit kell tenni, hogy ahogy az első megjegyzett mintában kizárjuk a szóközt, ugyanúgy a regexp végén is:
> if ( /([^ ]+).* ([^ ]+)/
tl;dr
Egy-két mondatban leírnátok, hogy lehet ellopni egy bitcoin-t?