ugrás a tartalomhoz

Kommunikáció web szerver és démon között?

mind1 valami név · 2018. Okt. 10. (Sze), 09.45
Ha jár itt élő ember, aki tudna tippet adni, hogy hogyan érdemes megvalósítani a kommunikációt web szerver és a háttérben futó démon processz között...

Szeretném elkerülni az ágyúval verébre effektust, viszont esélyes, hogy egy pythonban írt, háttérben futó processznek kellene társalognia egy PHP/perl/nodejs/etc. nyelven írt, GUI-t előállító web szerveren futó programmal.
Ezt hogy lenne célszerű megoldani?
Pontosabban: milyen eszközzel? IPC message queue alkalmas ilyesmire?
Előfordulhat, hogy nagyobb mennyiségű (több megabájt) adatnak kellene mozogni a két processz között, adatbázist meg mellőzném, ha lehet.
(most konkrétan a mindenféle logokból akarok előállítani ezt-azt, de ezekhez a logokhoz nem akarok jogot adni a web szervernek, ezért kellene a démon)
 
1

socket

Hidvégi Gábor · 2018. Okt. 10. (Sze), 09.56
unix socket, ha egy gépen van.
2

Ez nagyon feladat függő. Ha

inf · 2018. Okt. 10. (Sze), 10.06
Ez nagyon feladat függő. Ha csak olvasni akarsz a deamonról egy-egy kérésnél, akkor egy REST API elég lenne neki, vagy esetleg socket, ahogy fentebb írták. Ha pusholni akarsz róla, és muszáj, hogy minden üzenet eljusson a deamonról a webszerverhez, akkor kellhet a message queue.
3

Kicsit továbbgondoltam a

mind1 valami név · 2018. Okt. 10. (Sze), 11.56
Kicsit továbbgondoltam a dolgot és azt hiszem, a korrekt megvalósítás nem fog menni. Nem gondoltam bele, hogy a web szerver több kérést is kiszolgálhat párhuzamosan és ezeket a kérés-válasz párokat összhangba hozni... hát nem egyszerű. :(

Köszi mindkettőtöknek.

Update: legnagyobb gond, hogy már azt sem tudom, milyen irományt keresgéljek, ami alapján legalább el tudnék indulni :((
18

Nem bonyolult az annyira,

BlaZe · 2018. Okt. 16. (K), 00.17
Nem bonyolult az annyira, ezért jó egy (valamilyen) queuet rakni a kettő közé. Akkor egymástól függetlenül tudod hangolni a webszervert és a backend rendszert. Ez lehet egy MQ, vagy a backend rendszered is implementálhat egy egyszerű queuet. A lényeg, hogy aszinkron legyen és tudd párosítani a kéréseket a válaszokkal.

Az eddig leírtak alapján egy MQ bróker túlzás lehet, hacsak nem akarod kihasználni valamelyik kész featuret (pl durability, STOMP protocol support, filtering, ... ), vagy pl nincs kedved minimálban se megírni. De szvsz egy egyszerű ZeroMQ-val nekiugrani ez bőven elég, és a backenden meg tudsz valósítani egy in-memory queuet, ami az aszinkronitást hivatott megoldani. A ZeroMQ a nevével ellentétben egy socket lib és nem egy MOM, viszont nagyszerűen elfedi a TCP socket, unix socket, shared memory stb különbségeit. Vagyis ha már úgyis gépen belül vagy, nem kell átrángatnod mindent a network stacken, választhatsz SHM-et pl. Viszont ha ki akarod tenni a frontendet másik gépre, egész egyszerűen megvalósítható. Hogy efölé milyen protocolt teszel az lehet kérdés, de az eddig leírtak alapján a protocol nem tűnik bonyolult feladatnak. Nincs se verzió kompatibilitás, se egyebek. Lehet egy egyszerű szöveges protocol, vagy egy szintén egyszerű bináris.

Ami viszont érdekes lehet, ha nagy tartalmat szeretnél megosztani a két process között. Itt bonyolódhat a protocol, ha pl egy lapozgatást szeretnél megvalósítani. Ezesetben (ha gépen belül vagy) a válaszokban küldhetsz egy file nevet, amibe beleírod magát a választ. Ezt meg lehet csinálni elég gyorsra is, ha esetleg arra van szükség. A lényeg, hogy ne kelljen az egész választ a web process memóriájába behúzni, ha az nagy.
19

Akkor most képzeld el a köv.

mind1 valami név · 2018. Okt. 16. (K), 13.09
Akkor most képzeld el a köv. szitut: van három, egysoros shell szkript, pipe-ban összefogva egy grep/sed/perl/stb. program felparaméterezve, amik megmutatnak haszontalan, de a saját hülyeségemet kielégítőt infókat (hány csomagot dobott el a router óránként, milyen IP címekről jöttek portscanek, milyen, a szokásostól eltérő sorok jelennek meg a router logjában)

Erre a feladatra akartam egy webes interface-t gyártani, kulturáltan leprogramozva, nem úgy, hogy egy PHP szkript system() fv.-ből hívja mindezt. Szerinted ér ez annyit, hogy hetekig, hónapokig tökölődjek rajta, hogy hogyan konfiguráljam csak a szervereket, majd írjam meg a programokat? :))
Mert ha lenne bármi értelme az egésznek, akkor persze, megérné, de ez csak egy hirtelen jött hülyeség, amit már bánom, hogy felvetettem itt... (egy nyomorult, statikus HTML lapot nem tudok már összerakni, annyira elfelejtettem mindent)
20

Nem ér annyit, de ezt eddig

BlaZe · 2018. Okt. 16. (K), 15.02
Nem ér annyit, de ezt eddig egyrészt nem írtad, másrészt neked kell tudni :)

