Zobrazit příspěvky

Tato sekce Vám umožňuje zobrazit všechny příspěvky tohoto uživatele. Prosím uvědomte si, že můžete vidět příspěvky pouze z oblastí Vám přístupných.


Příspěvky - exkalibr

Stran: 1 ... 22 23 [24] 25
346
Tak to nefunguje. Povedlo se otestovat jen dva bloky, ale mají příliš vysoký čas. Možná kvůli té testovací smyčce (i když file_exists asi hledá v bufferu, že?).

347
Dík za článek. A proč prostě soubor nepřejmenovat?
Kód: [Vybrat]
if file exists jirka do:
  copy jirka jirka.backup
  rename jirka jirka.2
  open jirka.2
  read jirka.2
  add jirka.2
  save jirka.2
  close  jirka.2
  rename jirka.2 jirka
else:
while (delay) do:
 if file jirka exists do ...
endwhile;
endif;
Vtip je v tom, že pokud se se souborem pracuje, tak k němu žádný jiný program/skript nemůže. Je to geniálně jednoduché a nevyžaduje to zámky.
Dal by se do toho zakomponovat i test if jirka.2 exists do:
To mě nepřijde jako dobré řešení. Více procesů ve stejnou chvíli může vyhodnotit první řádek jako true a budou chtít provádět copy, rename.... Ten co bude o setinku pomalejší vyhodí chybu. Já jsem kdysi používal zámek pomocí vytváření a ověřování adresáře, protože mkdir je atomická a rychlá funkce. Pro permanentní zápisy do souboru je nejlepší databáze, tak jak ti Kid už napsal.

Máš pravdu, to rename musí následovat hned za if, pak už je pozdě. Copy provést až po přejmenování. Mě připadá že vytváření adresáře je složitější proces než přejmenování. FS si musí kvůli tomu vytvořit nový záznam, kdežto při rename souboru nemusí vytvářet nic... Ale mohu otestovat ten rename a říct ti jestli je to spolehlivější než T7.

348
Dík za článek. A proč prostě soubor nepřejmenovat?

Přejmenování se pro docílení atomicity skutečně používá. V daném případě musíš ještě ošetřit situaci, kdy proces přejmenuje soubor a následně chcípne. Co teď?

Díky za potvrzení :) Jsem perfekcionista, počítal jsem s tím přece. Viz

Citace
Dal by se do toho zakomponovat i test if jirka.2 exists do:

349
Dík za článek. A proč prostě soubor nepřejmenovat?

Kód: [Vybrat]
if file exists jirka do:
  copy jirka jirka.backup
  rename jirka jirka.2
  open jirka.2
  read jirka.2
  add jirka.2
  save jirka.2
  close  jirka.2
  rename jirka.2 jirka
else:
while (delay) do:
 if file jirka exists do ...
endwhile;
endif;

Vtip je v tom, že pokud se se souborem pracuje, tak k němu žádný jiný program/skript nemůže. Je to geniálně jednoduché a nevyžaduje to zámky.

Dal by se do toho zakomponovat i test if jirka.2 exists do:

350
Dej příklad jak by se dali použít. Chci si rozšířit obzory.

Tak jedno použití mě napadlo. Možná na stáhnutí vzdáleného souboru?

351
Díky moc za odpovědi. Moc jsem se poučil a teď už mám klid. Takže teď už vím, že file_get_contents a file_put_contents jsou vlastně k ničemu. Neumím si představit k čemu bych je využil, když existuje riziko, že dva lidé odešlou do stejného souboru data, ale uloží se jen jeden, ten druhej ne. Je to úleva.

PS: Tys nikdy nedělal kočku v mikrovlnce?  ;D

352
Zajímavé je ale to, že v manuálu těch funkcí není nic o tom, že data jsou bufferované.

Myslím že ten rozdíl v rychlosti T2 a T3/T4 dokazuje, že T3 a T4 neprovádí bezpečné čtení a zápis.

