[PHP] Lock op Cronjob

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • Saven
  • Registratie: December 2006
  • Laatst online: 07:59

Saven

Administrator

Topicstarter
Holaa

Ik zit met een vreemd probleem. Ik run elke 5 minuten een (pittige) cronjob op een server. Het is niet de bedoeling dat die weer opnieuw wordt uitgevoerd terwijl de ander nog niet is afgerond.

Ik dacht een makkelijke snippet te hebben gemaakt:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?
    public function action_heavytask()
    {
        if( file_exists( Kohana::$config->load('global.lockfile.heavytask') ) )
        {
            $log = ORM::factory('log');
            
            $currDateTime = new DateTime();
            
            $log->log       = 'Action heavy task stuck in lock';
            $log->time      = $currDateTime->format('Y-m-d H:i:s');
            $log->type      = 'Cronjob';
            
            $log->save();
            
            //die('Locked');
            return;
        }
        
        $myfile = fopen(Kohana::$config->load('global.lockfile.heavytask'), "w") or die("Unable to open file!");
        $txt = "locked";
        fwrite($myfile, $txt);
        fclose($myfile);

        foreach( $heavytasks as $heavytask )
        {
            //..........
        }
        
        unlink( Kohana::$config->load('global.lockfile.heavytask') );
        
        echo 'finished';
    }


Als ik de file handmatig uitvoer is er niks aan de hand. Echter zodra ik een cronjob activeer die de url via CURL aanroept verwijdert hij de lockfile niet meer.

Overigens is het script nu nog niet zo zwaar dat hij in de lock zou moeten schieten. De cron staat op 5 minuten en de script execution time is ongeveer 1 minuut. Maar goed, dan nog zou hij de lockfile moeten verwijderen :X

Ik heb al geëxperimenteerd met een return; en een die() zoals je kunt zien. Maar beide hebben geen nuttig effect.

Heeft iemand een idee wat er hier fout gaat?

Overigens zie ik in de ftp wel steeds de modified date (laatst gewijzigd) veranderen als de cron wordt uitgevoerd. Dus 12:15:01, en 5 min later is de last modified date 12:20:02. Terwijl hij toch echt in de lock zit :X

Acties:
  • 0 Henk 'm!

  • Hydrosine
  • Registratie: Februari 2009
  • Laatst online: 13-10 09:47
je doet het script uitvoeren en de cron onder dezelde user neem ik aan?
Ah ik lees dat je het via curl uitvoert en niet direct.
Ik vermoed een rechtenissue ;)

[ Voor 38% gewijzigd door Hydrosine op 01-05-2015 12:27 ]


Acties:
  • 0 Henk 'm!

  • kwaakvaak_v2
  • Registratie: Juni 2009
  • Laatst online: 10-10 08:02
tja..