Amúgy amit én mondtam, az kb a két program kommunikál egy socketen kategória. Inkább pár este munkája, mint hónapoké, és akkor már mindent megcsináltál hozzá.

De ha csak otthon te magadnak nyomkodnád, akkor egy system() is bőven jó szerintem...
4

socket

Hidvégi Gábor · 2018. Okt. 10. (Sze), 13.34
Nézd át ezt, mondjuk épp C-ben írták, de megértheted belőle a logikát, egy bejövő kérést forkol, feldolgoz, majd visszaad valamit, neked pont erre van szükséged.
5

Látatlanba: ráül egy

mind1 valami név · 2018. Okt. 10. (Sze), 15.24
Látatlanba: ráül egy portra/socketre, ezen jön egy kérés, arra "azonnal" a válasz, hogy nyitottam csak neked egy socketet, folytassuk ott, előtte/közben létrehoz egy új processzt ami a válaszban küldött socketen hallgatózik?

Köszi, megnézem, talán olvasni még tudom a C-t. :)
6

Megnéztem és vagy én nem

mind1 valami név · 2018. Okt. 10. (Sze), 18.29
Megnéztem és vagy én nem tudom értelmezni a kódot vagy ez mást csinál, mint amin én problémázok.
Mintha ez egy nagyon primitív web szerver akarna lenni.
Nekem meg (itt és most) nem a web szerver működése okoz gondot önmagában, hanem az alatta futó PHP vagy más nyelven írt program kommunikációja egy azonos gépen futó démonnal. Hogy a démon hogyan tudja kezelni, egymástól elválasztani az esetleg párhuzamosan beeső több, eltérő kérést.
Illetve némileg felélesztve pár maradék agysejtet, halvány elképzelésem van róla már (lásd korábbi reakcióm), csak ez vélhetőleg bonyolultabb, mint amit az egész feladvány ér.
(arról már rég letettem, hogy munkát keressek, szóval ez már tényleg csak játék)
7

Ha nem túl speciális a

inf · 2018. Okt. 10. (Sze), 20.27
Ha nem túl speciális a feladat, akkor sok esetben úgy szokták megoldani, hogy a daemon egy REST/SOAP/CRUD webszolgáltatást nyújt, ami nincs kifele nyitva, csak a webszerver látja. Aztán azon keresztül végez műveleteket. A socket meg message queue akkor kell, ha a webszerver, esetleg onnan a kliensek fele akarja nyomni az adatot a daemon úgy, hogy kb. realtime a dolog és a polling nem jöhet szóba. Persze lehet, hogy én látom rosszul.

Nekem nem hangzik túl értelmesen, amit írsz, hogy a webszerver átadja a kéréseket a daemonnak, de ha nem mondasz többet a problémáról, akkor én kb. ennyit tudtam segíteni.
8

Egyszerűen az van, hogy web

mind1 valami név · 2018. Okt. 10. (Sze), 21.14
Egyszerűen az van, hogy web szervernek nem adunk jogot olyasmire, amihez root/admin jog kellene. Mert nem illik. Mert ki tudja, hány helyen lyukas. Mert ... stb. :)
Ergo marad az, hogy fut a háttérben valami, aminek megvan a szükséges jogosultsága (pl. jelen esetben bizonyos logfájlok olvasására való jog) és ő végzi el a tényleges tennivalókat, míg az apache/nginx/stb. alatt futó akármilyen szkriptek csak a GUI-t biztosítják. Kb. mintha egy adatbáziskezelővel társalogna egy PHP program...
9

Teljesen mindegy, hogy mit

inf · 2018. Okt. 11. (Cs), 21.06
Teljesen mindegy, hogy mit csinálsz, valamilyen lokálisan elérhető szerver kelleni fog a daemonra is ahhoz, hogy a webszervered kérést tudjon indítani felé. Most hogy ez socket szerver vagy webszerver vagy bármi egyéb, az szinte mindegy. Nem jellemző, hogy ezeken keresztül törnék fel a gépet, inkább a PHP vagy egyéb scripteken keresztül szokás, mert azok hemzsegni szoktak a biztonsági résektől. Elvileg a root tud adni a jogaiból valamennyit más felhasználóknak, szóval szerintem nem fog neked root jogosultság kelleni a daemonra sem. Azt hiszem janoszen írt régebben egy cikket a docker alapjairól, abban elég jól le vannak ezek írva, keress utána!
10

Pusztán arról van szó, hogy

mind1 valami név · 2018. Okt. 12. (P), 12.00
Pusztán arról van szó, hogy közvetlenül a web szerver (az őt futtató user) ne kapjon extra jogot a rendszeren, mert ha valahol feltörik a webszervert, akkor annak a jogosultságait is tudják használni. Ha teszem azt, valami admin feladat miatt írás jog kell neki a kofig fájlokra, attól kezdve már nagyon gázos a dolog.
Az a dockeres dolog meg szép és jó (feltételezem, a "capabilities" címszó alatt futó dologra gondolsz), de ahogy a setuid bit beállítása, úgy ezek is csak bináris fájlra adhatóak, szkriptekre nem annyira és ha jól rémlik, olyan sincs, amivel usernek lehet extra jogot adni ezen az úton, bár ebben már nem vagyok biztos.
11

Értettem elsőre is. A bináris

inf · 2018. Okt. 12. (P), 13.28
Értettem elsőre is. A bináris fájl a php.exe gondolom. Felteszel két standalone-t, aztán az egyiknek adsz jogkört, a másikat meg a webszerver használja.
12