Nedokazuje to vůbec nic.

Ale jo, dokazuje to přesně to co si říkal. Je totiž z toho patrné, že ty data se nečtou z disku (rozuměj - z plotny), ale z bufferu.

353
Problém je, pokud soubor přečteš, modifikuješ a uložíš. Tyto tři úkony nejsou v jedné transakci a proto při souběhu můžeš přijít o data.

Díky. To mi bohatě stačí. Proč ale tyto informace nejsou uvedeny v manuálu. To je přece důležitá informace. Když do googlu zadám např. "php file_get_contents you can lose data" tak nenajdu nic s tímto výskytem. Takže očividně se tato informace tají. Jak jinak si vysvětlit, že před tímto nezbytným faktem nevarují?

354
Nevím sice, o co se pokoušíš, ale obávám se, že ses vydal chybnou cestou. Pokud ti dělají starosti kolize, měl bys použít databázi, která se o takové problémy sama postará a k tomu ti nabídne luxusní přístupové metody. PHP v základní výbavě nabízí 5 různých databází, ze kterých si určitě vybereš.

Takže co je účelem zkoumání čtení a zápisu souborů? Konfigurace, blog, diskuzní fórum, ... ?

Takže přiznáváš, že u funkcí file_get_contents a file_put_contents existuje riziko kolize. Protože z tvého příspěvku to vyplývá. Se stejným přístupem mlžit a neříct to explicitně jsem se potkal na více místech internetu. To je ten důvod, proč jsem se vydal tou cestou, abych to prozkoumal. Jestliže považuješ file_get_contents a file_put contents za natolik nespolehlivé, že chceš raději používat databázi, nepřímo mi tím potvrzuješ výsledek mého zkoumání. Ale chtěl bych to slyšet explicitně, něco jako "Ano, už to tak asi bude" nebo "Z výsledků to vyplývá" nebo "Nevěřím tomu, jdu si to ověřit"... To je taky možnost.

Myslím že ten rozdíl v rychlosti T2 a T3/T4 dokazuje, že T3 a T4 neprovádí bezpečné čtení a zápis. Smůla je v tom, že kolizi nemám jak prokázat, protože tak chytrý algoritmus, který by zkontroloval validitu dat nemám. Mohu kontrolovat jen rozměr, ale to ještě nic nedokazuje. Podle mě čas zápisu na disk v rozsahu 22ms až 206 ms dokazuje (T2), že se jedná o čtení z disku a zápis na disk, kdežto časy u T3:

Kód: [Vybrat]
523		0,00251909
948 0,000630766
1371 0,002995359
1913 0,006401292
2701 0,002551624
4495 0,002908468
6758 0,019312313
a T4:
0,001060027
0,002461412
0,003131726
0,003644179
0,002659538
0,001959271
0,001399823
ukazují, že jde o čtení z bufferu. Tím pádem se nepokouší o ověřování skutečných dat a aktuálnost či správnost dat není zaručena. To co dělají ty funkce, že se podívají na jméno souboru a řeknou si "je to jeden a ten samý soubor" a obsahem se nezabývaj, prostě to tam plácnou tu starou kopii dat. Předpokládají, že ke změně nedošlo.

355
Souborové systémy mají vlastní buffery a cache. Zkus z jednoho procesu neustále modifikovat jeden soubor a z druhého ho číst. Uvidíš, že je to spolehlivé.

V T2 máš chybu
Kód: [Vybrat]
$s = file_get_contents("523");
Tohle čte ze souboru, který zřejmě neexistuje.

Všechny testy byly úspěšně zkontrolovány (kdyby neexistoval, dostal bych chybu).

523 je název originálního zdrojového souboru (obraz) 523 kB.
523.txt je název cílového souboru. Ta koncovka tam je jen pro rozlišení, trochu nelogické, já vím, ale já si tu koncovku oblíbil, protože obvykle pracuju s texťáky a ne s obrazy :)