code:
1
2
 if( file_exists( Kohana::$config->load('global.lockfile.heavytask') ) )
        {

moet daar geen else bij?


Je controlleert nu of er een lock file is, maar schrijft er hoe dan ook een nieuwe versie van.

Driving a cadillac in a fool's parade.


Acties:
  • 0 Henk 'm!

  • sander0
  • Registratie: Juli 2010
  • Laatst online: 13-02 07:32
Ik ga mee met een rechten issue, klinkt alsof de web user wel rechten heeft om de lock file te verwijderen en de cronjob niet.

Acties:
  • 0 Henk 'm!

  • triet
  • Registratie: Januari 2003
  • Niet online
kwaakvaak_v2 schreef op vrijdag 01 mei 2015 @ 12:29:
tja..

code:
1
2
 if( file_exists( Kohana::$config->load('global.lockfile.heavytask') ) )
        {

moet daar geen else bij?


Je controlleert nu of er een lock file is, maar schrijft er hoe dan ook een nieuwe versie van.
Nee, want er staat een 'return' in diezelfde if.

Acties:
  • 0 Henk 'm!

  • Kees
  • Registratie: Juni 1999
  • Laatst online: 08:19

Kees

Serveradmin / BOFH / DoC
kwaakvaak_v2 schreef op vrijdag 01 mei 2015 @ 12:29:
tja..

code:
1
2
 if( file_exists( Kohana::$config->load('global.lockfile.heavytask') ) )
        {

moet daar geen else bij?


Je controlleert nu of er een lock file is, maar schrijft er hoe dan ook een nieuwe versie van.
Nee, want daar is de early return in de if {} voor zodat hij het niet probeert als de file bestaat

Je zegt dat hij de file niet verwijderd, heeft hij daar rechten toe? En schrijft hij er ook daadwerkelijk iets in? In plaats van "locked", laat hem er eens date('r') oid heen schrijven?

[ Voor 25% gewijzigd door Kees op 01-05-2015 12:34 ]

"Een serveradmin, voluit een serveradministrator, is dan weer een slavenbeheerder oftewel een slavendrijver" - Rataplan


Acties:
  • 0 Henk 'm!

  • Donderpoes
  • Registratie: April 2011
  • Laatst online: 11-05 23:09
Kan je hem niet direct met PHP aanroepen i.p.v. curl?

En log je de output van de cronjob?

Acties:
  • 0 Henk 'm!

  • Barryvdh
  • Registratie: Juni 2003
  • Laatst online: 10:27
En Kohana::$config->load('global.lockfile.heavytask') is een absoluut pad?

Je kan overigens ook touch() gebruiken, je hoeft niet perse iets te schrijven naar het bestand.

Acties:
  • 0 Henk 'm!

  • Saven
  • Registratie: December 2006
  • Laatst online: 07:59

Saven

Administrator

Topicstarter
Donderpoes schreef op vrijdag 01 mei 2015 @ 12:44:
Kan je hem niet direct met PHP aanroepen i.p.v. curl?

En log je de output van de cronjob?
Ah dat is een goede, even via de mail laten sturen. Ik dacht dat dat al gebeurde bij errors bijkbaar niet. Nu monitor ik ff alle calls :)
Barryvdh schreef op vrijdag 01 mei 2015 @ 12:50:
En Kohana::$config->load('global.lockfile.heavytask') is een absoluut pad?

Je kan overigens ook touch() gebruiken, je hoeft niet perse iets te schrijven naar het bestand.
Is een absoluut pad. Touch zal ik even checken :)
sander0 schreef op vrijdag 01 mei 2015 @ 12:30:
Ik ga mee met een rechten issue, klinkt alsof de web user wel rechten heeft om de lock file te verwijderen en de cronjob niet.
Maar curl voert toch gewoon een http request uit? ALs ik hem via de browser aanroep draait het namelijk ook prima

Acties:
  • 0 Henk 'm!

  • sander0
  • Registratie: Juli 2010
  • Laatst online: 13-02 07:32
Saven schreef op vrijdag 01 mei 2015 @ 13:10:
[...]

Ah dat is een goede, even via de mail laten sturen. Ik dacht dat dat al gebeurde bij errors bijkbaar niet. Nu monitor ik ff alle calls :)


[...]

Is een absoluut pad. Touch zal ik even checken :)


[...]

Maar curl voert toch gewoon een http request uit? ALs ik hem via de browser aanroep draait het namelijk ook prima
Oeps, ik denk dat ik wat verwarring schep. Als ik lees 'Als ik de file handmatig uitvoer is er niks aan de hand.' dan verwacht ik hem dat je de cron via SSH uitvoert (of iets vergelijkbaars) en dan is je user wel belangrijk. Wat jij bedoelt is de URL in je browser bezoeken of via curl?

Acties:
  • 0 Henk 'm!

  • 3raser
  • Registratie: Mei 2008
  • Laatst online: 14-10 23:27

3raser

⚜️ Premium member

Ik heb ook PHP scripts die niet door elkaar mogen draaien. Daarom start ik ze via een bash script welke eerst flock gebruikt om zichzelf te locken. Dit heeft bij mij nog nooit problemen opgeleverd. PHP wordt overigens gewoon rechtstreeks aangeroepen en dus niet via curl.

code:
1
/usr/bin/php /home/myname/script.php