Az a gond, hogy ekkor még

mind1 valami név · 2018. Okt. 12. (P), 16.32
Az a gond, hogy ekkor még mindig a webszerveren belül vagyunk szerintem. Szóval amit meg tudok etetni a webszerverrel, az kihasználhatja az emelt jogokat.
Ha külön processz, más user alól megy és nem küldök neki közvetlenül felhasznált adatot (pl. fájlnevet), hanem csak (nagyon leegyszerűsítve) küldök MQ-n két számot, az egyik egy fájl sorszáma, a másik a vele végzendő műveleté, majd az elvégzett művelet eredményét valami hasonló módon visszaküldöm, akkor azért nagyjából védett vagyok az ilyen trükkökkel szemben.
Nem tudom érthetőbben...
13

Ja, működőképes megoldás,

inf · 2018. Okt. 13. (Szo), 01.19
Ja, működőképes megoldás, amit írsz. Egyébként a PHP-nek van beépített webszervere, amit használhatsz a daemonodban: link, vagy esetleg reactphp-vel is nekifuthatsz: , szóval nem szükséges Apache vagy nginx hozzá.

Az MQ-t én soknak érzem erre. link Az elvileg arra való, ha üzenetet akarsz küldeni egyik alkalmazásból a másikba A -> B, és azt szeretnéd, hogy biztosan megérkezzen. Pl ha B éppen elszállt, és várni kell, hogy újrainduljon, akkor az MQ megjegyzi az üzenetet, és vár, amíg B újraindul, és csak utána adja át neki. Ami neked kell az inkább kérés - válasz alapú (bár sok, ha nem az összes MQ implementálja a REQREP mintát is), amit meg kiszolgálhat egy socket server is, de ha nem valami olyasmit akarsz, ami realtime írja a fájl változásokat, akkor egy web server is teljesen jó neki, és a daemon egy webservice kellene, hogy legyen. Aztán persze lehet, hogy csak én idegenkedem egy kicsit az MQ-któl, mert inkább webservice-ekben gondolkodom, és más mást mondana.
14

MQ-ból sokféle van, sokféle

mind1 valami név · 2018. Okt. 13. (Szo), 07.43
MQ-ból sokféle van, sokféle működéssel.
Az IPC-hez tartozó MQ a doksi szerint rövid üzenetek váltására való, amennyire utánanéztem, talán pár kB a max. üzenetméret és úgy értettem (lehet, rosszul), hogy egy rebootot biztosan nem élnek túl a queue-ban lévő üzenetek.
Valami hasonló mechanizmusa van a pythonnak is, de úgy tudom, az csak a saját subprocesszekkel tud kommunikálni és a processz megszűnésekor elvész a tartalma.
Az IBM Websphere(??? MQSeries, de azt hiszem, a Websphere része volt) amivel 10+ éve dolgom volt, az meg szinte önálló szervert igényelt, egy spec DB2 adatbázismotor volt benne és még egy atomcsapást is túlélt volna a benne lévő üzenet, ami akár sok MB-os is lehetett volna, komplett fájlokat küldözgettünk rajta :D (vagy keverem aTivoli/TSM alapú archiváló rendszerrel... inkább abban lehetett a db2, ehhez meg külön kellett egy külső a RDBMS)


Hát kb. ennyi amire felszínesen emlékszem... (nekem nem létszükséglet a maradó állapot, de minél többet piszkálgatom a témát... annál több csontváz potyog ki az emlékeimet őrző, poros kisszekrényből ;) )
15

Amiket olvastam róla, az

inf · 2018. Okt. 13. (Szo), 22.36
Amiket olvastam róla, az alapján szokott lenni persistent mode minden MQ-ban, de külön be kell állítani az adott üzenetre. A maradó állapot megoldható webservice-ekkel is, ha a szervertől indítasz kérést a daemon felé, és a daemon válaszol. Ha a daemon indítja el az üzenet küldést, pl történik valamilyen esemény, mondjuk változik a log, akkor ha realtime kell, akkor socket kapcsolat vagy MQ kell, amiről tud pusholni eventet a daemon a webszervernek. Ha nem kell realtime, és elég mondjuk 10 másodpercenként, vagy akár másodpercenként kezelni az eseményeket, és nem számít annyira, hogy tekeri a processzort, tehát pl nem egy arduinon fut, akkor megoldható úgy is, hogy csinálsz egy webservice-et a daemon-ra, ami tárolja az eseményeket, aztán if-modified-since vagy etag header-el, esetleg "?since={timestamp}" query-vel elkéred, hogy mi változott az utolsó lekérés óta, aztán ha van új esemény, akkor kezeled a webserveren. Ezt polling-nak hívják amúgy. Létezik long polling is, az már közeli a realtime-hoz, annál nyitva marad a HTTP kapcsolat hosszabb ideig, és vár az új eseményekre. Vannak még más technikák is erre, de lényegtelen kb. Ami neked kell, az szerintem továbbra is egy sima webservice, amitől elkéred a logot, és amit másik - magasabb jogkörű - felhasználó indít, mint a webszervert. MQ-val ugyanígy meg tudod oldani, de kicsivel bonyolultabb lesz a végeredmény, mert a daemon mellett fel kell lőni az MQ-t is hozzá. Igazából ha ugyanúgy CGI-t akarsz a PHP-ben vagy más nyelven írt daemon helyett, mint ahogy a szerveren csinálod, akkor meg valszeg kelleni fog egy másik apache vagy nginx, aminek mások a jogkörei, beállításai, stb. De ebben a részében nem vagyok annyira otthon, mint a többiek. Na részemről kb. ennyi, többet most nem nagyon tudok hozzátenni. Jó szórakozást vele!
16

