A PHP weben használva egy nagyon hasznos találmány, parancssorban használva pedig mindennapi életünket könnyítheti meg. A PHP-t ráadásul felkészítették ilyen felhasználásra is, tovább segítve a programozót.
A lehetőségek bemutatását egy kódon keresztül, elsődlegesen Windows platformon mutatom be, Linux alatt kicsit egyszerűbb is az életünk. Ugyanis hogy igazán jó eszköz legyen a kezünkben, egy kicsit bele kell nyúlnunk a Windowsunkban. Hogy megértsük, miért is szükséges a következő pár lépés, menjünk először a Start menü Futtatás elemére, írjuk be, cmd és üssünk entert. Megnyílt a parancssor, amit a C:\Windows\System32 mappában van. Ezt az elérési utat a Windows a Path nevű ún. Környezeti változóból vette, ezt fogjuk szerkeszteni, hogy a PHP-t is megtalálja.
Ha már itt vagyunk, írjuk be a parancssorba, hogy Path, majd üssünk egy entert. Figyeljük meg, hogy minden elem ; jelekkel van elválaszva, és minden útvonal C:\-val kezdődik (nem baj, ha mégsem, ez a lényeg)!
Mielőtt tovább megyünk, egy fontos dolog: legtöbbünk gépén a WAMP szentháromság egy programcsomagként került fel (Xampp, EasyPHP, …), ami a webes fejlesztésekhez tökéletes, CLI-hez hackelni kéne (valószínűleg más php.ini-t használnánk a két környezetben), úgyhogy töltsük le a legújabb Windows futtatható állományokat a php.net-ről, majd tömörítsük ki egy mappába (a telepítő állományt is használhatjuk, csak jegyezzük fel, hova telepítettük). (A következőkben feltételezem, hogy a C:\Program Files\PHP 5 könyvtárba telepítettünk)
A telepítés/kitömörítés végeztével kattintsunk a Sajátgépen (My Computer) jobb gombbal, menjünk a Tulajdonságok (Properties) elemre. A megnyíló ablakban válasszuk a Speciális (Advanced) fület, majd a Környezeti Változók (Environment Variables) gombra kattintva megnyíló ablakban keressük meg a Path változót, duplaklikkeljünk rajta, majd a végére illesszük be a PHP-n elérési útvonalát! Ha a rendszermeghajtónkra (C:) telepítettük, akkor a meghajtó betűjele helyett használjuk a %systemdrive% helyettesítő karakterfüzért! Kattintsunk az OK gombra, és zárjuk be a Rendszertulajdonságok (System Properties) ablakot! A fenti módon nyissunk egy Parancssort, és ellenőrizzük, hogy a Path-ben szerepel-e a PHP elérési útja!
Egyszerűen társíthattuk volna a php.exe-hez a .php fájlokat, viszont így bárhonnan egyszerűen hívhatóak parancssorból, és továbbra a kedvenc szerkesztőnk nyílik meg egy php fájl kiválasztására. A leírás elején írtam, hogy Linuxszal egyszerűbb a dolgunk: egyszerűen beírjuk a fájl első sorába a PHP értelmező elérési útját, innentől kezdve a fájlunk, mint bármilyen shell script, futtatható. Például:
1 2 3 4 | #!/usr/bin/php <?php print file_get_contents("hello.txt"); ?> |
És hogy ez mire használható? Nézzük a következő kódot:
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 | #!/usr/bin/php <?php $filename = array('Folder.jpg', 'Cover.jpg'); $outfile = 'Folder.jpg'; if(!(IsSet($stdout) && is_resource($stdout))) { $stdout = fopen('php://stdout', 'w'); } function find($path, $filename) { $dir = opendir($path); while($object = readdir($dir)) { if($object == '.' || $object == '..') continue; if(Is_dir($path . '/' . $object)) { find($path . '/' . $object, $filename); } if(Is_file($path . '/' . $object) && ((Is_string($filename) && $object == $filename) || Is_array($filename) &&; in_array($object, $filename))) { $GLOBALS['files'][] = $path . '/' . $object; } } } find('.', $filename); $min = 10000; foreach($GLOBALS['files'] as $file) { $size = getimagesize($file); if($size[0] < $min) { $min = $size[0]; } } foreach($GLOBALS['files'] as $file) { $orig = imagecreatefromstring(file_get_contents($file)); $new = imagecreatetruecolor($min, imagesy($orig) * ($min / imagesx($orig))); imagecopyresampled($new, $orig, 0, 0, 0, 0, imagesx($new), imagesy($new), imagesx($orig), imagesy($orig)); imagejpeg($new, dirname($file) . '/' . $outfile, 100); fwrite($stdout, $file . " resized to " . dirname($file) . '/' . $outfile . " (" . imagesx($orig) . "x" . imagesy($orig) . " to " . imagesx($new) . "x" . imagesy($new) . ")\r\n"); imagedestroy($new); imagedestroy($orig); } ?> |
Hogy egyértelmű legyen: a kódot azért írtam, hogy a Folder.jpg fájljaim egységes méretűek legyenek (mindig akkora, mint a legkisebb ilyen kép), és hogy ne kelljen őket „kézzel” méretezgetni. Életszerű példa, ráadásul néha jól tud jönni. A legfontosabb PHP-CLI tulajdonságokat be lehet vele mutatni:
Standard input, output, error
Parancssori programozásnál három kiemelt streamünk van (C-ben például az stdio.h header tartalmazza ezeket): az stdin (bemenet, többnyire billentyűzet), stdout (kimenet, többnyire képernyő), stderr (hibaüzeneteknek, többnyire képernyő). Mindenhol a „többnyire” kifejezést használtam, mivel ezeket módosítani lehet (nem mennék nagyon bele, amit használni fogunk: > az stdout-ot egy fájlba irányítja, < az stdin-t egy fájlból veszi, a |, ami az első program kimenetét adja a második program bemenetéül és a >> ami az stderr-t küldi egy fájlba).
Ha a fenti kódot megnézzük, láthatjuk, hogy egy megfelelően bonyolult könyvtárszerkezettel iszonyatos mennyiségű kiemenetet adhat, de mivel ez a kimenet fontos lehet, érdemes otthagyni a kódban. Ha nem akarjuk nézni, akkor egyszerűen kiadjuk ezt az utasítást:
php folders.php > output.txt
Azonban hogy az élet ne legyen ilyen egyszerű, a streamek – a Kézikönyv által írottak ellenére – nem mindig állnak rendelkezésünkre futáskor, így érdemes így kezdeni a kódjainkat:
1 2 3 4 5 | #!/usr/bin/php <?php $stdin = (IsSet($stdin) && Is_resource($stdin)) ? $stdin : fopen("php://stdin", "r"); $stdout = (IsSet($stdout) && Is_resource($stdout)) ? $stdout : fopen("php://stdout", "w"); $stderr = (IsSet($stderr) && Is_resource($stderr)) ? $stderr : fopen("php://stdout", "w"); |
Az átirányítások használatával készíthetünk például egy Back-up scriptet:
1 2 3 | while($filename = trim(fgets($stdin))) { /* Felmásoljuk FTP-vel a fájlt */ } |
Így csinálhatjuk „kézzel”, elindítjuk a back-up scriptünket, kézzel beírogatjuk a fájlneveket, az meg szépen menti, vagy akár írhatunk egy fájllistát (legyen pl. fajlok.txt) és meghívhatjuk így is:
php backup.php > fajlok.txt
Ezzel már csinálhatunk egy ütemezett feladatot is (ekkor inkább a php-win.exe-t használjuk, az nem nyit parancssor ablakot), ami mondjuk 12 óránként elmenti a fontos fájljainkat. (Részleteket lássuk lentebb!)
Elérési utak
A következő dolog, amit érdemes megjegyeznünk, hogy parancssorból indításkor mindig az aktuális elérési utat használja a PHP, nem azt, ahol a .php fájl van. Hogy ez mit jelent: tegyük fel, hogy a parancssori scriptjeink a C:\Scripts\ mappában vannak, a parancssorban jelenleg a C:\Documents and Settings\Rendszergazda\Dokumentumok\Zene mappában vagyunk.
C:\Documents and Settings\Rendszergazda\Dokumentumok\Zene>php C:\Scripts\Folder.jpg.php > Output.txt
Ez a Zene mappán belül levő összes Folder.jpg fájlt nézi át, az Output.txt is a Zene mappába kerül. Ha megfigyeljük, relatív útvonalról kezdjük a kerestetést (a példában ez a Zene mappa):
find('.', $filename);
Ha ezután átmegyünk a Zene mappából a Filmek mappába, és ott is lefutatjuk, akkor a Filmek mappában levő Folder.jpg-ket méretezi át a kód.
Parancssori paraméterek
Jó szolgálatot tehetnek még az ún. parancssori paraméterek. Ezek azok a paraméterek, amelyeket szóközzel elválasztva szoktunk felsorolni utasítások kiadásakor (pl.: shutdown -r -c „Leállítjuk a gépet!”). Vagyük a következő példát: van egy kódunk, ami készít egy SQL mentést az adatbázisunkról. Általánosabbá tehetjük, ha az adatbázis nevét parancssori paraméterből veszi.
Ezeket a paramétereket az $argv nevű tömbből szerezhetjük meg (az elnevezésről annyit, hogy a C-ben a main függvénynek (ami a program indulásakor meghívásra kerül) nulla (void) vagy két paramétere lehet (int argc, char **argv), az első megadja a paraméterek számát, a második magukat a paramétereket). Hogy ez mit jelent: mentsük el a következő fájlt param.php néven és futassuk le:
1 2 3 4 | #!usr/bin/php <?php var_dump($argv); ?> |
A kimenete a következő lesz:
array(1) {
[0]=>
string(9) „param.php”
}
(Lesz még egy $argc változónk is, de PHP-ben nem valószínű, hogy túlindexelünk egy tömböt és segmens hibával leáll a programunk)
Ha php param.php -r now néven hívjuk, akkor ugyanez a kód a
array(3) {
[0]=>
string(9) „param.php”
[1]=>
string(2) „-r”
[2]=>
string(3) „now”
}
kimenetet adja.
Így már egyszerűen módosíthatjuk a DBBackup.php kódunkat, a
1 | mysql_select_db('adatbazisom'); |
helyett
1 2 3 4 | if(!@mysql_select_db($argv[1])) { fwrite($stderr, "Database (" . $argv[1] . ") not found!"); exit(); } |
írva meg is vagyunk. Ezután időzítjük a kódjainkat (mondjuk a „nagyoldal” nevű adatbázist 2 óránként mentjük, ott fontos adatok vannak és gyakran változnak, a „bezartforum” adatbázist (amelynél csak a látogatói statisztika frissül néha) két naponta).
Ütemezés Windows alatt
(Megjegyzés: Linux alatt ütemezhetjük a programjainkat a crontab használatával)
Tegyük fel, hogy szeretnénk a fenti Folder.jpg.php fájlunkat lefutattni minden héten egyszer, mondjuk vasárnap délután. Tegyük fel továbbá, hogy a kód a C:\Scripts mappában van, a célmappa pedig továbbra is a C:\Documents and Settings\Rendszergazda\Dokumentumok\Zene mappa.
Menjünk a Vezérlőpultba (Control Panel), ott válasszuk az Ütemezett Feladatok (Task Scheduler) elemet. A varázsló sajnos buta egy csöppet, így kézzel kell csinálnunk. A megnyíló ablakban üres helyen kattintsunk a jobb gombbal, Új (New), majd Ütemezett Feladat (Task) elemet. Írjunk be valami nevet (pl.: Folder.jpg), majd duplaklikkeljünk az új elemre. A Futtatás (Run) mezőbe írjuk be:
„C:\Program Files\PHP 5\php-win.exe” C:\Scripts\Folder.jpg.php
A futtatás helyéhez a
C:\Documents And Settings\Rendszergazda\Dokumentumok\Zene
útvonalat, majd jelöljük be a „Futtatás csak akkor, ha be van jelentkezve” mezőt, az Ütemezés (Schedule) fül alatt válasszuk a Hetente (Weekly) elemet, válasszuk ki a V feliratú mezőt, Kezdés időpontjának pedig mondjuk 13:00-t. Amint leokéztuk, az ütemezés életbe lép, és minden vasárnap rendezi a Folder.jpg fájljainkat.
(Sajnos az átirányításokra csak a command promtból van lehetőség, így ha ezt használni szeretnénk, akkor közbe kell iktatnunk egy .bat fájl, például:
@echo off
"C:\Program Files\PHP 5\php.exe" C:\Scripts\Folder.jpg.php > out.txt
@echo on
Ezt elmentve valami.bat-ként és a Futtatás mezőbe a bat fájl nevét írjuk, akkor már használhatunk átirányítást, csak csúnya megoldás)
Összefoglalás
A PHP parancssori nyelvként használva nagyon megkönnyítheti a mindennapi adminisztrációt, tanulmányokat (előfordult, hogy ilyen szkripttel töltettem le az egyik kurzus anyagát az előadó weboldaláról, mert lusta voltam kattintgatni a Firefoxban) stb. A PHP-GTK kiegészítve pedig az egyik leghasznosabb eszközünkké válhat.
(További – néhol talán felesleges – információkat a PHP kézikönyv Parancssori programozás a PHP-ben oldalán találhatunk)
Ha pedig a kész programunkat olyan jónak itéljük, meg, hogy megosztjuk a világgal megtehetjük. Bonyolult telepitési és egyébb macerák nélkül windowsos .exe formátumban a Bambalam nagysikerü forditójával:
http://www.bambalam.se/bamcompile/
Egyenlőre csak php4 -et tud, de ez ne zavarjon minket, nagyon bonyolult kódot úgy sem irunk.
A php windowson való grafikus felület kiegészitésére pedig tökéletes a WinBinder
http://winbinder.org/
Köszi a linkeket, majd átnézem őket! (Bár bamcompile PHP 5 supportig szvsz. felejtős…)
A közeljövőben még írok egy nagyon gyors és felületes tutorialt a PHP-GTK-ról (a példaprogi már meg is van, fut is folyamatosan a gépemen, és iszonyat idegölő, de pont ez volt a cél), utána rendesen átnézem/próbálgatom a winbindert és talán abból is lesz leírás.
BlackY
Wow, nagyon jó ez a leírás, köszönjük!
Sziasztok!
Suse linux szerveren próbáltam ki a fent leírtakat. A php script első sorába beírtam: #!usr/bin/php, indítottam a scriptet, és ezt írta ki:
bash: /srv/www/htdocs/bmb/rssSave.php: cannot execute binary file
Mi lehet a probléma?
Első körben, hogy a kezdeti / nélkül az relatív útvonal lenne. Ha /usr/bin/php-ben sem indul, akkor meg kell keresned, hogy hol van a php indítófájlja (php):
utasítás elvileg megmondja.
BlackY
Kösz BlackY, kipróbáltam, és a keresés a következő utat adta:
/var/lib/rpm/alternatives/php
Ezt beírva a php script első sorába (kiegészítve a #!-al persze) a hibaüzenet a következő:
” bad interpreter: No such file or directory”.
Ugyanakkor a scriptet, ha kiveszem belőle az általam beírt első sort, akkor minden további nélkül tudom futtatni a parancssorból a
php -f „scriptnev”
parancssal.
Valamit az elérési útvonal megadásával nagyon benézek, csak nem tudom, hogy mit.