Drupal futtatása parancssorból (azaz CLI-ből)

edgarpe képe

Miért is akarjunk mi parancssorból Drupal-t futtatni? Például akkor hasznos ha egy import szkirptet írunk, ami nagyon sokáig is futhat. Vagy ha a futás kimenete olyan információ, amit aztán a linux parancssorból vagy egy bash scriptben akarunk felhasználni.

Oké, van nekünk Batch API-nk a hosszú futásokhoz, meg Drush is van a CLI-hez. De azért nézzük meg , mit tudunk kezdeni egy egyszerű php fájllal.

Először is érdemes belepillantani a Drupal index.php-ba, a cron.php-va, ha még nem tettük meg. Kiderül, hogy ezek faék egyszerű fájlok, így aztán innen fogunk puskázni.

Első naiv próbálkozás

Legyen a cli.php fájl tartalma ez:

<span style="color: #000000"><span style="color: #0000BB">&lt;?php<br />define</span><span style="color: #007700">(</span><span style="color: #DD0000">'DRUPAL_ROOT'</span><span style="color: #007700">, </span><span style="color: #0000BB">getcwd</span><span style="color: #007700">()); <br />include_once </span><span style="color: #0000BB">DRUPAL_ROOT </span><span style="color: #007700">. </span><span style="color: #DD0000">'/includes/bootstrap.inc'</span><span style="color: #007700">; <br /></span><span style="color: #0000BB">drupal_bootstrap</span><span style="color: #007700">(</span><span style="color: #0000BB">DRUPAL_BOOTSTRAP_FULL</span><span style="color: #007700">); <br /></span><span style="color: #0000BB">?&gt;</span></span>

Futtassuk így:
# php cli.php

Rögtön kapunk is egy csomó hibát, mert nem létezik a REMOTE_ADDR kulcs egy tömbben. Ez a tömb nem lehet más, csak a $_SERVER. Érthető is, hiszen nem böngészőből hívjuk meg a scriptet. Javítsuk ezt a hibát azzal, hogy pótoljuk ezt az értéket.

<span style="color: #000000"><span style="color: #0000BB">&lt;?php<br />$_SERVER</span><span style="color: #007700">[</span><span style="color: #DD0000">'REMOTE_ADDR'</span><span style="color: #007700">] = </span><span style="color: #DD0000">'127.0.0.1'</span><span style="color: #007700">; <br /></span><span style="color: #0000BB">?&gt;</span></span>

Tegyünk egy kis óvintézkedést, és állítsuk le a szkript futását, ha nem parancssorból futtatjuk. Ezt így tehetjük meg:

<span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /></span><span style="color: #007700">if (</span><span style="color: #0000BB">php_sapi_name</span><span style="color: #007700">() !== </span><span style="color: #DD0000">'cli'</span><span style="color: #007700">) { <br />&nbsp; exit(</span><span style="color: #0000BB">1</span><span style="color: #007700">); <br />} <br /></span><span style="color: #0000BB">?&gt;</span></span>

Ezzel teljesen kizárjuk a webszervert, így a legtöbb biztonsági kockázatnak elejét vettük.

A teljes kód

Nos nagyjából ennyi, a teljes kód mindössze ennyi:

<span style="color: #000000"><span style="color: #0000BB">&lt;?php<br />define</span><span style="color: #007700">(</span><span style="color: #DD0000">'DRUPAL_ROOT'</span><span style="color: #007700">, </span><span style="color: #0000BB">getcwd</span><span style="color: #007700">()); <br /><br />if (</span><span style="color: #0000BB">php_sapi_name</span><span style="color: #007700">() !== </span><span style="color: #DD0000">'cli'</span><span style="color: #007700">) { <br />&nbsp; exit(</span><span style="color: #0000BB">1</span><span style="color: #007700">); <br />} <br /><br /></span><span style="color: #0000BB">$_SERVER</span><span style="color: #007700">[</span><span style="color: #DD0000">'REMOTE_ADDR'</span><span style="color: #007700">] = </span><span style="color: #DD0000">'127.0.0.1'</span><span style="color: #007700">; <br /><br />include_once </span><span style="color: #0000BB">DRUPAL_ROOT </span><span style="color: #007700">. </span><span style="color: #DD0000">'/includes/bootstrap.inc'</span><span style="color: #007700">; <br /></span><span style="color: #0000BB">drupal_bootstrap</span><span style="color: #007700">(</span><span style="color: #0000BB">DRUPAL_BOOTSTRAP_FULL</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">?&gt;</span></span>

Ezután bármit megtehetünk a kis php szkriptben. Például meghívhatunk egy hook-ot minden modulban így:

<span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /> module_invoke_all</span><span style="color: #007700">(</span><span style="color: #DD0000">'xmlrpc'</span><span style="color: #007700">); <br /></span><span style="color: #0000BB">?&gt;</span></span>

Vagy bármely modul egy tetszőleges függvényét így:

<span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /> import_modulom_import_fuggvenye</span><span style="color: #007700">(); <br /></span><span style="color: #0000BB">?&gt;</span></span>

Fontos, hogy kinek a nevében fut!

Egy dologra viszont oda kell figyelni: a php-t futtató szerver felhasználó. Debian/Ubuntu rendszereken www-data az alapbeállítás, de szervertől függően ez bármi lehet. A fájlkezelés miatt fontos, ugyanis a fájlokat tartalmazó könyvtárban (pl.: sites/default/files) minden fájlnak a webszerver a tulajdonosa, ezzel lehet írni-olvasni a fájlokat. Ha mi egy másik felhasználó nevében futtatjuk a ki import php szkriptünket, ami mondjuk képeket is importál, akkor bizony az új vagy módosított fájloknak más lesz a tulajdonosa. És ez baj, mert akkor később a web-ről már nem tudjuk módosítani, vagy akár törölni ezeket.

Ezerféle módon megoldhatjuk ezt a problémát, a két legegyszerűbbet mutatom be.
Legjobb megoldás, ha a php-t a megfelelő felhasználó nevében futtatjuk. Ha pl. www-data nevében fut az Apache vagy másik webszerver, akkor így:

# sudo -u www-data php cli.php

Erre viszont nincs mindig lehetőség. Egyszerű, de nagyszerű megoldás az is, ha a cli.php futása után egyszerűen átadjuk a megfelelő felhasználónak a files könyvtár tartalmát:

# chown -R www-data sites/default/files

Ez az egész ötlet nekem egy importálás miatt kellett, és nagyon jól bevált. Remélem másnak is hasznos lesz.