Szerver

Hidvégi Gábor · 2018. Okt. 15. (H), 11.38
Igen, ez épp egy webszerver kódja, de ezzel arra szerettem volna példát hozni, hogy a te háttérben futó magas jogosultságú szolgáltatásod futhatna ilyen módon, amihez a webszerverről csatlakoznál valamilyen porton keresztül.
17

Ja, akkor bocs,

mind1 valami név · 2018. Okt. 15. (H), 11.58
Ja, akkor bocs, félreértettelek. De úgy fest, már mindegy, mert vagy én épültem le annyira agyilag, hogy a primitív dolgokat sem fogom már fel, vagy annyira elcsesződött ez a nyomorult világ, hogy már nem képesek normális, valóban használható doksikat gyártani a szoftverekhez (legalábbis az OSS kategóriában). Vagy a kettő együtt. :)
A lényeg, hogy elég hamar feladtam a dolgot.
22

Már sokadjára futok neki,

mind1 valami név · 2018. Okt. 17. (Sze), 03.47
Már sokadjára futok neki, hogy megértsem, de nem áll össze a kép: mi van, ha párhuzamosan beesik 50 kérés? Nem látom, hogy hol választja szét azt, hogy az egyes bejövő kérésekre pontosan azt a választ küldje, amire a kérés vonatkozott. Vagy nem értem a C-ben leírt socket kezelést... (sajnos debuggolni nem tudom, hogy hátha abból megértem)
Ha felébredtem, előtúrom újra a libc(?) doksiját és átnézem, miket ír az ilyenekről, mind bind, accept, mert egyelőre totál érthetetlen.
37

Egyszerű

Hidvégi Gábor · 2018. Okt. 19. (P), 10.48
A program sorosan fut, ezért a párhuzamosság miatt nem kell félned.

A következő történik: az inicializáció után a program ráül egy socketre, és nézi a bejövő kéréseket. Ezt a részt egy for ciklus kezeli, azaz, ha véletlenül egyszerre több esik be, akkor a többi vár, amíg a sorban az elsőt lekezeled.

socketfd = accept(listenfd, (struct sockaddr *) &cli_addr, &length);


Ez az első parancs, létrehoz egy fájlleíró erőforrást, ezen fog a kérés bejönni karakterlánc formában (GET akarmi).

pid = fork();


Ez után forkolunk, ami azt csinálja, hogy létrehoz egy új processzt, és lemásolja bele a fork() hívás előtti processz memóriastruktúráját (ez lehet, hogy pongyola megfogalmazás). Tehát az új szálban lesz egy socketfd nevű változó, amit épp az előbb hoztunk létre, és benne van a kérés.

/* ha a pid értéke 0, akkor a lemásolt processzben vagyunk, azaz elindul a feldolgozás, átadjuk neki a fájlleírót */
if (pid == 0) {
  close(listenfd);
  feldolgoz(socketfd);
}
/* ha a pid nem nulla, akkor a szülő processzben vagyunk, és lezárjuk a fájlleírót */
else {
  close(socketfd);
}


És ezzel vége is a for ciklus belső részének, kezdjük újra az egészet.

Nézzük meg a feldolgozó függvényt:

void
feldolgoz(_socketfd) {
  long hossz;
  static char puffer[501];

  hossz = read(_socketfd, puffer, 500);
  /*
  ...
  itt elvégzünk mindenféle ellenőrzéseket
  */
  if (strncmp(puffer, "GET akarmi", 10) == 0) {
    /* az a kérés, hogy GET akarmi */
    /* ... */
    write(_socketfd, "Ez a valaszom", 14);
  }

  sleep(1);
  close(_socketfd);
  _exit(1);
}


Beolvassuk, amit a fájlleíróban kaptunk, megnézzük a tartalmát, ha GET akarmi van benne, akkor "Ez a valaszom"-ot írunk ki. Végül lezárjuk a fájlleírót, majd pedig forkolt processzből az _exit(1);-gyel lépünk ki.
40

Mellékszál 1. A fork()

mind1 valami név · 2018. Okt. 19. (P), 16.54
Mellékszál 1. A fork() működését, pontosabban annak értelmét sosem tudtam felfogni: miért jó az, hogy minden duplikálódik, mikor egy a főprogramtól független subprocesszt akarok futtatni?
Mellékszál 2. Az _exit miért 1-gyel lép ki? Az tudtommal hibára utal.

A többi... most esett le, hogy amit én manuálisan képzeltem elkövetni (t.i., hogy a szerver szerez egy új socketet/portot és azt visszajuttatja a kliensnek, hogy "ezen pofázz drágám"), azt valójában az accept/connect páros intézi a háttérben, nekem nem kell vele foglalkoznom.
Csak ehhez az kellett, hogy legyen energiám kipróbálni :)
(ugyanis a python doksi azt javasolja, hogy a socket modult felejtsem el, használjam helyette a serversocket vagy socketserver modult, ami valamivel magasabb szinten intézi a dolgokat)
Tankjú!
44

Ez a fork() számomra egyre

mind1 valami név · 2018. Okt. 21. (V), 20.43
Ez a fork() számomra egyre gázosabb...
Rég volt, így mára már elfelejtettem, hogy ha a fork() után a gyerek processz kiszáll, akkor ottmarad mint zombi. ("defunct") És egészen addig így marad, míg a szülő ki nem ad egy wait() hívást. Így viszont már elég komoly macera normálisan megírni egy ilyen kódot, ahogy elnézem, mert a wait-nek akkor kellene lefutnia, amikor valóban befejeződik a gyerek, de ahhoz a gyerek és a szülő közé kellene valami kommunikáció...
Hm.