Acties:
  • 0 Henk 'm!

  • Donderpoes
  • Registratie: April 2011
  • Laatst online: 11-05 23:09
Saven schreef op vrijdag 01 mei 2015 @ 13:10:
[...]

Ah dat is een goede, even via de mail laten sturen. Ik dacht dat dat al gebeurde bij errors bijkbaar niet. Nu monitor ik ff alle calls :)
Ik bedoel eigenlijk direct loggen in een file.

cron_commando > path_to_logfile 2>&1

Acties:
  • 0 Henk 'm!

  • Saven
  • Registratie: December 2006
  • Laatst online: 07:59

Saven

Administrator

Topicstarter
Thanks via mail en via log krijg ik t zelfde:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
.....|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [text/html]
Saving to: &#8220;/dev/null&#8221;

     0K .......... .......... .......... .......... ..........  186M
    50K .......... .......... .......... .......... ..........  263M
   100K .......... .......... .......... .......... ..........  224M
   150K .......... .......... .......... .......... ..........  415M
   200K .......... .......... .......... .......... ..........  529M
   250K .......... .......... .......... .......... ..........  321M
   300K .......... .......... .......... .......... ..........  312M
   350K .......... .......... .......... .......... ..........  324M
   400K .......... .......... .......... .......... ..........  208M
   450K .......... .......... .......... .......... ..........  529M
   500K .......... .......... .......... .......... ..........  353M
   550K .......... .......... .......... .......... ..........  392M
   600K .......... .......... .......... .......... ..........  393M
   650K .......... .......... .......... .......... ..........  345M
   700K .......... .......... .......... .......... ..........  387M
   750K .......... .......... .......... .......... ..........  285M
   800K .......... .......... .......... .......... ..........  326M
   850K .......... .......... .......... .......... ..........  442M
   900K .......... .......... .......... .......... ..........  670M
   950K .......... .......... .......... .......... ..........  817M
  1000K .......... .......... .......... .......... ..........  601M
  1050K .......... .......... .......... .......... ..........  610M
  1100K .......... .......... .......... .......... ..........  799M
  1150K .......... .......... .......... .......... ..........  829M
  1200K .......... .......... .......... .......... ..........  461M
  1250K .......... .......... .......... .......... ..........  793M
  1300K .......... .......... .......... .......... ..........  780M
  1350K .......... .......... .......... .......... ..........  643M
  1400K .......... .......... .......... .......... ..........  823M
  1450K .......... .......... .......... .......... ..........  492M
  1500K .......... .......... .......... .......... ..........  806M
  1550K .......... .......... .......... .......... ..........  763M
  1600K .......... .......... .......... .......... ..........  469M
  1650K .......... .......... .......... .......... ..........  779M
  1700K .......... .......... .......... .......... ..........  780M
  1750K .......... .......... .......... .......... ..........  562M
  1800K .......... .......... .......... .......... ..........  423M
  1850K .......... .......... .......... .......... ..........  304M
  1900K .......... .......... .......... .......... ..........  114M
  1950K .......... .......... .......... .......... ..........  345M
  2000K .......... .......... .......... .......... ..........  358M
  2050K .......... .......... .......... .......... ..........  526M
  2100K .......... .......... .......... .......... ..........  482M
  2150K .......... .......... .......... .......... ..........  561M
  2200K .......... .......... .......... .......... ..........  594M
  2250K .......... .......... .......... .......... ..........  524M
  2300K .......... .......... .......... .......... ..........  568M
  2350K .......... .......... .......... .......... ..........  588M
  2400K .......... .......... .......... .......... ..........  406M
  2450K .......... .......... .......... .......... ..........  571M
  2500K .......... .......... .......... .......... ..........  597M
  2550K .......... .......... .......... .......... ..........  568M
  2600K .......... .......... .......... .......... ..........  607M
  2650K .......... .......... .......... .......... ..........  600M
  2700K .......... .......... .......... .......... ..........  575M
  2750K .......... .......... .......... .......... ..........  599M
  2800K .......... .......... .......... .......... ..........  420M
  2850K .......... .......... .......... .......... ..........  679M
  2900K .......... .......... .......... .......... ..........  711M
  2950K .......... .......... .......... .......... ..........  669M
  3000K .......... .......... .......... .......... ..........  820M
  3050K .......... .......... .......... .......... ..........  791M
  3100K .......... .......... .......... .......... ..........  692M
  3150K .......... .......... .......... .......... ..........  825M
  3200K .......... .......... .......... .......... ..........  596M
  3250K .......... .......... .......... .......... ..........  827M
  3300K .......... .......... .......... .......... ..........  790M
  3350K .......... .......... .......... .......... ..........  831M
  3400K .......... .......... .......... .......... ..........  794M
  3450K .......... .......... .......... .......... ..........  723M
  3500K .......... .......... .......... .......... ..........  783M
  3550K .......... .......... .......... .......... .......... 74.0M
  3600K .......... .......... .......... .......... ..........  127M
  3650K .......... .......... .......... .......... ..........  166M
  3700K .......... .......... .......... .......... ..........  173M
  3750K .......... .......... .......... .......... ..........  178M
  3800K .......... .......... .......... .......... ..........  177M
  3850K .......... .......... .......... .......... ..........  175M
  3900K .......... .......... .......... .......... ..........  177M
  3950K .......... .......... .......... .......... ..........  179M
  4000K .......... .......... .......... .......... ..........  123M
  4050K .......... .......... .......... .......... ..........  179M
  4100K .......... .......... .......... .......... ..........  179M
  4150K .......... .......... .......... .......... ..........  174M
  4200K .......... .......... .......... .......... ..........  181M
  4250K .......... .......... .......... .......... ..........  182M
  4300K .......... .......... .......... .......... ..........  175M
  4350K .......... .......... .......... .......... ..........  176M
  4400K .....                                                  61.5M=0.01s