356
Ještě bych k tomu dodal, že pokud ty funkce používají buffering na úrovni souborového systému, což předpokládám, není nutné se obávat nespolehlivosti a nekonzistence. Ukaž příklad, kdy k něčemu takovému došlo a rozebereme příčiny. Bez zámků se to stává jen u souborů >8 KiB.

Já ty data nekontroloval, velikost odpovídá, jenže jak vysvětlíš rozdíl v časech mezi T2 a T3, T4?

T2 bylo načítání z originálního souboru a zápis do jiného souboru (tedy dva různé soubory) a má výrazně vyšší časy, než když jsem použil T3, T4 se čtením ze stejného souboru do kterého jsem provedl zápis.

Kód T2:

Kód: [Vybrat]
echo "file_get_contents/file_put_contents test ".time()."<br>";
die;
while ( time()<1570604800 )
{
usleep(500);
}

$file = "temp.jpg";

echo "<h4>523 at ".time()."</h4>";
for ($i = 0; $i<50; $i++ ){
 $start = microtime(true);
 $s = file_get_contents("523");
 file_put_contents("523.txt",$s,LOCK_EX);
 usleep( 50 );
 $time_elapsed_secs = microtime(true) - $start;
echo "time: $time_elapsed_secs s<br>";
}
echo "<h4>948 at ".time()."</h4>";
for ($i = 0; $i<50; $i++ ){
 $start = microtime(true);
 $s = file_get_contents("948");
 file_put_contents("948.txt",$s,LOCK_EX);
 usleep( 50 );
 $time_elapsed_secs = microtime(true) - $start;
echo "time: $time_elapsed_secs s<br>";
}
echo "<h4>1371 at ".time()."</h4>";
for ($i = 0; $i<50; $i++ ){
 $start = microtime(true);
 $s = file_get_contents("1371");
 file_put_contents("1371.txt",$s,LOCK_EX);
 usleep( 50 );
 $time_elapsed_secs = microtime(true) - $start;
echo "time: $time_elapsed_secs s<br>";
}

echo "<h4>1913 at ".time()."</h4>";
for ($i = 0; $i<50; $i++ ){
 $start = microtime(true);
 $s = file_get_contents("1913");
 usleep( 50 );
 file_put_contents("1913.txt",$s,LOCK_EX);
 $time_elapsed_secs = microtime(true) - $start;
echo "time: $time_elapsed_secs s<br>";
}

echo "<h4>2701 at ".time()."</h4>";
for ($i = 0; $i<50; $i++ ){
 $start = microtime(true);
 $s = file_get_contents("2701");
 file_put_contents("2701.txt",$s,LOCK_EX);
 usleep( 50 );
 $time_elapsed_secs = microtime(true) - $start;
echo "time: $time_elapsed_secs s<br>";
}

echo "<h4>4495 at ".time()."</h4>";
for ($i = 0; $i<50; $i++ ){
 $start = microtime(true);
 $s = file_get_contents("4495");
 file_put_contents("4495.txt",$s,LOCK_EX);
 usleep( 50 );
 $time_elapsed_secs = microtime(true) - $start;
echo "time: $time_elapsed_secs s<br>";
}

echo "<h4>6758 at ".time()."</h4>";
for ($i = 0; $i<50; $i++ ){
 $start = microtime(true);
 $s = file_get_contents("6758");
 usleep( 50 );
 file_put_contents("6758.txt",$s,LOCK_EX);
 $time_elapsed_secs = microtime(true) - $start;
echo "time: $time_elapsed_secs s<br>";
}

T3:
Kód: [Vybrat]
echo "flock test ".time()."<br>";
die;
while ( time()<1570612500 )
{
usleep(500);
}

$file = "temp.jpg";