Update: ja, hogy nem sys.exit, hanem os._exit kell a child esetében... na ezt még kipróbálom.
Update2: aham, így is ottmarad az összes child "defunct" jelzéssel...
Update3: ... mert kell még bele egy "signal.signal(signal.SIGCHLD, signal.SIG_IGN)" parancs is, így nem marad ott zombiként a child...
Update4: valamiért a leírások/tutorialok többsége egy szót sem szól a defunct processzek megjelenéséről, sem az n+1 korlátról, amik egy forkolt processzre vonatkoznak. Viszont találtam valami érdekesnek tűnő posztot: https://stackoverflow.com/questions/4160935/how-to-use-fork-in-unix-why-not-something-of-the-form-forkpointertofunctiont
Ebből az is kiderült, hogy a fork egy nagyon régi dolog, sokkal régebbi, mint a multithreading és hasonlók, így érthetővé válik néhány apróság...
43

Kapcsolódva...

mind1 valami név · 2018. Okt. 20. (Szo), 11.38
23

User story (hiányzik)

Pepita · 2018. Okt. 17. (Sze), 16.07
"Látogatóként azt szeretném, ha a weboldalam meg tudna mutatni egyes fájlok tartalmából részeket, amikhez viszont csak egy másik, háttérben futó alkalmazás férhet hozzá."

Ha ez igaz, akkor leginkább szerintem is REST API.

Ha nem, akkor próbáld meg a példámhoz hasonlóan megfogalmazni / konkretizálni a feladatot.

Erre a kérdésre:
hogyan érdemes megvalósítani a kommunikációt web szerver és a háttérben futó démon processz között
nemigazán tudok használható választ adni, nem eléggé definiált a cél.
24

Asszem, valahol itt korábban

mind1 valami név · 2018. Okt. 17. (Sze), 17.20
Asszem, valahol itt korábban leírtam: eredetileg olyan logokban kellett volna turkálni és abból a kapott paramétereknek megfelelő sorokat visszaküldeni, amit alapjáraton csak a root láthat.
Később meg esetleg olyasmit is elkövettem volna, hogy a mindenféle konfig fájlok szerkesztését is webes felületről intézni, ha összejön.

De elég hamar rájöttem, hogy ez... hogy úgy mondjam, túl nagy falat még úgy is, hogy csak a saját szórakoztatásomra akartam.

ui: de már ixedszer nézem át a wikipédián a REST cikket és ránézésre az jóval bonyolultabbnak tűnik, mint ami nekem kellett volna az eredeti elképzeléshez. (pl. kliens->szerver üzenet: kérem a portscan-ek listáját, szerver megcsócsálja a logot és visszaküld egy listát a portscannel próbálkozó IP-kről a kliensnek - ehhez képest a REST egy elég komoly dolog, mindenféle megkötésekkel)
25

Irtam pár bejegyzést annak

inf · 2018. Okt. 17. (Sze), 20.38
Irtam pár bejegyzést annak idején REST-ről, de ha nem ismered, akkor sok idő, mire beletanulsz. link Talán így nulláról elsőre egyszerűbb egy sima CRUD API, aminél beégeted a kliensbe az URI-ket, ha csak néhány fájlról van szó. A lapozás megoldható range header-el vagy query-ben átadott paraméterekkel. A jogosultság kezelésnél talán elég annyi, hogy csak helyi IP-ről érhető el. Ha nem, akkor azon felül még HTTPS meg egy API key is elférne benne. Később esetleg ha érdekel a REST, akkor megpróbálhatsz megfelelni a hypermedia meg a self-descriptive message constraint-eknek. Az első nagyjából annyit takar, hogy linkeket adsz meg, aztán a kliensed a linkeket követi, ahelyett, hogy valami beégetett URI-vel dolgozna. A második arról szól, hogy csinálsz egy saját RDF vocab-ot, amit hozzákötsz az elküldött adathoz, mint metaadatot, aztán ennek a vocab-nak a kulcsszavai alapján dolgozod fel az üzeneteket, azonosítod be a linkeket, nem a property nevek és az URI template alapján. Nyilván ez elég komplikált tud lenni, és ebben az esetben inkább csak tanulás célzattal van értelme megcsinálni, mert csak egy kliensed van, és nem fog sűrűn változni később sem a kódod. Fapados alternatíva még erre, ha definiálsz egy vendor specific MIME type-ot, aztán ott megmondod, hogy melyik property mit jelent, és ezt a MIME type-ot verziózod, ha változtatni akarsz. Általában ez utóbbit szokták csinálni, mert az RDF-hez kevesen értenek, pedig nem annyira bonyolult. Elvileg. Bár én sem értem, főleg nem JSON-LD syntax-al. :D
26

Csak egy idézet

mind1 valami név · 2018. Okt. 17. (Sze), 20.51
Csak egy idézet tőled:
"Kellett pár hónap, mire rájöttem, hogy ez nem járható út, mert ezeknek az írásoknak szinte 100%-a teljesen használhatatlan, a készítőik pedig valószínűleg egyformán képzetlenek ezen a téren és vakok közt a félszemű a király alapon egymást oktatják."

:D
És akkor ilyenekre biztattok :))
(Fielding írásába belenéztem már korábban és sírva menekültem, mikor megláttam a méretét ;) )
27

Abból elég csak a REST-es

