PHP FTP daemon

Kedves fórumtársak!

Nemrég találtam meg a nanoftpd nevű PHP-s projektet, amivel tökéletesen elégedett vagyok, egy hiányossága van csak: amikor nagy fájlokat töltök fel, a kontroll kapcsolat fél perc múlva időtúllépés miatt megszakad. Úgy vélem, ez a PHP egyszálúsága miatt van így.

A kérdésem az lenne, lenne-e valakinek ötlete arra vonatkozólag, hogyan lehetne ezt feloldani egyszerűen - ha egyáltalán lehetséges. Az jutott eszembe, hogy esetleg forkolni lehetne az adatfolyamot, de ezzel a technikával nincs még tapasztalatom.

A válaszokat előre is köszönöm.

Hozzászólások

megkérdezhetem, h miért akarod "megerőszakolni" a dolgokat?
mekkora adatmennyiséget akarsz feltölteni? miért éppen FTP-ben gondolkodsz?

tuti van valmi max run time beállítása a php nek és abba futsz bele.

De amúgy ez valami végtelen nagy tévedés: ftp démon php-ban! What? Inkább írd le, h mire akarod használni!  Szerintem lesz a ftp-nél jobb javaslat! 

"antiegalitarian, antiliberal, antidemocratic, and antipopular"

Kíváncsiságból megkérdeztem az eheti experimental Gemini modellt:

A nanoftpd-nél jelentkező probléma, hogy nagy fájlok feltöltésekor a kontroll kapcsolat fél perc után megszakad, valóban a PHP egyszálúságával függhet össze. Mivel a PHP alapértelmezetten szinkron módon dolgozza fel a kéréseket, egy hosszú feltöltés blokkolhatja a kontroll kapcsolatot.

Nézzünk meg néhány lehetséges megoldást a problémára:

1. PHP időkorlát növelése:

  • set_time_limit() függvény: Ez a függvény megnöveli a script futási idejének maximális értékét másodpercben. Próbáld meg a script elején meghívni set_time_limit(0); értékkel, ami kikapcsolja az időkorlátot. Fontos megjegyezni, hogy ez nem ajánlott éles környezetben, mivel biztonsági kockázatot jelenthet.

  • max_execution_time beállítás a php.ini fájlban: Ez a beállítás a script maximális futási idejét határozza meg másodpercben. Növeld meg az értékét egy nagyobb számra, például 300-ra (5 perc). A php.ini módosítása után indítsd újra a webszervert.

2. Aszinkron feldolgozás:

  • Háttérfolyamat indítása: A feltöltést egy külön háttérfolyamatban lehet futtatni, így a kontroll kapcsolat nem blokkolódik. Ehhez használhatsz olyan eszközöket, mint a exec() vagy a pcntl_fork() függvények. Fontos azonban megjegyezni, hogy ezeknek a függvényeknek a használata bonyolultabbá teszi a kódot, és biztonsági kockázatokat is rejthet.

  • Üzenetsorok használata: Az üzenetsorok lehetővé teszik az aszinkron kommunikációt a folyamatok között. A feltöltést el lehet küldeni egy üzenetsorba, amelyet egy külön háttérfolyamat dolgoz fel.

3. Forkolás (elágazás):

Ahogy említetted, a forkolás is egy lehetőség. A pcntl_fork() függvény segítségével létrehozhatsz egy új folyamatot, amely a feltöltéssel foglalkozik, míg az eredeti folyamat fenntartja a kontroll kapcsolatot. Ez a megoldás is bonyolultabb, és körültekintést igényel.

Fontos megjegyzések:

  • Biztonság: Mindenképpen vedd figyelembe a biztonsági szempontokat, amikor módosítod a PHP beállításait vagy aszinkron feldolgozást használsz.

  • Karbantarthatóság: A bonyolultabb megoldások, mint a forkolás vagy az üzenetsorok, nehezebben karbantarthatók.

  • Tesztelés: Alaposan teszteld a változtatásokat, hogy biztosan megfelelően működnek.

Melyik megoldást válaszd?

A legegyszerűbb megoldás a max_execution_time növelése a php.ini fájlban. Ha ez nem elegendő, vagy biztonsági aggályaid vannak, akkor próbálkozhatsz a háttérfolyamat indításával vagy az üzenetsorok használatával. A forkolás a legbonyolultabb megoldás, és csak akkor ajánlott, ha a többi megoldás nem működik.

A nanoftpd kódjának ismerete nélkül nehéz pontos tanácsot adni. Javaslom, hogy olvasd el a nanoftpd dokumentációját, és keress hasonló problémákról szóló fórumbejegyzéseket.

Remélem, ezek a tippek segítenek megoldani a problémát!

Szerkesztve: 2024. 11. 17., v – 19:49

hogyan indítod az ftpd oldalt? cli? mit ír ki miután megszakad a kapcsolat? A forrást megnézve használ socket_select -et, így az, hogy egy szálon történnek a dolgok, nem befolyásol semmit ezzel kapcsolatban

// Happy debugging, suckers
#define true (rand() > 10)