2015-05-01 14:07:54 (336 MB/s) - &#8220;/dev/null&#8221; saved [4511385]

/var/log/cronsyncv2.log: Scheme missing.
FINISHED --2015-05-01 14:07:54--
Downloaded: 1 files, 4.3M in 0.01s (336 MB/s)


wat zijn al die regels daar? :X

Die finished is als laatste idd,
daarvoor zijn er nog een shitload aan echo's die hele lange string bevatten :P

Acties:
  • 0 Henk 'm!

  • Keiichi
  • Registratie: Juni 2005
  • Laatst online: 13-10 14:20
Ik heb dit als crontab:

*/5 * * * * flock -n /tmp/lock.cron.blaat php blaat.php

Als /tmp/lock.cron.blaat gelocked is, voert flock 'php blaat.php' niet uit.

Solar @ Dongen: http://solar.searchy.net/ - Penpal International: http://ppi.searchy.net/


Acties:
  • 0 Henk 'm!

  • Voutloos
  • Registratie: Januari 2002
  • Niet online
En er zit ook nog een race condition tussen de file_exists() en fwrite().

Ja, die kans zou klein moeten zijn, maar je kan er maar beter voor zorgen dat er in je implementatie nooit een dergelijke race zit.

{signature}


Acties:
  • 0 Henk 'm!

  • T-MOB
  • Registratie: Maart 2001
  • Laatst online: 14-10 18:22
Om die race-conditie te voorkomen kun je in PHP voor zover ik weet het beste mkdir() gebruiken voor lock "files".

Regeren is vooruitschuiven


Acties:
  • 0 Henk 'm!

  • Voutloos
  • Registratie: Januari 2002
  • Niet online
Oftewel zoek iets wat standaard atomic aangeboden wordt, want in user space kom je er niet zomaar uit. ;)

{signature}


Acties:
  • 0 Henk 'm!

  • T-MOB
  • Registratie: Maart 2001
  • Laatst online: 14-10 18:22
Ja dat bedoel ik te zeggen: mkdir() is vziw de enige standaardfunctie die atomic werkt.

Over het issue van TS: unlink() verwijdert niet als een bestand in gebruik is. Ik weet niet of je letterlijk code hebt gekopieerd voor in het topic of dat je speciaal iets bij elkaar gezet hebt qua voorbeeld. Maar controleer of in de code die uitgevoerd wordt wel echt fclose($myfile) wordt aangeroepen voor de unlink, en zorg dat je niet zelf je lockfile nog ergens hebt geopend.