inf · 2018. Okt. 17. (Sze), 21.02
Abból elég csak a REST-es fejezetet elolvasni. A többi lényegtelen. Az olyan 10-15 oldal lehet, max 30, nem emlékszem már. SO-n a többsége szemét a REST-es válaszoknak, ha esetleg belevágsz és kérdésed van, akkor inkább ide írj.
28

Troll on...

mind1 valami név · 2018. Okt. 17. (Sze), 21.48
Ha már a webprog.hu nem műxik ;)

Most ennél sokkal primitívebb dologgal szopatom magam.
Van ez a három egysorosom, amit próbálnék több sorosra, de a jelenleginél kulturáltabbra átírni.
Miután tőlem kitelik, hogy szóközt hagyok egy fájl nevében... hogy hozzam össze, hogy ha "-" jel van a szkript paraméterei közt, az a stdin legyen, ha több név van felsorolva, azt mindet tolja bele a mögötte álló filter/feldolgozó script stdin-jébe és működjön akkor is, ha szóköz van a kapott fájlnevek némelyikében? (a kérdés költői, többé-kevésbé már megvan, csak próbálom demonstrálni, mennyire leépültem az elmúlt pár évben. :( )
29

A vége az lesz, hogy

inf · 2018. Okt. 17. (Sze), 22.24
A vége az lesz, hogy felcseszem magam, aztán megírom node-ban és kiteszem a Herokura vagy valami olcsó VPS-re.

Ez most bash-re vonatkozik? Általában idézőjelbe szokás tenni, ha space van az útvonalban.
30

Ha egy sima idézőjel elég

mind1 valami név · 2018. Okt. 17. (Sze), 23.20
Ha egy sima idézőjel elég lett volna... :D
https://github.com/haa-zee/shell-scripts
A log-common.sh tartalmazza a lényeg egyik felét és mondjuk a dropped_packets_per_hours.sh az utolsó pipe-ig a másikat.
Ez utóbbin még finomítok, csak most nem volt lelkierőm még függvényezni is, épp elég megrázó élmény a bash tömbkezelése :D
Valami kavarás, esetleg bug van a bash-ben, mikor a $@ változóból kiadja az egyes paramétereket. Ha csak simán végigmegyek rajta, akkor a szóközöknél kettévágja a nevet, mintha két külön paraméter lenne - legalábbis most ezt csinálta - ezért a horrorisztikus kód.
Majd ha felkeltem, újra átnézem, hogy miért is csinál egy "bb bb" névből két bb-t ahelyett, hogy "bb bb"-ként kezelné tovább. Lehet, hogy a for-nál csesztem el valamit, de ezt már csak holnap...
31

Hát sok sikert! :-) Én a

inf · 2018. Okt. 18. (Cs), 01.24
Hát sok sikert! :-) Én a bash-t igyekszem minimálra szorítani, és csak szökő évente egyszer ha komolyabban használom.

Egyébként majd talán jövőre megpróbálkozok olyan node projekttel, ami kiváltja teljesen a bash scripteket. Most is van shelljs meg hasonlók, de az alacsony szintű. Valami olyat szeretnék, ami végigmegy a létező bash parancsokon, meghívja mindegyikre a helpet, aztán kinyeri belőlük a teljes paraméter listát. Aztán js-ből valami ilyesmivel, hogy `await(shell.cmd({param1: "a", param2: "b"})`, stb. tudom csinálni ahelyett, hogy bash scriptet kellene írnom a maga nyakatekert módján. Elvileg a CLI ugyanígy kiváltható lesz, tehát ott is a fenti js paranccsal megoldható a dolog node repl-ből.
32

Hát a fene tudja... ha

mind1 valami név · 2018. Okt. 18. (Cs), 01.37
Hát a fene tudja... ha annyira shell programozás, arra elvben ott a tcsh, csak az is olyan, hogy meg kellene tanulni. De minek... :)
A bash esetében attól kezdek beborulni az agyamba, hogy csomó dolgot két-három utility meghívásával elintézhetek, amit egy akármilyen script nyelvből csak iszonyat hosszú kóddal lehet kiváltani. Pl. egy uniq -c parancsot próbálj megcsinálni python-ban vagy akár perl-ben! Garantáltan több lesz, mint hét karakter :D
Ugyanakkor az is gusztustalan dolog, hogy bizonyos dolgokat elintézek perlben, de közben folyton külső programot hívogatok. Működik, de ocsmány...


Bash egyik legbosszantóbb hülyesége, hogy van benne valami olyasmi, amit függvénynek hív, de csak return code-ot képes visszaadni, tehát inkább nevezhető szubrutinnak, mint függvénynek... Most épp ezen anyázok. :D
33

Gondolom globális változókkal

inf · 2018. Okt. 18. (Cs), 02.21
Gondolom globális változókkal vagy ilyesmivel csak megkerülhető.

Amit bash-ben csinálsz ilyen uniq-el meg ilyesmivel azok transform stream-ek. A node alapból támogat ilyesmit. link A CGI scriptnek készült nyelvek nem biztos, bár szerintem tuti van ilyen python-ban és perl-ben is valami eldugott extension-ben vagy mittudomén.
34

Persze, megkerülhető, csak

mind1 valami név · 2018. Okt. 18. (Cs), 10.17
Persze, megkerülhető, csak OOOOCSMÁÁÁÁNY :D

Nem állítom, hogy értem, amit a trasform streamek kapcsán emlegetsz, de attól tartok, elbeszélünk egymás mellett.
Nem az a gond, hogy ne tudnék egy uniq parancsba átküldeni sorokat és a kapott eredményen tovább dolgozni. Hanem az, hogy natív nyelvi eszköz általában nincs rájuk .