Ez az ftpd nem kezel timeout-ot. Csak "===false" jellegű hibakezelés van a socketekre. A timeout értéke valami default ill. a php config-ból adódik.

A max_conn ill. max_conn_per_ip túllépése esetén "421 <hibaüzenet>" választ ad, majd megszakítja a kapcsolatot.

Szerintem neked a felhasználói élménnyel van gondod, azaz hogy az általad használt kliens nem kapcsolódik újra, ha megszakadt a kapcsolat. Vagy próbál, de előbbi két korlátozás valamelyikébe ütközik.

Köszönöm a válaszokat, a következő a helyzet: van egy feladatkezelő rendszerem, amit PHP-ban írtam, és az ide feltöltött fájlokat (feladatokhoz és a tárhelyre) szeretném FTP-n is elérhetővé tenni. Az FTP számomra egy tökéletes protokoll, régi, szabványos, titkosított kapcsolaton keresztül folyhat a kommunikáció, valamint végtelenféle klienst írtak már hozzá mindenféle operációs rendszerhez.

Amikor WinSCP-vel csatlakozom hozzá, az úgy van beállítva, hogy a fájlok felmásolásához a háttérben indítson külön kapcsolatot. Amikor elkezdem a nagy fájlt felmásolni, az eredeti kapcsolat (kontroll) "lefagy", nem lehet rajta frissítést nyomni, a könyvtárak között közlekedni, bármi mást csinálni. Ráadásul ez szakad meg fél perc múlva, az adatkapcsolaton a fájl közben felmegy.

Találtam node.js csomagokat a témában, ezek végülis működnek, de jobban szeretném PHP-val megoldani, amennyiben lehetséges.

FTP-nél hogy oldod meg h. titkosítson? Mert én még titkosított ftp átvitelt nem láttam, de lehet én vagyok lemaradva. Az sftp az meg ugye igazából SSH.

Tudomásom szerint az ftps az annyit tudott évekkel ezelőtt is h. a hitelesítés titkosított volt, minden más ugyanúgy plain. Aztán most lehet valaki megcáfol.

FTPS esetében választhatsz, az explicit titkosításnál titkosítatlanul kezdődik a kapcsolat (alapértelmezetten a 21-es port), ahol felkínál egy AUTH TLS nevű parancsot, ha ezzel folytatod, akkor a kapcsolat utána titkosított csatornára vált. Implicit titkosítás esetén (általában a 990-es porton fut) eleve TLS kézrázással indul, és utána titkosított lesz az adatcsere.

FTP szoftver és beállítás függvénye, hogy kötelező-e a titkosítás vagy sem.

Nem tudom, hogy számodra mi az előny és mi a hátrány, ezért csak a magam véleményét tudom leírni, amivel vagy egyetértesz vagy nem.

Az FTP egy viszonylag egyszerű protokoll, ami nagyjából változatlan évtizedek óta. Ez szerintem óriási előny, ha a https alatt egy böngésző alapú szolgáltatást értesz, akkor ott az adott szolgáltatás publikus API-ját (URL) jellemzően párévente lecserélik (jön egy újabb divat, újabb frontend), így a klienseket is módosítani kell.

Az FTP arra lett kitalálva, hogy fájlokat juttassanak el egyik helyről a másikra. A http protokoll ennél egy picit általánosabb, emiatt érdekes az előbbi bekezdésem, hogy változhat az API és a kliensek.

Természetesen készítettem webes és webdav klienst is, de ezekhez képest az FTP-nek még előnye, hogy nagyon egyszerűen scriptelhető, azaz könnyen megoldható bizonyos fájlok automatizált másolása a rendszerbe.

több dolgot nem értek:
1) ahol elfut egy (apache?) webserver ott elfut egy ftpd is - kár ezért még a PHP-t is bevonni
2) mint azt irták, az FTP nemigen tud titkosítani
3) ha a kliens NAT mögött van, akkor vagy passive mód kell vagy NAT helper (emlékeim szerint)
4) http átvitelben mi az, ami nem scriptelhető? egy olyan egyszerű eszközben mint egy Mikrotik router is van már tool/fetch - ami még upload-ot is tud

  1. saját, adatbázisalapú fájl- és hozzáféréskezelés van a rendszerben, amit egyszerűbbnek tűnik egyelőre saját szerverből módosítani, mint külső ftpd-re hagyatkozni - hogy ez így marad-e, még megfontolás tárgyát képezi
  2. mint írtam, tud (FTPS)
  3. a nanoftpd tud passzív módot
  4. míg egy HTTP alapú alkalmazásnál ma ezt az URL-t kell meghívni fel- és letöltéshez, két év múlva másikat, öt év múlva harmadikat, tíz év múlva nyolcadikat; az FTP protokoll "API"-ja húsz év múlva is ugyanaz marad, azaz olcsóbb az üzemeltetése és a használata

SFTP-t használnak mindenhol. 
Nem elérhető azon a szerveren? Nincs SSH?
Bármi jobb egy megerőszakolt PHP-nál. :)