Regeren is vooruitschuiven


Acties:
  • 0 Henk 'm!

  • Donderpoes
  • Registratie: April 2011
  • Laatst online: 11-05 23:09
Wat die regels zijn weet ik niet.

Ik doe het zelf altijd zo:

PHP:
1
fopen("/path/to/file/filename.lock", "w");


En aan het einde van mijn script zet ik

PHP:
1
unlink("/path/to/file/filename.lock");


Ik schrijf er niets in weg en kijk alleen maar of de file bestaat. Tot nu toe nog nooit problemen gehad.

Acties:
  • 0 Henk 'm!

  • T-MOB
  • Registratie: Maart 2001
  • Laatst online: 14-10 18:22
Donderpoes schreef op vrijdag 01 mei 2015 @ 16:13:
Wat die regels zijn weet ik niet.

Ik doe het zelf altijd zo:
[knip]
Ik schrijf er niets in weg en kijk alleen maar of de file bestaat. Tot nu toe nog nooit problemen gehad.
Het probleem wat je hebt als je met file_exists en fopen aan de gang gaat is dat je de file aanmaakt nadat je hebt gecontroleerd of ie bestaat. In theorie kan het zo zijn dat er op exact hetzelfde moment twee instanties van het script tot de conclusie komen dat het bestand niet bestaat. Dan zullen ze allebei doorgaan met alle narigheid van dien. Zo'n situatie noemen ze een race conditie.
Als het er om gaat om een cron job niet opnieuw te laten starten als de oude nog loopt zal dit niet voorkomen. In een druk bezochte site des te eerder.

Zelf gebruik ik iets als dit om met locks om te gaan.
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
 * Simple locking mechanism using mkdir()
 */
class Lock {

    private static function _getPath($name) {
        return DATA_DIR .'lock_'.md5($name);    
    }

    public static function acquire($name) {
        return mkdir(self::_getPath($name));
    }

    public static function exists($name) {
        return is_dir(self::_getPath($name));
    }

    public static function release($name) {
        return @rmdir(self::_getPath($name));
    }
}

Regeren is vooruitschuiven


Acties:
  • 0 Henk 'm!

  • Donderpoes
  • Registratie: April 2011
  • Laatst online: 11-05 23:09
T-MOB schreef op vrijdag 01 mei 2015 @ 17:14:
[...]

Het probleem wat je hebt als je met file_exists en fopen aan de gang gaat is dat je de file aanmaakt nadat je hebt gecontroleerd of ie bestaat. In theorie kan het zo zijn dat er op exact hetzelfde moment twee instanties van het script tot de conclusie komen dat het bestand niet bestaat. Dan zullen ze allebei doorgaan met alle narigheid van dien. Zo'n situatie noemen ze een race conditie.
Als het er om gaat om een cron job niet opnieuw te laten starten als de oude nog loopt zal dit niet voorkomen. In een druk bezochte site des te eerder.

Zelf gebruik ik iets als dit om met locks om te gaan.
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
 * Simple locking mechanism using mkdir()
 */
class Lock {

    private static function _getPath($name) {
        return DATA_DIR .'lock_'.md5($name);    
    }

    public static function acquire($name) {
        return mkdir(self::_getPath($name));
    }

    public static function exists($name) {
        return is_dir(self::_getPath($name));
    }

    public static function release($name) {
        return @rmdir(self::_getPath($name));
    }
}
Je hebt helemaal gelijk!

Maar TS zegt dat de cron elke vijf minuten gestart wordt. Binnen die vijf minuten zou de file toch wel aangemaakt moeten zijn.

Mocht er om een dubieuze rede de cron 2x gelanceerd worden, kan het inderdaad mis gaan.

Acties:
  • 0 Henk 'm!

  • Barryvdh
  • Registratie: Juni 2003
  • Laatst online: 10:27
T-MOB schreef op vrijdag 01 mei 2015 @ 17:14:
[...]