Példa, bár nem vagyok profi perles, lehet, hogy milliószor egyszerűbb megoldás is lett volna (az if helyett asszem, van feltételes értékadás is ilyen $x=(exists($a)?$a++:1; formában, de már kezdett kifolyni a szemem, nem sikerült eltalálni a helyes szintaxist)

https://gist.github.com/haa-zee/48ab3e1cc51408ddd3da4a9136a664ff
Azért a második változat - ebben az esetben - lényegesen szebb. De ha tovább akarok dolgozni a uniq kimenetével... akkor vagy megírom, mint fent vagy berakom két perl-es pipe közé, ami ronda...
35

Nyilván nem lesz egyik

inf · 2018. Okt. 18. (Cs), 23.37
Nyilván nem lesz egyik nyelvben sem natívan benne a UniqStream osztály. Legalábbis nem lenne túl logikus. Amit csinálni tudsz, hogy megírod egy transform stream-ből kiindulva, hogy milyen transzformációt akarsz a szövegbe, vagy használsz egy létező stream lib-et, ami a létező unix parancsokat tartalmazza, és azokkal rakod össze úgy, mint most bash-ben. Ugyanúgy `read.pipe(transform).pipe(write)`, ami kelleni fog.

Ja nagyjából ezt mondom, hogy a te esetedben is szebb lenne, ha keresnél valami perles implementációt a uniq-re, vagy megírnád te magad. Annyira nem bonyolult szerintem sor duplázást nézni. Csak soronként kell küldeni az adatot, mindig le kell menteni az előző sort, aztán átugrani, ha megegyezik vele a következő.
36

Ö... izé... ne vedd

mind1 valami név · 2018. Okt. 19. (P), 08.28
Ö... izé... ne vedd kötekedésnek, de átmentél write only-ba? :D
Ott az a gist izé, benne a perlben megírt uniq -c -> pont azt próbáltam demonstrálni, hogy csak az ocsmány és ocsmány közül választhatok sok esetben. :)
38

Egy kicsit igen. :D Nem

inf · 2018. Okt. 19. (P), 11.09
Egy kicsit igen. :D

Nem értem a perlt, de amit írtál az ránézésre egyben rántja be a memóriába az egész logot. Amennyire én tudom az összes unix command stream-el, és nem egyben dolgozza fel az adatot, szóval valszeg nem felel meg a kódod a unix uniq-nek, és bedől az egész, ha egy igazán nagy log fájlt akarsz feldolgozni vele, mert nem fog beleférni a memóriába. Ha úgy gondolod, hogy nem lesznek ilyen gondjaid, akkor felejtsd el, amit a transform stream-ekről írtam, mert nem fog kelleni neked, és jó így, ahogy perlben megírtad. Ocsmánynak persze ocsmány. :D

Ha CLI-t akarsz csinálni bármelyik nyelvben nagyjából hasonló dolgokhoz, akkor igazán jóra úgy lehet megírni, ha csak egy entry point van, amit paraméterezel, aztán a paraméterek alapján csinál különböző dolgokat. Igy, hogy fele shell script, fele meg perl, szerintem bárhogy csinálod, mindenképp ocsmány lesz. Amúgy az MQ-ról teljesen lemondtál már, vagy miért CLI-ben megy az egész?
39

Sorry, ezt most nagyon

mind1 valami név · 2018. Okt. 19. (P), 14.57
Sorry, ezt most nagyon csúnyán benéztem. Mentségemre: napok óta alig alszom (nem emiatt :D). Egyszerűen amikor összedobtam azt a pár sort, akkor csak azt néztem, hogy működjön, nem gondolkodtam rajta, hogy vajon valóban azt csinálja-e, amit a shell parancsok sorozata.
Ezzel eltérő ("hibás") eredményt kapnék, ha valami véletlen folytán egy órán belül többször változna az IP címem és ugyanazt az IP-t többször is megkapnám. :)
Memória elfogyásától ebben az esetben nem tartok, ahhoz kb. száz éven át kéne gyűjteni az adatokat, hogy 1GB-ból kifussak :D

Azért CLI, mert évek óta ilyeneket futtatok, csak meguntam, hogy vagy a shell history-ból vagy a memóriám romjaiból kellett előszedni a parancsokat. A webes felülethez kellene majd valami MQ-féle, de szerintem odáig már sosem jutok el. A webes felület meg csak azért kellett volna, hogy ne kelljen mindig a laptopot bekapcsolni, ha rá akarok nézni ezekre a logokra. Mobilon elég szar gépelgetni és a terminál program betűi is elég aprók, ezért akartam webre áttolni :)
41

Szerintem nem olyan nagy

inf · 2018. Okt. 19. (P), 17.39
Szerintem nem olyan nagy munka átvinni webre az egészet MQ-val, ha már működnek a CLI scriptjeid. Egy node express szervert fellőni kb 3 sor, még beleszórsz egy MQ csatolót, amin keresztül eléred a fájlokat, meg esetleg egy IP ellenőrzést, generálsz pár linket a fájljaid olvasásához, aztán szinte készen is vagy. Persze ugyanez megoldható PHP-vel, perl-el, vagy bármelyik másik nyelvvel is, talán kicsit nehézkesebben az MQ miatt.
42

mondom még1x: gusztustalan,

mind1 valami név · 2018. Okt. 19. (P), 19.32
mondom még1x: gusztustalan, ocsmány stb. ;)
Persze, mivel saját célra kell, feldobhatnék egy önálló webszervert ami adm csoportba tartozó user alatt fut, meg valamit ami cgi futtatásra képes és megoldva a dolog.
45