echo "<h4>523 at ".time()."</h4>";
for ($i = 0; $i<50; $i++ ){
 $start = microtime(true);
 $s = file_get_contents("523.txt");
 file_put_contents("523.txt",$s,LOCK_EX);
 usleep( 50 );
 $time_elapsed_secs = microtime(true) - $start;
echo "time: $time_elapsed_secs s<br>";
}
echo "<h4>948 at ".time()."</h4>";
for ($i = 0; $i<50; $i++ ){
 $start = microtime(true);
 $s = file_get_contents("948.txt");
 file_put_contents("948.txt",$s,LOCK_EX);
 usleep( 50 );
 $time_elapsed_secs = microtime(true) - $start;
echo "time: $time_elapsed_secs s<br>";
}
echo "<h4>1371 at ".time()."</h4>";
for ($i = 0; $i<50; $i++ ){
 $start = microtime(true);
 $s = file_get_contents("1371.txt");
 file_put_contents("1371.txt",$s,LOCK_EX);
 usleep( 50 );
 $time_elapsed_secs = microtime(true) - $start;
echo "time: $time_elapsed_secs s<br>";
}

echo "<h4>1913 at ".time()."</h4>";
for ($i = 0; $i<50; $i++ ){
 $start = microtime(true);
 $s = file_get_contents("1913.txt");
 usleep( 50 );
 file_put_contents("1913.txt",$s,LOCK_EX);
 $time_elapsed_secs = microtime(true) - $start;
echo "time: $time_elapsed_secs s<br>";
}

echo "<h4>2701 at ".time()."</h4>";
for ($i = 0; $i<50; $i++ ){
 $start = microtime(true);
 $s = file_get_contents("2701.txt");
 file_put_contents("2701.txt",$s,LOCK_EX);
 usleep( 50 );
 $time_elapsed_secs = microtime(true) - $start;
echo "time: $time_elapsed_secs s<br>";
}

echo "<h4>4495 at ".time()."</h4>";
for ($i = 0; $i<50; $i++ ){
 $start = microtime(true);
 $s = file_get_contents("4495.txt");
 file_put_contents("4495.txt",$s,LOCK_EX);
 usleep( 50 );
 $time_elapsed_secs = microtime(true) - $start;
echo "time: $time_elapsed_secs s<br>";
}

echo "<h4>6758 at ".time()."</h4>";
for ($i = 0; $i<50; $i++ ){
 $start = microtime(true);
 $s = file_get_contents("6758.txt");
 usleep( 50 );
 file_put_contents("6758.txt",$s,LOCK_EX);
 $time_elapsed_secs = microtime(true) - $start;
echo "time: $time_elapsed_secs s<br>";
}

To die na začátku tam je jen kvůli tomu, abych si nejdříve opsal čas a zkopíroval do while + 20 vteřin. To proto, aby se všechny 4 "exekuce" spustily ve stejný okamžik.

Kontrolu dat jsem prováděl jen od toho fflush, fwrite

357
Jako třetí parametr file_put_contents() zkus uvést konstantu LOCK_EX

Používám téměř výhradně tyto dvě funkce, ostatní jsem odstavil jako nepotřebné. Výsledky po úpravě volání mě zajímají.

Ale to tam mám.

test 2 obsahuje toto:
Kód: [Vybrat]
file_put_contents("523.txt",$s,LOCK_EX);

Díky za připomínku.

358
Zajímalo mě jak je to s bezpečností funkcí file_get_contents/file_put_content vs flock/fread/fwrite/flush při hromadném přístupu k téže souboru. Jelikož jsem nikde na netu nenašel žádné informace, které by mi jednoznačně a definitivně vyloučili možnost selhání (např. vzniku vadného souboru, ztráty dat apod.) při čtení/zápisu pomocí prvních dvou zmíněných funkcí, tak jsem se újmul toho, že jsem udělal testy. Test jsem nahrál na vzdálený server a otestoval jsem stránku (skript): spustil jsem stejný požadavek 4x paralelně, abych zjistil jak rychle dokáže vzdálený server načítat a zapisovat data na pevný disk.

Kompletní popis testu a výsledků je v angličtině zde:

https://stackoverflow.com/questions/58351839/is-file-get-contents-file-put-contents-reliable-or-can-lead-to-loss-of-data-b

graf zde:


První tři testy T2, T3, T4 probíhaly s file_read_contents/file_write_contents, z toho jen T2 vykazuje takovou rychlost, která svědčí o faktickém čtení z disku (nikoliv z bufferu). T3 a T4 měly tak malé časy, že na grafu téměř nejsou vidět.

Pak je tam T5, T6 a T7 což je použití flock, fread, fflush + ověření správnosti zadaných dat, občas se selháním a následným obnovením souboru pomocí copy(). Všechny funkce měly smyčku s 50 cykly a prodlevu smyčky 50 microsekund. V posledním testu se to zdálo jako překážka, tak jsem to usleep v T7 odstranil.

Z výsledku mi vyplývá, že první dvě zmíněné funkce používají buffering a není na ně spoleh pokud jde o konkurenční zápis do spouboru. Při paralelním přístupu je třeba použít metodu flock, ffread, fflush, fwrite.

Zajímá mě, jestli mi tu můžete potvrdit správnost závěrů ke kterým jsem došel. Případně, pokud by byl zájem o zdrojáky testů, mohu poskytnout. Ale zajímá mě hlavně váš pohled na to, zda ten test má nějakou vypovýdající hodnotu. Jelikož jsem měl k dispozici 4 sady dat z každého testu, celkem 7*50*4 čísel, měl jsem dostatek čísel ke zhodnocení průměrů časů, odchylek, minimum a maxim, vytvoření grafů. Dělat další testy v oblasti prvních zmíněných funkcí mi už dál nepřipadalo užitečné, protože jsem nepřišel na to jak je donutit aby zapsaly celý obsah zásobníku do souboru (nebo aby si ten soubor skutečně přečetly z disku a ne z bufferu).

359
Vývoj / Re:Jak se chránit pro XSS útoku na php serveru?
« kdy: 11. 10. 2019, 17:45:57 »
Parsery si vždycky píšu vlastní, rychlejší než ty co jsou defaultně zabudované v php. Jako oddělovač nejčastěji používám \n, \t ale uvažuju i o použití speciálních znaků tam kde user nevkládá vstupy. Napsal jsem si například funkci, která převádí číslo na zakódovaný string (něco jako intval, ale má ord. rozsah 32-254). Výhodou je to, že i velké id se zkrátí na 4-5 bajtů. Jak ale čísla oddělit? Tak mě napadlo buď 255 (protože 255 pro id nikdy nepoužívám) nebo \r.

Přesně tohle je vlákno příspěvků které sráží věrohodnost tohoto serveru pro mě až na dno :O(
Uživatel zaregistrován těsně před založením vlákna, nikam jinam nepřispívá a vede to přesně tak aby vyvolával kontroverze a provokoval. Bohužel je to tu opravdu časté i přes povinnou registraci :O(

Copak tě trápí, svěř se nám.

360
Vývoj / Re:Jak se chránit pro XSS útoku na php serveru?
« kdy: 11. 10. 2019, 15:32:58 »
S tím souvisí i ukládání a načítání dat do souborů/databází - platí podobná pravidla - záleží zda se data nějak parsují (jak při ukládání tak při čtení, nebo případně includování, někdy si člověk ani neuvědomí co všechno fuguje jako parser).

Parsery si vždycky píšu vlastní, rychlejší než ty co jsou defaultně zabudované v php. Jako oddělovač nejčastěji používám \n, \t ale uvažuju i o použití speciálních znaků tam kde user nevkládá vstupy. Napsal jsem si například funkci, která převádí číslo na zakódovaný string (něco jako intval, ale má ord. rozsah 32-254). Výhodou je to, že i velké id se zkrátí na 4-5 bajtů. Jak ale čísla oddělit? Tak mě napadlo buď 255 (protože 255 pro id nikdy nepoužívám) nebo \r.

Stran: 1 ... 22 23 [24] 25