Het probleem wat je hebt als je met file_exists en fopen aan de gang gaat is dat je de file aanmaakt nadat je hebt gecontroleerd of ie bestaat. In theorie kan het zo zijn dat er op exact hetzelfde moment twee instanties van het script tot de conclusie komen dat het bestand niet bestaat. Dan zullen ze allebei doorgaan met alle narigheid van dien. Zo'n situatie noemen ze een race conditie.
Als het er om gaat om een cron job niet opnieuw te laten starten als de oude nog loopt zal dit niet voorkomen. In een druk bezochte site des te eerder.

Zelf gebruik ik iets als dit om met locks om te gaan.
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
 * Simple locking mechanism using mkdir()
 */
class Lock {

    private static function _getPath($name) {
        return DATA_DIR .'lock_'.md5($name);    
    }

    public static function acquire($name) {
        return mkdir(self::_getPath($name));
    }

    public static function exists($name) {
        return is_dir(self::_getPath($name));
    }

    public static function release($name) {
        return @rmdir(self::_getPath($name));
    }
}
Maar zodra je die Lock::exists() gebruikt, is je operatie niet meer atomic toch?

Dus eigenlijk wil je exists() niet gebruiken, maar meer zoiets:

PHP:
1
2
3
4
5
6
if (Lock::acquire('heavytask')) {
    // do heavy task
    Lock::release('heavytask');
} else {
    // Log that we didn't get a lock and ignored this..
}


Maar omdat mkdir een warning geeft als hij al bestaat, zul je die moeten onderdrukken.

PHP:
1
2
3
public static function acquire($name) {
    return @mkdir(self::_getPath($name));
}


Meer over atomic/locking http://wiki.bash-hackers.org/howto/mutex

(Maar waarschijnlijk bedoelde je dat ook, alleen vanuit het eerste voorbeeld zou je misschien concluderen dat je alsnog de exists gebruikt.)

Edit: is de standaard flock() functie hier niet voor bedoeld eigenlijk? Bijv. http://stackoverflow.com/...on-in-cron-file-lock-safe

PHP:
1
2
3
4
5
6
7
8
9
10
11
$fp = fopen("/tmp/lock.txt", "w+");

if (flock($fp, LOCK_EX | LOCK_NB)) { // do an exclusive lock
    // do the work

    flock($fp, LOCK_UN); // release the lock
} else {
    echo "Couldn't get the lock!";
}

fclose($fp);

[ Voor 11% gewijzigd door Barryvdh op 01-05-2015 20:21 ]


Acties:
  • 0 Henk 'm!

  • Cartman!
  • Registratie: April 2000
  • Niet online
Barryvdh schreef op vrijdag 01 mei 2015 @ 20:12:
Edit: is de standaard flock() functie hier niet voor bedoeld eigenlijk? Bijv. http://stackoverflow.com/...on-in-cron-file-lock-safe

PHP:
1
2
3
4
5
6
7
8
9
10
11
$fp = fopen("/tmp/lock.txt", "w+");

if (flock($fp, LOCK_EX | LOCK_NB)) { // do an exclusive lock
    // do the work

    flock($fp, LOCK_UN); // release the lock
} else {
    echo "Couldn't get the lock!";
}

fclose($fp);
Ik heb al meerdere hostingpartijen meegemaakt waar dat niet werkte. Het enige wat bij mij goed werkte is een record wegschrijven in een transactie en als dat niet lukte (unique constraint) dan doet ie niks. Nadat ie klaar is gewoon t record weer weghalen.

Acties:
  • 0 Henk 'm!

  • Barryvdh
  • Registratie: Juni 2003
  • Laatst online: 10:27
Cartman! schreef op vrijdag 01 mei 2015 @ 20:38:
[...]

Ik heb al meerdere hostingpartijen meegemaakt waar dat niet werkte. Het enige wat bij mij goed werkte is een record wegschrijven in een transactie en als dat niet lukte (unique constraint) dan doet ie niks. Nadat ie klaar is gewoon t record weer weghalen.
Enig idee waarom het dan fout gaat?