adatok "szerializációja" ?

mind1 valami név · 2018. Okt. 23. (K), 12.56
Van erre valami normális, magyar kifejezés? Na mindegy...
Pár napja belefutottam egy olyanba, hogy ugye a socketen nem stringet, hanem byte streamet lehet csak átküldeni. O.K., tehát akkor kell valami átalakító.
Pythonban erre a pickle modult javasolták valahol, aminek a doksijában ott van, hogy csak olyan forrásból érkező adatot szabad vele "deszerializálni", amiben megbízunk, mert semmiféle védelem nincs benne a potenciálisan kártékony adattartalom ellen...
O.K., de akkor éles környezetben, kívülről jövő, megbízhatatlan forrással mégis hogyan kellene kommunikálni?
Vagy ez python specifikus dolog, egyéb nyelveken meg van oldva normálisan?
46

Szerializáció,

BlaZe · 2018. Okt. 23. (K), 17.09
Szerializáció, deszerializáció magyarul. Legalábbis még nem hallottam azt hiszem máshogy. Nem is kell :)

A pickle objektum struktúrát serializál és épít fel, ezáltal képes bármilyen támadó kódot lefuttatni deserializáció közben. A hasonló megoldások jellemzően jelentősen lassabbak és nagyobb méretet produkálnak azoknál a módszereknél, ahol te írod meg a serializációt minden egyes osztályra, vagy struktúrára, és bináris formátumban kommunikálsz.

Ez utóbbira 2 módszer létezik. Az egyik a deklaratív, ahol leírod a struktúrák formátumát és vagy valami reflection megoldással, vagy kódgenerálással serializál. Utóbbi nyilván sokkal gyorsabb.

A másik módszer a programmatic, amikor egy valamilyen interfacet kell implementálj, ami egy adott típust tud serializálni, deserializálni. Ez jellemzően szintén gyors.

Ezekben az esetekben csak az adatokat írod ki, a kapott bytestream sokkal kisebb. Cserébe minden oldalnak ismernie kell a struktúrát, hogy fel tudd építeni deserializációkor a helyes objektumot. Ez behoz más problémákat, mint pl a verzió inkompatibilitás, de ez is megoldható.

Emellett lehet valami struktúrált formátumba írni, mint pl XML, JSON, YAML stb, ami megint nagyobb méretben és jóval lassabb.

Biztos vagyok benne, hogy mindegyik módszerhez létezik megfelelő python lib.

Pár példa:
Protobuf
Flatbuffers
JSON
47

Köszi, akkor ennek újra

mind1 valami név · 2018. Okt. 23. (K), 18.18
Köszi, akkor ennek újra nekifutok, valamit kihagytam az olvasásból.
A json modul által előállított objektum ugyanis nem bytestream, legalábbis a send hibát ad rá (vagy a recv? Mind1)
Nekem nincs szükségem egyelőre komplex objektumok szerializációjára, bőven elég ha egy fix adatstruktúrát át tudok zavarni a socketen bytestreamként.

Na jó, akkor reset és olvasok újra, hátha észreveszem, mi maradt ki...
48

Mégis kérdés a kérdés

mind1 valami név · 2018. Okt. 25. (Cs), 03.04
Na, mégsem néztem el: https://stackoverflow.com/questions/39817641/how-to-send-a-json-object-using-tcp-socket-in-python

Mert eredendően úgy emlékeztem, hogy a json/xml/yaml formátumot szokták használni szerializációhoz, itt meg valamiért nem akart menni. A fenti poszt egyik válasza szerint jól látom: a json modul által előállított ojjektum további konverzióra szorul, ha socketen akarom átküldeni. És akkor goto 1: a pickle nem biztonságos... :S
49

Lehet, hogy én nem értem a

Endyl · 2018. Okt. 25. (Cs), 10.36
Lehet, hogy én nem értem a feladatot, de mi a probléma?

Van egy küldendő objektumod, ezt szerializálod sztringgé json-nal, azt átküldöd socketen, a fogadó oldalon meg visszalakítod a json sztringet objektummá, nem? Hol van itt a biztonsági probléma, ha nem ész nélkül használod fel, amit végül a küldött struktúrából kiolvasol?

https://stackoverflow.com/questions/38813298/is-json-loads-vulnerable-to-arbitrary-code-execution
50

Ott, hogy amit eddig

mind1 valami név · 2018. Okt. 25. (Cs), 10.44
Ott, hogy amit eddig találtam, minden poszt/válasz/tutorial a pickle modul használatát javasolja a szerializációhoz, mert önmagában a json (meg az összes többi hasonló) modulból kijövő adatot nem lehet átküldeni közvetlenül a socketen, mivel az nem byte sorozat. (mondja ezt a python)

>>> s.send(json.dumps(x))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: a bytes-like object is required, not 'str'
>>>

Viszont a pickle modul eleve úgy íródott, hogy nem biztonságos, ezt külön ki is emelik a doksiban.
És akkor most itt állok, mint ..., mert akkor mégis mi a bánatot lehetne használni?
C-ben nincs ilyen gond, de ez most épp python.


Update: bocs, asszem, megvan a lényeg:
json.dumps(...).encode()
Ezzel menni látszik pickle nélkül is.
51

Az általad linkelt kérdés

Endyl · 2018. Okt. 25. (Cs), 11.20
Az általad linkelt kérdés miatt azt hittem, hogy a json.loads() eredményét akarod a pickle-lel szerializálni, és nem értettem, hogy miért nem jó a json.dumps(). De akkor a str -> bytes konverzió hiányzott. Legalább már működik :)