mkdir lijkt wel aardig te werken bij mij iig. Wel even tijd verpest doordat Chrome maar 1 verbinding tegelijk maakt, dus 2 browserschermen testen werkt niet, dan wachten ze al op elkaar :+ (Maar 1 in incognito modus werkt wel)

Heb er zoiets van gemaakt, omdat ik ook wou wachten totdat de lock beschikbaar kwam eventueel.

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
class Lock
{
    /** @var string The name of the dir to use as lock */
    private $dir;

    /**
     * Create a new lock instance for a given key.
     *
     * @param $key
     */
    public function __construct($key)
    {
        $this->dir = __DIR__ .'/../storage/locks/'.md5($key).'.lock';
    }

    /**
     * Try to acquire a lock. Can optionally wait a given time when already locked.
     *
     * @param  int  $wait  Time in seconds to keep waiting for a lock
     * @return bool
     */
    public function acquire($wait = 0)
    {
        $time = 0;

        do {
            $locked = $this->attemptAcquireLock();

            if ($locked || !$wait) {
                return $locked;
            }

            sleep(1);
            $time++;
        } while ($time <= $wait);

        return false;
    }

    /**
     * Release the lock so other processes can continue;
     */
    public function release()
    {
        @rmdir($this->dir);
    }

    /**
     * Attempt to acquire a lock by creating a new directory.
     * When the directory already exists, the lock is already in place.
     *
     * @return bool
     */
    private function attemptAcquireLock()
    {
        return @mkdir($this->dir);
    }
}

$lock = new Lock('heavy-task');
if ($lock->acquire(60)) {
    // Do the heavy lifting
    $lock->release();
} else {
    echo "Lock failed..";
}

Acties:
  • 0 Henk 'm!

  • Cartman!
  • Registratie: April 2000
  • Niet online
Barryvdh schreef op vrijdag 01 mei 2015 @ 22:10:
[...]

Enig idee waarom het dan fout gaat?
Wat ik gelezen heb is dat op (sommige?) filesystems locking slechts n advies is en dus niet gegarandeerd. Vooral via NFS en SMB kan t problemen geven ook. Database heeft mij nooit gefaald daarna omdat innodb atomic is.

Acties:
  • 0 Henk 'm!

  • T-MOB
  • Registratie: Maart 2001
  • Laatst online: 14-10 18:22
Donderpoes schreef op vrijdag 01 mei 2015 @ 19:12:
[...]


Je hebt helemaal gelijk!

Maar TS zegt dat de cron elke vijf minuten gestart wordt. Binnen die vijf minuten zou de file toch wel aangemaakt moeten zijn.

Mocht er om een dubieuze rede de cron 2x gelanceerd worden, kan het inderdaad mis gaan.
Wat mij betreft zijn er twee discussies. De eerste is hoe je een goede lock / mutex maakt. De tweede is waarom de ts problemen heeft. Die mutex is waar mijn code voorbeeldje van komt. Exists() gebruik je daar niet om te checken voor je acquire() aanroept. Ik heb overigens ook nog age() beschikbaar om oude locks / errors te detecteren. Voor zover ik weet triggered mkdir ook geen warning bij failure.

Het probleem van ts staat verder los van hoe je een lock implementeert. Daar gaat iets mis met het filesystem. Voor zover ik php interpreteer klopt het code voorbeeld uit de ts. Maar als het alleen een versimpeld voorbeeld is kun filesystem issues hebben waarvoor clearstatcache() soelaas kan bieden. Of het gaat mis omdat se topicstarter zelf de lockfile open houdt om te debuggen. Dan werkt unlink() namelijk niet...

Regeren is vooruitschuiven


Acties:
  • 0 Henk 'm!

  • Saven
  • Registratie: December 2006
  • Laatst online: 07:59

Saven

Administrator

Topicstarter
Sorry voor de late reactie, en dat ik niemand ff quote.

Maar de file lijkt nu spookachtig te worden aangemaakt :')

Zelfs als de actie niet wordt uigevoerd, verschijnt de file om de 5 minuten in de map _O-

Daar moet i kdus even induiken
Pagina: 1