string(3586) "

NAME

AF_AX25 - AX.25 amateur packet radio protocol family

DESCRIPTION

AX.25 is a protocol used extensively by radio amateurs. The Linux AX.25 protocol family permits access to these protocols via the standard networking socket metaphor.

The AX.25 protocol layer supports both connected mode and datagram (UI) frame modes. IP traffic may be stacked on top of AX.25 frames for IP transmission over the AX.25 medium.

The primary mode of operation is connected mode which is the mode used for a socket of type SOCK_SEQPACKET (stream sockets are not available in AX.25). This requires that the user ensures output data is suitably packetised, and that input data is read a packet at a time into a buffer of suitable size. The Linux AX.25 protocol layer can operate in standard AX.25 mode with three bit sequence numbers or in PE1CHL extended AX.25 mode which uses seven bit sequence numbers. The protocol passed to the socket is used for all outgoing frames. Passing 0 causes the normal AX.25 Text PID to be used.

SOCK_DGRAM gives access to AX.25 UI frames. For access to special frames (of any form) SOCK_RAW can be used. There is no SOCK_PACKET support under AX.25. Instead an AF_INET socket of type SOCK_PACKET should be used.

AX.25 addresses consist of 6 ascii characters and a number called the SSID. These are encoded into a sockaddr_ax25 structure which is provided to the relevant system calls. When digipeaters are included a callsign path can be much more complex. When this is the case a struct full_sockaddr_ax25 should be passed to the system calls.

AX.25 has some unusual properties. Notably in a multi-user system an AX.25 address is often associated with a user, and some users may not have such an association. a set of ioctl calls are provided to manage an association table, and in addition the superuser may use an arbitary callsign by binding to the callsign desired and specifying the port to use as a first digipeated hop.

AX.25 supports the following socket options for SOL_AX25. AX25_T1 is the T1 timer in 1/10ths of a second, AX25_T2 is the T2 timer in 1/10ths of a second, AX25_T3 is the T3 timer. The window is settable with AX25_WINDOW. AX25_N2, the retry counter is also configurable. There is no 'infinite retry' option supported however. The method of backoff for retries is configurable via the socket option AX25_BACKOFF, a value of true indicates the use of exponential backoff and false simple linear backoff. The mode of a connection made be altered to be either standard AX.25 or extended AX.25 via AX25_EXTSEQ. It is possible to have the complete AX.25 header returned to the application by setting AX25_HDRINCL to true, programs must be aware of the internal structure of AX.25 frames to use this option. Note that if AX.25 fragmentation is encountered, only the control information of the first frame is returned along with the defragmented data.

SEE ALSO

call(1), socket(2), setsockopt(2), getsockopt(2), axctl(8), axparms(5), axassociate(8), axparms(8), kissattach(8).

BUGS

Too numerous to list in full currently.

•
Minor protocol violations exist.

AUTHOR

Alan Cox GW4PTS <alan@cymru.net>


Jonathan Naylor G4KLX <g4klx@g4klx.demon.co.uk>
" array(1) { [0]=> object(LibXMLError)#6 (6) { ["level"]=> int(2) ["code"]=> int(1845) ["column"]=> int(0) ["message"]=> string(86) "Element 'litteral': No matching global declaration available for the validation root. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(1) } } string(1869) "

NAME

AF_ROSE - Rose amateur packet radio protocol family

DESCRIPTION

Rose is a protocol used extensively by radio amateurs. The Linux Rose protocol family permits access to these protocols via the standard networking socket metaphor.

The Rose protocol layer only supports connected mode.

The only mode of operation is connected mode which is the mode used for a socket of type SOCK_SEQPACKET (stream sockets are not available in Rose). This requires that the user ensures output data is suitably packetised, and that input data is read a packet at a time into a buffer of suitable size.

Rose addresses consist of 10 digits. These are encoded into a sockaddr_rose structure which is provided to the relevant system calls.

Rose has some unusual properties. Notably in a multi-user system an AX.25 address is often associated with a user, and some users may not have such an association. a set of ioctl calls are provided to manage an association table.

Rose supports the following socket options for SOL_ROSE. ROSE_T1 is the T11/T21 timer in 1/10ths of a second, ROSE_T2 is the T12/T22 timer in 1/10ths of a second. ROSE_T3, is the T13/T23 timer in 1/10ths of a second. It is possible for an application to request that the Rose layer return the Rose header as well as the application data, this is done via the ROSE_HDRINCL socket option.

SEE ALSO

call(1), socket(2), setsockopt(2), getsockopt(2), rsports(5), rsctl(8), rsparms(8).

AUTHOR

Jonathan Naylor G4KLX <g4klx@g4klx.demon.co.uk>

" array(2) { [0]=> object(LibXMLError)#6 (6) { ["level"]=> int(2) ["code"]=> int(1845) ["column"]=> int(0) ["message"]=> string(86) "Element 'litteral': No matching global declaration available for the validation root. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(1) } [1]=> object(LibXMLError)#10 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(157) "Element 'litteral': This element is not expected. Expected is one of ( custom, emphasize, embed, embed-inline, strong, link, table, anchor, line, literal ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(1) } } string(3832) "

NAME

AF_AX25 - AX.25 amateur packet radio protocol family

DESCRIPTION

AX.25 is a protocol used extensively by radio amateurs. The Linux AX.25 protocol family permits access to these protocols via the standard networking socket metaphor.

The AX.25 protocol layer supports both connected mode and datagram (UI) frame modes. IP traffic may be stacked on top of AX.25 frames for IP transmission over the AX.25 medium.

The primary mode of operation is connected mode which is the mode used for a socket of type SOCK_SEQPACKET (stream sockets are not available in AX.25). This requires that the user ensures output data is suitably packetised, and that input data is read a packet at a time into a buffer of suitable size. The Linux AX.25 protocol layer can operate in standard AX.25 mode with three bit sequence numbers or in PE1CHL extended AX.25 mode which uses seven bit sequence numbers. The protocol passed to the socket is used for all outgoing frames. Passing 0 causes the normal AX.25 Text PID to be used.

SOCK_DGRAM gives access to AX.25 UI frames. For access to special frames (of any form) SOCK_RAW can be used. There is no SOCK_PACKET support under AX.25. Instead an AF_INET socket of type SOCK_PACKET should be used.

AX.25 addresses consist of 6 ascii characters and a number called the SSID. These are encoded into a sockaddr_ax25 structure which is provided to the relevant system calls. When digipeaters are included a callsign path can be much more complex. When this is the case a struct full_sockaddr_ax25 should be passed to the system calls.

AX.25 has some unusual properties. Notably in a multi-user system an AX.25 address is often associated with a user, and some users may not have such an association. a set of ioctl calls are provided to manage an association table, and in addition the superuser may use an arbitary callsign by binding to the callsign desired and specifying the port to use as a first digipeated hop.

AX.25 supports the following socket options for SOL_AX25. AX25_T1 is the T1 timer in 1/10ths of a second, AX25_T2 is the T2 timer in 1/10ths of a second, AX25_T3 is the T3 timer. The window is settable with AX25_WINDOW. AX25_N2, the retry counter is also configurable. There is no 'infinite retry' option supported however. The method of backoff for retries is configurable via the socket option AX25_BACKOFF, a value of true indicates the use of exponential backoff and false simple linear backoff. The mode of a connection made be altered to be either standard AX.25 or extended AX.25 via AX25_EXTSEQ. It is possible to have the complete AX.25 header returned to the application by setting AX25_HDRINCL to true, programs must be aware of the internal structure of AX.25 frames to use this option. Note that if AX.25 fragmentation is encountered, only the control information of the first frame is returned along with the defragmented data.

SEE ALSO

call(1), socket(2), setsockopt(2), getsockopt(2), axctl(8), axparms(5), axassociate(8), axparms(8), kissattach(8).

BUGS

Too numerous to list in full currently.

•
Minor protocol violations exist.

AUTHOR

Alan Cox GW4PTS <alan@cymru.net>


Jonathan Naylor G4KLX <g4klx@g4klx.demon.co.uk>
" array(3) { [0]=> object(LibXMLError)#10 (6) { ["level"]=> int(2) ["code"]=> int(1845) ["column"]=> int(0) ["message"]=> string(86) "Element 'litteral': No matching global declaration available for the validation root. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(1) } [1]=> object(LibXMLError)#6 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(157) "Element 'litteral': This element is not expected. Expected is one of ( custom, emphasize, embed, embed-inline, strong, link, table, anchor, line, literal ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(1) } [2]=> object(LibXMLError)#14 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(101) "Element 'litteral': This element is not expected. Expected is one of ( paragraph, section, header ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(4) } } string(2071) "

NAME

AF_ROSE - Rose amateur packet radio protocol family

DESCRIPTION

Rose is a protocol used extensively by radio amateurs. The Linux Rose protocol family permits access to these protocols via the standard networking socket metaphor.

The Rose protocol layer only supports connected mode.

The only mode of operation is connected mode which is the mode used for a socket of type SOCK_SEQPACKET (stream sockets are not available in Rose). This requires that the user ensures output data is suitably packetised, and that input data is read a packet at a time into a buffer of suitable size.

Rose addresses consist of 10 digits. These are encoded into a sockaddr_rose structure which is provided to the relevant system calls.

Rose has some unusual properties. Notably in a multi-user system an AX.25 address is often associated with a user, and some users may not have such an association. a set of ioctl calls are provided to manage an association table.

Rose supports the following socket options for SOL_ROSE. ROSE_T1 is the T11/T21 timer in 1/10ths of a second, ROSE_T2 is the T12/T22 timer in 1/10ths of a second. ROSE_T3, is the T13/T23 timer in 1/10ths of a second. It is possible for an application to request that the Rose layer return the Rose header as well as the application data, this is done via the ROSE_HDRINCL socket option.

SEE ALSO

call(1), socket(2), setsockopt(2), getsockopt(2), rsports(5), rsctl(8), rsparms(8).

AUTHOR

Jonathan Naylor G4KLX <g4klx@g4klx.demon.co.uk>

" array(4) { [0]=> object(LibXMLError)#14 (6) { ["level"]=> int(2) ["code"]=> int(1845) ["column"]=> int(0) ["message"]=> string(86) "Element 'litteral': No matching global declaration available for the validation root. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(1) } [1]=> object(LibXMLError)#6 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(157) "Element 'litteral': This element is not expected. Expected is one of ( custom, emphasize, embed, embed-inline, strong, link, table, anchor, line, literal ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(1) } [2]=> object(LibXMLError)#10 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(101) "Element 'litteral': This element is not expected. Expected is one of ( paragraph, section, header ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(4) } [3]=> object(LibXMLError)#15 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(95) "Element 'h2': This element is not expected. Expected is one of ( paragraph, section, header ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(4) } } string(10806) "
Résumé des épisodes précédents :
  1. Le prompt bash et la manipulation des titres des fenêtres
  2. Navigation dans les répertoires en ligne de commande et les alias
  3. L'historique et le complètement avancé avec bash
Après ces trois billets plutôt sur la configuration de bash, passons aux choses sérieuses avec l'étude de trois concepts qui font du shell en général et de bash en particulier un outil extrêment puissant :
  1. Les gestion des entrées/sorties (ou flux ou Input/Output ou I/O pour les intimes :) avec les redirections et l'utilisation du pipe.
    1. Rediriger la sortie standard dans un fichier
    2. Rediriger la sortie d'erreur dans un fichier
    3. Rediriger la sortie standard et la sortie d'erreur sur la sortie standard
    4. Et l'entrée standard ?
    5. Pour aller plus loin
  2. Les motifs (ie le globbing)
Les entrées/sorties
L'article sur les flux standards sur Wikipedia est une très bonne et courte introduction au concept d'entrée/sorties standards. Pour faire simple, lorsqu'un shell est lancé en mode interactif (ie le shell attend qu'on lui tape des commandes typiquement dans un terminal), l'entrée standard est le clavier et la sortie standard et la sortie d'erreur sont reliées au terminal. Par défaut, lorsque le shell lance une commande, cette commande hérite (entre autre) des entrées/sorties standards du shell parent. Ces flux sont manipulables dans le shell, quelques exemples pratiques à l'aide de la commande find permettant de rechercher tous les répertoires dans le dossier de l'utilisateur root sur lequel mon utilisateur n'a évidemment pas tous les droits, cette commande renvoie donc des informations sur la sortie d'erreur et la sortie standard : > tigrou@Lorien[192.168.0.243]:/tmp$ find ~root -type d /root /root/.gnome2 find: /root/.gnome2: Permission non accordée /root/.gconf find: /root/.gconf: Permission non accordée
Rediriger la sortie standard dans un fichier
Cette opération se fait avec l'opérateur >, qui créa le fichier si il n'existe pas ou l'écrasera avec la sortie standard en l'utilisant de la manière suivante : > tigrou@Lorien[192.168.0.243]:/tmp$ find ~root -type d > sortie_standard find: /root/.gnome2: Permission non accordée find: /root/.gconf: Permission non accordée > tigrou@Lorien[192.168.0.243]:/tmp$ cat sortie_standard /root /root/.gnome2 /root/.gconf Plutôt que d'écraser le fichier, il est aussi possible d'ajouter la sortie au fichier si celui-ci existe déjà avec l 'opérateur >>.
Rediriger la sortie d'erreur dans un fichier
Cette opération se fait également avec > mais en spécifiant le descripteur de la sortie d'erreur (par défaut 2) : > tigrou@Lorien[192.168.0.243]:/tmp$ find ~root -type d 2> sortie_erreur /root /root/.gnome2 /root/.gconf > tigrou@Lorien[192.168.0.243]:/tmp$ cat sortie_erreur find: /root/.gnome2: Permission non accordée find: /root/.gconf: Permission non accordée Cette séquence est fréquemment utilisée pour n'afficher que la sortie standard en spécifiant comme fichier le fichier spécial /dev/null. De la même manière que précédemment, 2>> ajoutera la sortie d'erreur à la fin du fichier.
Rediriger la sortie d'erreur et la sortie standard sur la sortie standard
Ici, on souhaite tout avoir sur la même sortie pour un traitement ultérieur, pour cela il faut indiquer au shell de rediriger les données écrites sur le descripteur 2 sur le descripteur 1. > tigrou@Lorien[192.168.0.243]:/tmp$ find ~root -type d > sortie_1_et_2 2>&1 > tigrou@Lorien[192.168.0.243]:/tmp$ cat sortie_1_et_2 /root /root/.gnome2 find: /root/.gnome2: Permission non accordée /root/.gconf find: /root/.gconf: Permission non accordée
Et l'entrée standard ?
Il est possible d'enchâiner les commandes en redirigeant les sorties d'une commande sur l'entrée standard à l'aide du pipe (| ou tube), par exemple si je souhaite n'avoir que les messages concernant les dossier de GNOME à la suite de find, je peux utiliser l'utilitaire grep pour filtrer la sortie comme suit : > tigrou@Lorien[192.168.0.243]:/tmp$ find ~root -type d 2>&1 | grep gnome /root/.gnome2 find: /root/.gnome2: Permission non accordée Comme vue précédemment, les sorties standard et d'erreur de find sont redirigés sur la sortie standard qui est elle même redirigées sur l'entrée standard de grep. Cette ligne est équivalente aux deux lignes suivantes utilisant le symbole < permettant de rediriger le contenu d'un fichier sur l'entrée standard : > tigrou@Lorien[192.168.0.243]:/tmp$ find ~root -type d > sortie_1_et_2 2>&1 > tigrou@Lorien[192.168.0.243]:/tmp$ grep gnome < sortie_1_et_2 /root/.gnome2 find: /root/.gnome2: Permission non accordée elle même équivalente à > tigrou@Lorien[192.168.0.243]:/tmp$ find ~root -type d > sortie_1_et_2 2>&1 > tigrou@Lorien[192.168.0.243]:/tmp$ cat sortie_1_et_2 | grep gnome /root/.gnome2 find: /root/.gnome2: Permission non accordée Ce sont des exemples très simples, mais il est possible ainsi de faire des choses assez complexe en une ligne en enchaînant quelques commandes (qui feront l'objet d'un prochaine billet) : tigrou@Lorien[192.168.0.243]:/tmp$ cat access.log | egrep -v '(/var|/design|/share|/stats| 404 )' | cut -d ' ' -f 7 | sort | uniq | wc -l 2911 Cette ligne lit le fichier de log d'apache access.log et permet de compter le nombre de pages différentes vues au moment où j'écris ces lignes.
Pour aller plus loin
Pour en revenir aux entrée/sorties, ces opérations sont les plus courantes, mais il existe bien d'autres possibilités décrites dans la page du manuel de bash.
Les motifs
Les motifs sont des caractères spécifiques qui permettent, une fois développé par le shell, de remplacer plusieurs fichiers sans avoir à tous les écrire. Pour faire simple, ce sont des expressions rationnelles très limitées. Le plus connu de ces caractères est l'étoile * souvent utilisé dans les rm -rf * (ce qui est très dangereux !). Pour tester ces caractères, il vaut mieux utiliser echo. À la suite des commandes tapées ci-dessus, j'ai plusieurs fichiers dans le répertoire temporaire qui peuvent servir d'exemple : > tigrou@Lorien[192.168.0.243]:/tmp$ ls gconfd-tigrou mapping-tigrou sortie_1_et_2 sortie_standard listen orbit-tigrou sortie_erreur ssh-jDyKBu4304 # tout ce qui commençe par un s > tigrou@Lorien[192.168.0.243]:/tmp$ echo s* sortie_1_et_2 sortie_erreur sortie_standard ssh-jDyKBu4304 # tout ce qui termine par un u > tigrou@Lorien[192.168.0.243]:/tmp$ echo *u gconfd-tigrou mapping-tigrou orbit-tigrou # tout ce qui termine par un chiffre > tigrou@Lorien[192.168.0.243]:/tmp$ echo *[0-9] sortie_1_et_2 ssh-jDyKBu4304 # tout ce qui ne se termine PAS par un chiffre > tigrou@Lorien[192.168.0.243]:/tmp$ echo *[!0-9] gconfd-tigrou listen mapping-tigrou orbit-tigrou sortie_erreur sortie_standard # tout ce qui commence par sortie suivi d'un caractère suivi de standard > tigrou@Lorien[192.168.0.243]:/tmp$ echo sortie?standard sortie_standard Pour utiliser l'un de ces caractères sur la ligne de commande sans qu'il soit interprèté, il suffit de la préfixer d'un antislash (\).
" array(14) { [0]=> object(LibXMLError)#15 (6) { ["level"]=> int(2) ["code"]=> int(1845) ["column"]=> int(0) ["message"]=> string(86) "Element 'litteral': No matching global declaration available for the validation root. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(1) } [1]=> object(LibXMLError)#10 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(157) "Element 'litteral': This element is not expected. Expected is one of ( custom, emphasize, embed, embed-inline, strong, link, table, anchor, line, literal ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(1) } [2]=> object(LibXMLError)#6 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(101) "Element 'litteral': This element is not expected. Expected is one of ( paragraph, section, header ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(4) } [3]=> object(LibXMLError)#14 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(95) "Element 'h2': This element is not expected. Expected is one of ( paragraph, section, header ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(4) } [4]=> object(LibXMLError)#16 (6) { ["level"]=> int(3) ["code"]=> int(26) ["column"]=> int(64) ["message"]=> string(27) "Entity 'Acirc' not defined " ["file"]=> string(0) "" ["line"]=> int(13899) } [5]=> object(LibXMLError)#17 (6) { ["level"]=> int(3) ["code"]=> int(26) ["column"]=> int(69) ["message"]=> string(25) "Entity 'deg' not defined " ["file"]=> string(0) "" ["line"]=> int(13899) } [6]=> object(LibXMLError)#18 (6) { ["level"]=> int(3) ["code"]=> int(26) ["column"]=> int(113) ["message"]=> string(27) "Entity 'Acirc' not defined " ["file"]=> string(0) "" ["line"]=> int(294) } [7]=> object(LibXMLError)#19 (6) { ["level"]=> int(3) ["code"]=> int(26) ["column"]=> int(119) ["message"]=> string(26) "Entity 'copy' not defined " ["file"]=> string(0) "" ["line"]=> int(294) } [8]=> object(LibXMLError)#20 (6) { ["level"]=> int(2) ["code"]=> int(1866) ["column"]=> int(0) ["message"]=> string(87) "Element 'header', attribute 'anchor_name': The attribute 'anchor_name' is not allowed. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(59) } [9]=> object(LibXMLError)#21 (6) { ["level"]=> int(2) ["code"]=> int(1866) ["column"]=> int(0) ["message"]=> string(87) "Element 'header', attribute 'anchor_name': The attribute 'anchor_name' is not allowed. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(70) } [10]=> object(LibXMLError)#22 (6) { ["level"]=> int(2) ["code"]=> int(1866) ["column"]=> int(0) ["message"]=> string(87) "Element 'header', attribute 'anchor_name': The attribute 'anchor_name' is not allowed. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(84) } [11]=> object(LibXMLError)#23 (6) { ["level"]=> int(2) ["code"]=> int(1866) ["column"]=> int(0) ["message"]=> string(87) "Element 'header', attribute 'anchor_name': The attribute 'anchor_name' is not allowed. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(98) } [12]=> object(LibXMLError)#24 (6) { ["level"]=> int(2) ["code"]=> int(1866) ["column"]=> int(0) ["message"]=> string(87) "Element 'header', attribute 'anchor_name': The attribute 'anchor_name' is not allowed. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(111) } [13]=> object(LibXMLError)#25 (6) { ["level"]=> int(2) ["code"]=> int(1866) ["column"]=> int(0) ["message"]=> string(87) "Element 'header', attribute 'anchor_name': The attribute 'anchor_name' is not allowed. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(141) } } string(3456) "
Voila presque une semaine que je me bats avec PDO_MySQL pour arriver à enfin tester le composant PersistentObject d'eZ components... Après pas mal de recherches, beaucoup de prises de tête, je voyais la défenestration arrivée à grand pas ;-) en m'apercevant que finalement le problème venait du module PDO_MySQL fraîchement compilé sur ma Dapper Drake grâce au tuto trouvé sur BlogNote. Je pensais alors à un problème dû au hack pobomékimarche du tuto, mais le problème était identique sur ma Dedibox et sa Edgy Eft toute propre... J'ai aussi posté un message sur le forum Ubuntu-fr avec un succès comment dire... relatif, 17 affichages et aucune réponse au moment où j'écris ces lignes... Les symptômes étaient simples, les deux bouts code suivants devraient affichés la même chose, mais celui avec le bindValue() échoue et ne renvoie rien : <?php $db = new PDO('mysql:host=localhost;dbname=sew', 'sew', 'sew'); // Code simple de référence $stmt = $db->prepare('select * from `sew_sites` where `id`=1'); $stmt->execute(); $row = $stmt->fetchAll( PDO::FETCH_ASSOC ); var_dump($row); $stmt->closeCursor(); // Ne renvoie rien si compilé avec libmysqlclient14 ou 15 $stmt = $db->prepare('select * from `sew_sites` where `id`=:id'); $stmt->bindValue(':id', 1); $stmt->execute(); $row = $stmt->fetchAll( PDO::FETCH_ASSOC ); var_dump($row); $stmt->closeCursor(); ?> En fait, visiblement, la compilation de ce module avec libmysqlclient14 ou libmysqlclient15 correspondant respectivement à MySQL 4.1 et MySQL 5.0 d'après apt-cache, pose problème. Pour que ça fonctionne chez moi, il a fallu que j'installe libmysqlclient12 et libmysqlclient12-dev pour compiler PDO_MySQL... Ce qui est d'autant plus surprenant que libmysqlclient12 correspond à MySQL 4.0 et que la deuxième ligne de la documentation sur PDO_MySQL indique : PDO_MYSQL prendra avantage des requêtes natives préparées présentes dans MySQL 4.1 et supérieur. Et là, je me dis, mais bon sang, pourquoi n'y a t il pas de paquet officiels php5-pdo-mysql surtout que la documentation PHP indique que PDO est livré en standard avec PHP depuis la version 5.1 et qu'il s'agit d'une fonctionnalité majeure de cette version de PHP.
" array(15) { [0]=> object(LibXMLError)#25 (6) { ["level"]=> int(2) ["code"]=> int(1845) ["column"]=> int(0) ["message"]=> string(86) "Element 'litteral': No matching global declaration available for the validation root. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(1) } [1]=> object(LibXMLError)#24 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(157) "Element 'litteral': This element is not expected. Expected is one of ( custom, emphasize, embed, embed-inline, strong, link, table, anchor, line, literal ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(1) } [2]=> object(LibXMLError)#23 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(101) "Element 'litteral': This element is not expected. Expected is one of ( paragraph, section, header ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(4) } [3]=> object(LibXMLError)#22 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(95) "Element 'h2': This element is not expected. Expected is one of ( paragraph, section, header ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(4) } [4]=> object(LibXMLError)#21 (6) { ["level"]=> int(3) ["code"]=> int(26) ["column"]=> int(64) ["message"]=> string(27) "Entity 'Acirc' not defined " ["file"]=> string(0) "" ["line"]=> int(13899) } [5]=> object(LibXMLError)#20 (6) { ["level"]=> int(3) ["code"]=> int(26) ["column"]=> int(69) ["message"]=> string(25) "Entity 'deg' not defined " ["file"]=> string(0) "" ["line"]=> int(13899) } [6]=> object(LibXMLError)#19 (6) { ["level"]=> int(3) ["code"]=> int(26) ["column"]=> int(113) ["message"]=> string(27) "Entity 'Acirc' not defined " ["file"]=> string(0) "" ["line"]=> int(294) } [7]=> object(LibXMLError)#18 (6) { ["level"]=> int(3) ["code"]=> int(26) ["column"]=> int(119) ["message"]=> string(26) "Entity 'copy' not defined " ["file"]=> string(0) "" ["line"]=> int(294) } [8]=> object(LibXMLError)#17 (6) { ["level"]=> int(2) ["code"]=> int(1866) ["column"]=> int(0) ["message"]=> string(87) "Element 'header', attribute 'anchor_name': The attribute 'anchor_name' is not allowed. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(59) } [9]=> object(LibXMLError)#16 (6) { ["level"]=> int(2) ["code"]=> int(1866) ["column"]=> int(0) ["message"]=> string(87) "Element 'header', attribute 'anchor_name': The attribute 'anchor_name' is not allowed. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(70) } [10]=> object(LibXMLError)#14 (6) { ["level"]=> int(2) ["code"]=> int(1866) ["column"]=> int(0) ["message"]=> string(87) "Element 'header', attribute 'anchor_name': The attribute 'anchor_name' is not allowed. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(84) } [11]=> object(LibXMLError)#6 (6) { ["level"]=> int(2) ["code"]=> int(1866) ["column"]=> int(0) ["message"]=> string(87) "Element 'header', attribute 'anchor_name': The attribute 'anchor_name' is not allowed. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(98) } [12]=> object(LibXMLError)#10 (6) { ["level"]=> int(2) ["code"]=> int(1866) ["column"]=> int(0) ["message"]=> string(87) "Element 'header', attribute 'anchor_name': The attribute 'anchor_name' is not allowed. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(111) } [13]=> object(LibXMLError)#15 (6) { ["level"]=> int(2) ["code"]=> int(1866) ["column"]=> int(0) ["message"]=> string(87) "Element 'header', attribute 'anchor_name': The attribute 'anchor_name' is not allowed. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(141) } [14]=> object(LibXMLError)#26 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(126) "Element 'literal': This element is not expected. Expected is one of ( custom, emphasize, link, strong, embed, embed-inline ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(18) } } string(3456) "
Voila presque une semaine que je me bats avec PDO_MySQL pour arriver à enfin tester le composant PersistentObject d'eZ components... Après pas mal de recherches, beaucoup de prises de tête, je voyais la défenestration arrivée à grand pas ;-) en m'apercevant que finalement le problème venait du module PDO_MySQL fraîchement compilé sur ma Dapper Drake grâce au tuto trouvé sur BlogNote. Je pensais alors à un problème dû au hack pobomékimarche du tuto, mais le problème était identique sur ma Dedibox et sa Edgy Eft toute propre... J'ai aussi posté un message sur le forum Ubuntu-fr avec un succès comment dire... relatif, 17 affichages et aucune réponse au moment où j'écris ces lignes... Les symptômes étaient simples, les deux bouts code suivants devraient affichés la même chose, mais celui avec le bindValue() échoue et ne renvoie rien : <?php $db = new PDO('mysql:host=localhost;dbname=sew', 'sew', 'sew'); // Code simple de référence $stmt = $db->prepare('select * from `sew_sites` where `id`=1'); $stmt->execute(); $row = $stmt->fetchAll( PDO::FETCH_ASSOC ); var_dump($row); $stmt->closeCursor(); // Ne renvoie rien si compilé avec libmysqlclient14 ou 15 $stmt = $db->prepare('select * from `sew_sites` where `id`=:id'); $stmt->bindValue(':id', 1); $stmt->execute(); $row = $stmt->fetchAll( PDO::FETCH_ASSOC ); var_dump($row); $stmt->closeCursor(); ?> En fait, visiblement, la compilation de ce module avec libmysqlclient14 ou libmysqlclient15 correspondant respectivement à MySQL 4.1 et MySQL 5.0 d'après apt-cache, pose problème. Pour que ça fonctionne chez moi, il a fallu que j'installe libmysqlclient12 et libmysqlclient12-dev pour compiler PDO_MySQL... Ce qui est d'autant plus surprenant que libmysqlclient12 correspond à MySQL 4.0 et que la deuxième ligne de la documentation sur PDO_MySQL indique : PDO_MYSQL prendra avantage des requêtes natives préparées présentes dans MySQL 4.1 et supérieur. Et là, je me dis, mais bon sang, pourquoi n'y a t il pas de paquet officiels php5-pdo-mysql surtout que la documentation PHP indique que PDO est livré en standard avec PHP depuis la version 5.1 et qu'il s'agit d'une fonctionnalité majeure de cette version de PHP.
" array(16) { [0]=> object(LibXMLError)#26 (6) { ["level"]=> int(2) ["code"]=> int(1845) ["column"]=> int(0) ["message"]=> string(86) "Element 'litteral': No matching global declaration available for the validation root. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(1) } [1]=> object(LibXMLError)#15 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(157) "Element 'litteral': This element is not expected. Expected is one of ( custom, emphasize, embed, embed-inline, strong, link, table, anchor, line, literal ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(1) } [2]=> object(LibXMLError)#10 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(101) "Element 'litteral': This element is not expected. Expected is one of ( paragraph, section, header ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(4) } [3]=> object(LibXMLError)#6 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(95) "Element 'h2': This element is not expected. Expected is one of ( paragraph, section, header ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(4) } [4]=> object(LibXMLError)#14 (6) { ["level"]=> int(3) ["code"]=> int(26) ["column"]=> int(64) ["message"]=> string(27) "Entity 'Acirc' not defined " ["file"]=> string(0) "" ["line"]=> int(13899) } [5]=> object(LibXMLError)#16 (6) { ["level"]=> int(3) ["code"]=> int(26) ["column"]=> int(69) ["message"]=> string(25) "Entity 'deg' not defined " ["file"]=> string(0) "" ["line"]=> int(13899) } [6]=> object(LibXMLError)#17 (6) { ["level"]=> int(3) ["code"]=> int(26) ["column"]=> int(113) ["message"]=> string(27) "Entity 'Acirc' not defined " ["file"]=> string(0) "" ["line"]=> int(294) } [7]=> object(LibXMLError)#18 (6) { ["level"]=> int(3) ["code"]=> int(26) ["column"]=> int(119) ["message"]=> string(26) "Entity 'copy' not defined " ["file"]=> string(0) "" ["line"]=> int(294) } [8]=> object(LibXMLError)#19 (6) { ["level"]=> int(2) ["code"]=> int(1866) ["column"]=> int(0) ["message"]=> string(87) "Element 'header', attribute 'anchor_name': The attribute 'anchor_name' is not allowed. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(59) } [9]=> object(LibXMLError)#20 (6) { ["level"]=> int(2) ["code"]=> int(1866) ["column"]=> int(0) ["message"]=> string(87) "Element 'header', attribute 'anchor_name': The attribute 'anchor_name' is not allowed. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(70) } [10]=> object(LibXMLError)#21 (6) { ["level"]=> int(2) ["code"]=> int(1866) ["column"]=> int(0) ["message"]=> string(87) "Element 'header', attribute 'anchor_name': The attribute 'anchor_name' is not allowed. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(84) } [11]=> object(LibXMLError)#22 (6) { ["level"]=> int(2) ["code"]=> int(1866) ["column"]=> int(0) ["message"]=> string(87) "Element 'header', attribute 'anchor_name': The attribute 'anchor_name' is not allowed. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(98) } [12]=> object(LibXMLError)#23 (6) { ["level"]=> int(2) ["code"]=> int(1866) ["column"]=> int(0) ["message"]=> string(87) "Element 'header', attribute 'anchor_name': The attribute 'anchor_name' is not allowed. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(111) } [13]=> object(LibXMLError)#24 (6) { ["level"]=> int(2) ["code"]=> int(1866) ["column"]=> int(0) ["message"]=> string(87) "Element 'header', attribute 'anchor_name': The attribute 'anchor_name' is not allowed. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(141) } [14]=> object(LibXMLError)#25 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(126) "Element 'literal': This element is not expected. Expected is one of ( custom, emphasize, link, strong, embed, embed-inline ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(18) } [15]=> object(LibXMLError)#27 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(126) "Element 'literal': This element is not expected. Expected is one of ( custom, emphasize, link, strong, embed, embed-inline ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(18) } } string(5918) "
Je continue tranquillement l'installation / la configuration de ma Dedibox sous Ubuntu hébergeant ce site. Après avoir fait cohabiter PHP4 et PHP5, migrer son site utilisant eZ publish, configurer mes statistiques web avec AWStats et m'être battu avec PDO_MySQL (rien que ça :)), j'en viens aux backups. On ne le répètera jamais assez, il est important de faire des backups réguliers et systèmatiques comme il est important de savoir restaurer ses sauvegardes... En plus, le service Dedibox propose un accès FTP avec un quota de 5Go inclu dans l'offre, il serait dommage de ne pas en profiter. Il est également possible d'augmenter ce quota, moyennant finances. Pour mon serveur, j'ai choisi d'utiliser cet espace pour sauvegarder les bases de données. C'est la partie la plus volumineuse et dans beaucoup de cas, c'est le seul élément à récupèrer. De toute manière, l'ensemble des données est aussi sauvegardé à intervalle régulier sur mon PC de bureau. Bien sûr les informations indiquées dans ce billet fonctionnent également avec n'importe quel autre accès FTP.
Configuration de MySQL
Il faut tout d'abord créer un utilisateur dans MySQL qui aura le droit en lecture sur toutes les bases pour faire un dump. Cela peut se faire via un assistant comme PHPMyAdmin ou bien avec 2 requêtes SQL exécutées en tant que root (de MySQL évidemment) : GRANT SELECT, LOCK TABLES, SHOW DATABASES ON * TO 'backup'@'localhost' IDENTIFIED BY 'pass_backup'; FLUSH PRIVILEGES; L'utilisateur backup de MySQL a maintenant les droits en lecture sur toutes bases (il est conseillé de mettre un mot de passe fort...). Pour qu'un script puisse se connecter sans avoir à taper le mot de passe, il faut créer un fichier nommé .my.cnf dans le répertoire personnel de l'utilisateur qui exécutera le script. Ce fichier doit ressembler à : [client] port = 3306 user = backup password = pass_backup Attention à bien restreindre les permission sur ce fichier pour que personne ne puisse le lire, sauf l'utilisateur en question avec la commande suivante : > tigrou@dedipwet[88.191.30.29]:~$ chmod 600 .my.cnf
Configuration de l'accès FTP
Une fois l'option FTP activée dans la rubrique Sauvegarde de la console Dedibox, comme pour MySQL il faut faire en sorte que l'accès FTP se fasse sans demander de mot de passe. Il faut créer un fichier .netrc toujours à la racine du dossier personnel de l'utilisateur qui fera tourner le script : machine dedibackup.dedibox.fr login login_ftp_sauvegarde password mot_de_passe_ftp_sauvegarde Avec ce fichier, les connections FTP sur dedibackup.dedibox.fr se feront avec le login et le mot de passe indiqués avec les clients FTP suivant ce fichier (ftp, lftp, ncftp, ...) sans rien demander. De la même manière que le fichier .my.cnf, il faut faire attention aux permissions sur ce fichier.
Le script
#! /bin/bash # Script de sauvegarde de toutes les bases sur FTP FTP='dedibackup.dedibox.fr' MYSQL_DIR='/var/lib/mysql' TMP="/tmp/backup_site" # fenêtre de backup en semaine ROTATION_WEEK=3 PREFIX_DATE=`date '+%U'` PREFIX_DATE_DELETE=`date '+%U' -d "-${ROTATION_WEEK}weeks"` [ ! -d "$MYSQL_DIR" ] && exit 2 [ ! -d "$TMP" ] && mkdir -p "$TMP" cd "$MYSQL_DIR" for base in `find . -maxdepth 1 -name [a-zA-Z]\* -type d` ; do base=`echo $base | sed 's#\./##g'` mysqldump --single-transaction "$base" | bzip2 -9 - > "$TMP/$PREFIX_DATE.$base.sql.bz2" done cd - lftp -e "mrm $PREFIX_DATE_DELETE* ; mput $TMP/* ; exit" "$FTP" rm -rf "$TMP" Ce script est prévu pour être lancé une fois par semaine avec crontab. Il va faire un dump de toutes les bases, effacer les dumps de plus $ROTATION_WEEK semaines sur le serveur distant et uploader les nouveaux ensuite. Le nombre de semaines sur lequel se fait la rotation peut être modifié via la variable ROTATION_WEEK.
" array(17) { [0]=> object(LibXMLError)#27 (6) { ["level"]=> int(2) ["code"]=> int(1845) ["column"]=> int(0) ["message"]=> string(86) "Element 'litteral': No matching global declaration available for the validation root. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(1) } [1]=> object(LibXMLError)#25 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(157) "Element 'litteral': This element is not expected. Expected is one of ( custom, emphasize, embed, embed-inline, strong, link, table, anchor, line, literal ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(1) } [2]=> object(LibXMLError)#24 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(101) "Element 'litteral': This element is not expected. Expected is one of ( paragraph, section, header ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(4) } [3]=> object(LibXMLError)#23 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(95) "Element 'h2': This element is not expected. Expected is one of ( paragraph, section, header ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(4) } [4]=> object(LibXMLError)#22 (6) { ["level"]=> int(3) ["code"]=> int(26) ["column"]=> int(64) ["message"]=> string(27) "Entity 'Acirc' not defined " ["file"]=> string(0) "" ["line"]=> int(13899) } [5]=> object(LibXMLError)#21 (6) { ["level"]=> int(3) ["code"]=> int(26) ["column"]=> int(69) ["message"]=> string(25) "Entity 'deg' not defined " ["file"]=> string(0) "" ["line"]=> int(13899) } [6]=> object(LibXMLError)#20 (6) { ["level"]=> int(3) ["code"]=> int(26) ["column"]=> int(113) ["message"]=> string(27) "Entity 'Acirc' not defined " ["file"]=> string(0) "" ["line"]=> int(294) } [7]=> object(LibXMLError)#19 (6) { ["level"]=> int(3) ["code"]=> int(26) ["column"]=> int(119) ["message"]=> string(26) "Entity 'copy' not defined " ["file"]=> string(0) "" ["line"]=> int(294) } [8]=> object(LibXMLError)#18 (6) { ["level"]=> int(2) ["code"]=> int(1866) ["column"]=> int(0) ["message"]=> string(87) "Element 'header', attribute 'anchor_name': The attribute 'anchor_name' is not allowed. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(59) } [9]=> object(LibXMLError)#17 (6) { ["level"]=> int(2) ["code"]=> int(1866) ["column"]=> int(0) ["message"]=> string(87) "Element 'header', attribute 'anchor_name': The attribute 'anchor_name' is not allowed. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(70) } [10]=> object(LibXMLError)#16 (6) { ["level"]=> int(2) ["code"]=> int(1866) ["column"]=> int(0) ["message"]=> string(87) "Element 'header', attribute 'anchor_name': The attribute 'anchor_name' is not allowed. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(84) } [11]=> object(LibXMLError)#14 (6) { ["level"]=> int(2) ["code"]=> int(1866) ["column"]=> int(0) ["message"]=> string(87) "Element 'header', attribute 'anchor_name': The attribute 'anchor_name' is not allowed. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(98) } [12]=> object(LibXMLError)#6 (6) { ["level"]=> int(2) ["code"]=> int(1866) ["column"]=> int(0) ["message"]=> string(87) "Element 'header', attribute 'anchor_name': The attribute 'anchor_name' is not allowed. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(111) } [13]=> object(LibXMLError)#10 (6) { ["level"]=> int(2) ["code"]=> int(1866) ["column"]=> int(0) ["message"]=> string(87) "Element 'header', attribute 'anchor_name': The attribute 'anchor_name' is not allowed. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(141) } [14]=> object(LibXMLError)#15 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(126) "Element 'literal': This element is not expected. Expected is one of ( custom, emphasize, link, strong, embed, embed-inline ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(18) } [15]=> object(LibXMLError)#26 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(126) "Element 'literal': This element is not expected. Expected is one of ( custom, emphasize, link, strong, embed, embed-inline ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(18) } [16]=> object(LibXMLError)#28 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(126) "Element 'literal': This element is not expected. Expected is one of ( custom, emphasize, link, strong, embed, embed-inline ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(28) } } string(5917) "
Je continue tranquillement l'installation / la configuration de ma Dedibox sous Ubuntu hébergeant ce site. Après avoir fait cohabiter PHP4 et PHP5, migrer son site utilisant eZ publish, configurer mes statistiques web avec AWStats et m'être battu avec PDO_MySQL (rien que ça :)), j'en viens aux backups. On ne le répètera jamais assez, il est important de faire des backups réguliers et systèmatiques comme il est important de savoir restaurer ses sauvegardes... En plus, le service Dedibox propose un accès FTP avec un quota de 5Go inclu dans l'offre, il serait dommage de ne pas en profiter. Il est également possible d'augmenter ce quota, moyennant finances. Pour mon serveur, j'ai choisi d'utiliser cet espace pour sauvegarder les bases de données. C'est la partie la plus volumineuse et dans beaucoup de cas, c'est le seul élément à récupèrer. De toute manière, l'ensemble des données est aussi sauvegardé à intervalle régulier sur mon PC de bureau. Bien sûr les informations indiquées dans ce billet fonctionnent également avec n'importe quel autre accès FTP.
Configuration de MySQL
Il faut tout d'abord créer un utilisateur dans MySQL qui aura le droit en lecture sur toutes les bases pour faire un dump. Cela peut se faire via un assistant comme PHPMyAdmin ou bien avec 2 requêtes SQL exécutées en tant que root (de MySQL évidemment) : GRANT SELECT, LOCK TABLES, SHOW DATABASES ON * TO 'backup'@'localhost' IDENTIFIED BY 'pass_backup'; FLUSH PRIVILEGES; L'utilisateur backup de MySQL a maintenant les droits en lecture sur toutes bases (il est conseillé de mettre un mot de passe fort...). Pour qu'un script puisse se connecter sans avoir à taper le mot de passe, il faut créer un fichier nommé .my.cnf dans le répertoire personnel de l'utilisateur qui exécutera le script. Ce fichier doit ressembler à : [client] port = 3306 user = backup password = pass_backup Attention à bien restreindre les permission sur ce fichier pour que personne ne puisse le lire, sauf l'utilisateur en question avec la commande suivante : > tigrou@dedipwet[88.191.30.29]:~$ chmod 600 .my.cnf
Configuration de l'accès FTP
Une fois l'option FTP activée dans la rubrique Sauvegarde de la console Dedibox, comme pour MySQL il faut faire en sorte que l'accès FTP se fasse sans demander de mot de passe. Il faut créer un fichier .netrc toujours à la racine du dossier personnel de l'utilisateur qui fera tourner le script : machine dedibackup.dedibox.fr login login_ftp_sauvegarde password mot_de_passe_ftp_sauvegarde Avec ce fichier, les connections FTP sur dedibackup.dedibox.fr se feront avec le login et le mot de passe indiqués avec les clients FTP suivant ce fichier (ftp, lftp, ncftp, ...) sans rien demander. De la même manière que le fichier .my.cnf, il faut faire attention aux permissions sur ce fichier.
Le script
#! /bin/bash # Script de sauvegarde de toutes les bases sur FTP FTP='dedibackup.dedibox.fr' MYSQL_DIR='/var/lib/mysql' TMP="/tmp/backup_site" # fenêtre de backup en semaine ROTATION_WEEK=3 PREFIX_DATE=`date '+%U'` PREFIX_DATE_DELETE=`date '+%U' -d "-${ROTATION_WEEK}weeks"` [ ! -d "$MYSQL_DIR" ] && exit 2 [ ! -d "$TMP" ] && mkdir -p "$TMP" cd "$MYSQL_DIR" for base in `find . -maxdepth 1 -name [a-zA-Z]\* -type d` ; do base=`echo $base | sed 's#\./##g'` mysqldump --single-transaction "$base" | bzip2 -9 - > "$TMP/$PREFIX_DATE.$base.sql.bz2" done cd - lftp -e "mrm $PREFIX_DATE_DELETE* ; mput $TMP/* ; exit" "$FTP" rm -rf "$TMP" Ce script est prévu pour être lancé une fois par semaine avec crontab. Il va faire un dump de toutes les bases, effacer les dumps de plus $ROTATION_WEEK semaines sur le serveur distant et uploader les nouveaux ensuite. Le nombre de semaines sur lequel se fait la rotation peut être modifié via la variable ROTATION_WEEK.
" array(18) { [0]=> object(LibXMLError)#28 (6) { ["level"]=> int(2) ["code"]=> int(1845) ["column"]=> int(0) ["message"]=> string(86) "Element 'litteral': No matching global declaration available for the validation root. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(1) } [1]=> object(LibXMLError)#26 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(157) "Element 'litteral': This element is not expected. Expected is one of ( custom, emphasize, embed, embed-inline, strong, link, table, anchor, line, literal ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(1) } [2]=> object(LibXMLError)#15 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(101) "Element 'litteral': This element is not expected. Expected is one of ( paragraph, section, header ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(4) } [3]=> object(LibXMLError)#10 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(95) "Element 'h2': This element is not expected. Expected is one of ( paragraph, section, header ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(4) } [4]=> object(LibXMLError)#6 (6) { ["level"]=> int(3) ["code"]=> int(26) ["column"]=> int(64) ["message"]=> string(27) "Entity 'Acirc' not defined " ["file"]=> string(0) "" ["line"]=> int(13899) } [5]=> object(LibXMLError)#14 (6) { ["level"]=> int(3) ["code"]=> int(26) ["column"]=> int(69) ["message"]=> string(25) "Entity 'deg' not defined " ["file"]=> string(0) "" ["line"]=> int(13899) } [6]=> object(LibXMLError)#16 (6) { ["level"]=> int(3) ["code"]=> int(26) ["column"]=> int(113) ["message"]=> string(27) "Entity 'Acirc' not defined " ["file"]=> string(0) "" ["line"]=> int(294) } [7]=> object(LibXMLError)#17 (6) { ["level"]=> int(3) ["code"]=> int(26) ["column"]=> int(119) ["message"]=> string(26) "Entity 'copy' not defined " ["file"]=> string(0) "" ["line"]=> int(294) } [8]=> object(LibXMLError)#18 (6) { ["level"]=> int(2) ["code"]=> int(1866) ["column"]=> int(0) ["message"]=> string(87) "Element 'header', attribute 'anchor_name': The attribute 'anchor_name' is not allowed. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(59) } [9]=> object(LibXMLError)#19 (6) { ["level"]=> int(2) ["code"]=> int(1866) ["column"]=> int(0) ["message"]=> string(87) "Element 'header', attribute 'anchor_name': The attribute 'anchor_name' is not allowed. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(70) } [10]=> object(LibXMLError)#20 (6) { ["level"]=> int(2) ["code"]=> int(1866) ["column"]=> int(0) ["message"]=> string(87) "Element 'header', attribute 'anchor_name': The attribute 'anchor_name' is not allowed. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(84) } [11]=> object(LibXMLError)#21 (6) { ["level"]=> int(2) ["code"]=> int(1866) ["column"]=> int(0) ["message"]=> string(87) "Element 'header', attribute 'anchor_name': The attribute 'anchor_name' is not allowed. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(98) } [12]=> object(LibXMLError)#22 (6) { ["level"]=> int(2) ["code"]=> int(1866) ["column"]=> int(0) ["message"]=> string(87) "Element 'header', attribute 'anchor_name': The attribute 'anchor_name' is not allowed. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(111) } [13]=> object(LibXMLError)#23 (6) { ["level"]=> int(2) ["code"]=> int(1866) ["column"]=> int(0) ["message"]=> string(87) "Element 'header', attribute 'anchor_name': The attribute 'anchor_name' is not allowed. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(141) } [14]=> object(LibXMLError)#24 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(126) "Element 'literal': This element is not expected. Expected is one of ( custom, emphasize, link, strong, embed, embed-inline ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(18) } [15]=> object(LibXMLError)#25 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(126) "Element 'literal': This element is not expected. Expected is one of ( custom, emphasize, link, strong, embed, embed-inline ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(18) } [16]=> object(LibXMLError)#27 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(126) "Element 'literal': This element is not expected. Expected is one of ( custom, emphasize, link, strong, embed, embed-inline ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(28) } [17]=> object(LibXMLError)#29 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(126) "Element 'literal': This element is not expected. Expected is one of ( custom, emphasize, link, strong, embed, embed-inline ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(28) } } string(5469) "
Je continue tranquillement l'installation / la configuration de ma Dedibox sous Ubuntu hébergeant ce site. Après avoir fait cohabiter PHP4 et PHP5, migrer son site utilisant eZ publish, configurer mes statistiques web avec AWStats et m'être battu avec PDO_MySQL (rien que ça :)), j'en viens aux backups. On ne le répètera jamais assez, il est important de faire des backups réguliers et systèmatiques comme il est important de savoir restaurer ses sauvegardes... En plus, le service Dedibox propose un accès FTP avec un quota de 5Go inclu dans l'offre, il serait dommage de ne pas en profiter. Il est également possible d'augmenter ce quota, moyennant finances. Pour mon serveur, j'ai choisi d'utiliser cet espace pour sauvegarder les bases de données. C'est la partie la plus volumineuse et dans beaucoup de cas, c'est le seul élément à récupèrer. De toute manière, l'ensemble des données est aussi sauvegardé à intervalle régulier sur mon PC de bureau. Bien sûr les informations indiquées dans ce billet fonctionnent également avec n'importe quel autre accès FTP.
Configuration de MySQL
Il faut tout d'abord créer un utilisateur dans MySQL qui aura le droit en lecture sur toutes les bases pour faire un dump. Cela peut se faire via un assistant comme PHPMyAdmin ou bien avec 2 requêtes SQL exécutées en tant que root (de MySQL évidemment) : GRANT SELECT, LOCK TABLES, SHOW DATABASES ON * TO 'backup'@'localhost' IDENTIFIED BY 'pass_backup'; FLUSH PRIVILEGES; L'utilisateur backup de MySQL a maintenant les droits en lecture sur toutes bases (il est conseillé de mettre un mot de passe fort...). Pour qu'un script puisse se connecter sans avoir à taper le mot de passe, il faut créer un fichier nommé .my.cnf dans le répertoire personnel de l'utilisateur qui exécutera le script. Ce fichier doit ressembler à : [client] port = 3306 user = backup password = pass_backup Attention à bien restreindre les permission sur ce fichier pour que personne ne puisse le lire, sauf l'utilisateur en question avec la commande suivante : > tigrou@dedipwet[88.191.30.29]:~$ chmod 600 .my.cnf
Configuration de l'accès FTP
Une fois l'option FTP activée dans la rubrique Sauvegarde de la console Dedibox, comme pour MySQL il faut faire en sorte que l'accès FTP se fasse sans demander de mot de passe. Il faut créer un fichier .netrc toujours à la racine du dossier personnel de l'utilisateur qui fera tourner le script : machine dedibackup.dedibox.fr login login_ftp_sauvegarde password mot_de_passe_ftp_sauvegarde Avec ce fichier, les connections FTP sur dedibackup.dedibox.fr se feront avec le login et le mot de passe indiqués avec les clients FTP suivant ce fichier (ftp, lftp, ncftp, ...) sans rien demander. De la même manière que le fichier .my.cnf, il faut faire attention aux permissions sur ce fichier.
Le script
#! /bin/bash # Script de sauvegarde de toutes les bases sur FTP FTP='dedibackup.dedibox.fr' MYSQL_DIR='/var/lib/mysql' TMP="/tmp/backup_site" # fenêtre de backup en semaine ROTATION_WEEK=3 PREFIX_DATE=`date '+%U'` PREFIX_DATE_DELETE=`date '+%U' -d "-${ROTATION_WEEK}weeks"` [ ! -d "$MYSQL_DIR" ] && exit 2 [ ! -d "$TMP" ] && mkdir -p "$TMP" cd "$MYSQL_DIR" for base in `find . -maxdepth 1 -name [a-zA-Z]\* -type d` ; do base=`echo $base | sed 's#\./##g'` mysqldump --single-transaction "$base" | bzip2 -9 - > "$TMP/$PREFIX_DATE.$base.sql.bz2" done cd - lftp -e "mrm $PREFIX_DATE_DELETE* ; mput $TMP/* ; exit" "$FTP" rm -rf "$TMP" Ce script est prévu pour être lancé une fois par semaine avec crontab. Il va faire un dump de toutes les bases, effacer les dumps de plus $ROTATION_WEEK semaines sur le serveur distant et uploader les nouveaux ensuite. Le nombre de semaines sur lequel se fait la rotation peut être modifié via la variable ROTATION_WEEK.
" array(19) { [0]=> object(LibXMLError)#29 (6) { ["level"]=> int(2) ["code"]=> int(1845) ["column"]=> int(0) ["message"]=> string(86) "Element 'litteral': No matching global declaration available for the validation root. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(1) } [1]=> object(LibXMLError)#27 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(157) "Element 'litteral': This element is not expected. Expected is one of ( custom, emphasize, embed, embed-inline, strong, link, table, anchor, line, literal ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(1) } [2]=> object(LibXMLError)#25 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(101) "Element 'litteral': This element is not expected. Expected is one of ( paragraph, section, header ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(4) } [3]=> object(LibXMLError)#24 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(95) "Element 'h2': This element is not expected. Expected is one of ( paragraph, section, header ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(4) } [4]=> object(LibXMLError)#23 (6) { ["level"]=> int(3) ["code"]=> int(26) ["column"]=> int(64) ["message"]=> string(27) "Entity 'Acirc' not defined " ["file"]=> string(0) "" ["line"]=> int(13899) } [5]=> object(LibXMLError)#22 (6) { ["level"]=> int(3) ["code"]=> int(26) ["column"]=> int(69) ["message"]=> string(25) "Entity 'deg' not defined " ["file"]=> string(0) "" ["line"]=> int(13899) } [6]=> object(LibXMLError)#21 (6) { ["level"]=> int(3) ["code"]=> int(26) ["column"]=> int(113) ["message"]=> string(27) "Entity 'Acirc' not defined " ["file"]=> string(0) "" ["line"]=> int(294) } [7]=> object(LibXMLError)#20 (6) { ["level"]=> int(3) ["code"]=> int(26) ["column"]=> int(119) ["message"]=> string(26) "Entity 'copy' not defined " ["file"]=> string(0) "" ["line"]=> int(294) } [8]=> object(LibXMLError)#19 (6) { ["level"]=> int(2) ["code"]=> int(1866) ["column"]=> int(0) ["message"]=> string(87) "Element 'header', attribute 'anchor_name': The attribute 'anchor_name' is not allowed. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(59) } [9]=> object(LibXMLError)#18 (6) { ["level"]=> int(2) ["code"]=> int(1866) ["column"]=> int(0) ["message"]=> string(87) "Element 'header', attribute 'anchor_name': The attribute 'anchor_name' is not allowed. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(70) } [10]=> object(LibXMLError)#17 (6) { ["level"]=> int(2) ["code"]=> int(1866) ["column"]=> int(0) ["message"]=> string(87) "Element 'header', attribute 'anchor_name': The attribute 'anchor_name' is not allowed. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(84) } [11]=> object(LibXMLError)#16 (6) { ["level"]=> int(2) ["code"]=> int(1866) ["column"]=> int(0) ["message"]=> string(87) "Element 'header', attribute 'anchor_name': The attribute 'anchor_name' is not allowed. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(98) } [12]=> object(LibXMLError)#14 (6) { ["level"]=> int(2) ["code"]=> int(1866) ["column"]=> int(0) ["message"]=> string(87) "Element 'header', attribute 'anchor_name': The attribute 'anchor_name' is not allowed. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(111) } [13]=> object(LibXMLError)#6 (6) { ["level"]=> int(2) ["code"]=> int(1866) ["column"]=> int(0) ["message"]=> string(87) "Element 'header', attribute 'anchor_name': The attribute 'anchor_name' is not allowed. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(141) } [14]=> object(LibXMLError)#10 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(126) "Element 'literal': This element is not expected. Expected is one of ( custom, emphasize, link, strong, embed, embed-inline ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(18) } [15]=> object(LibXMLError)#15 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(126) "Element 'literal': This element is not expected. Expected is one of ( custom, emphasize, link, strong, embed, embed-inline ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(18) } [16]=> object(LibXMLError)#26 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(126) "Element 'literal': This element is not expected. Expected is one of ( custom, emphasize, link, strong, embed, embed-inline ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(28) } [17]=> object(LibXMLError)#28 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(126) "Element 'literal': This element is not expected. Expected is one of ( custom, emphasize, link, strong, embed, embed-inline ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(28) } [18]=> object(LibXMLError)#30 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(126) "Element 'literal': This element is not expected. Expected is one of ( custom, emphasize, link, strong, embed, embed-inline ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(17) } } string(3577) "
Comme je l'indiquais dernièrement, j'ai décidé de placer mes photos et mes billets sous Licence Creative Commons CC-By-Sa ce qui implique de citer mon nom (ou je me contente de l'adresse d'origine du site) lors de l'utilisation de ces contenus. Mais je me rend compte en regardant mes statistiques générées avec AWStats que beaucoup de gens hotlink mes photos sur divers blogs, page myspace ou divers forums sans rien mentionner de leur provenance et ça m'énerve un peu... Alors bien sûr, je peux m'inscrire et rajouter les mentions nécessaires dans le topic du forum en question mais :
  1. c'est long et fastidieux ;
  2. parfois impossible ;
  3. bien souvent les administrateurs prennent peur et retirent purement et simplement l'image alors que je demande juste une simple et courte mention.
J'ai donc décider d'automatiser un peu le processus en utilisant quelques règles de Rewriting Apache et un simple script PHP qui ajoute un texte à la volée et met en cache les images hébergées sur ma Dedibox mais utilisées hors de pwet.fr. Je n'aime pas trop le procédé, mais je n'en vois pas d'autre... Techniquement parlant, j'ai mis la configuration suivante dans mon fichier de configuration d'Apache : RewriteCond %{HTTP_REFERER} !^$ [NC] RewriteCond %{HTTP_REFERER} !^http://.*pwet\.fr.*$ [NC] RewriteCond %{HTTP_REFERER} !^http://images\.google\..*$ [NC] RewriteRule .*\.jpg$ /hotlink.php?img=%{SCRIPT_FILENAME}&ref=%{HTTP_REFERER} Ce qui signifie que lors de l'appel à une image si une URL référente est définie et n'est ni pwet.fr, ni Google Images alors l'image renvoyée est en fait traitée par un script. Le script hotlink.php est un traitement qui ajoute un texte blanc en bas de l'image en fonction de la taille de l'image en utilisant les fonctions de traitements d'image de la bibliothèque GD.
" array(20) { [0]=> object(LibXMLError)#30 (6) { ["level"]=> int(2) ["code"]=> int(1845) ["column"]=> int(0) ["message"]=> string(86) "Element 'litteral': No matching global declaration available for the validation root. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(1) } [1]=> object(LibXMLError)#28 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(157) "Element 'litteral': This element is not expected. Expected is one of ( custom, emphasize, embed, embed-inline, strong, link, table, anchor, line, literal ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(1) } [2]=> object(LibXMLError)#26 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(101) "Element 'litteral': This element is not expected. Expected is one of ( paragraph, section, header ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(4) } [3]=> object(LibXMLError)#15 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(95) "Element 'h2': This element is not expected. Expected is one of ( paragraph, section, header ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(4) } [4]=> object(LibXMLError)#10 (6) { ["level"]=> int(3) ["code"]=> int(26) ["column"]=> int(64) ["message"]=> string(27) "Entity 'Acirc' not defined " ["file"]=> string(0) "" ["line"]=> int(13899) } [5]=> object(LibXMLError)#6 (6) { ["level"]=> int(3) ["code"]=> int(26) ["column"]=> int(69) ["message"]=> string(25) "Entity 'deg' not defined " ["file"]=> string(0) "" ["line"]=> int(13899) } [6]=> object(LibXMLError)#14 (6) { ["level"]=> int(3) ["code"]=> int(26) ["column"]=> int(113) ["message"]=> string(27) "Entity 'Acirc' not defined " ["file"]=> string(0) "" ["line"]=> int(294) } [7]=> object(LibXMLError)#16 (6) { ["level"]=> int(3) ["code"]=> int(26) ["column"]=> int(119) ["message"]=> string(26) "Entity 'copy' not defined " ["file"]=> string(0) "" ["line"]=> int(294) } [8]=> object(LibXMLError)#17 (6) { ["level"]=> int(2) ["code"]=> int(1866) ["column"]=> int(0) ["message"]=> string(87) "Element 'header', attribute 'anchor_name': The attribute 'anchor_name' is not allowed. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(59) } [9]=> object(LibXMLError)#18 (6) { ["level"]=> int(2) ["code"]=> int(1866) ["column"]=> int(0) ["message"]=> string(87) "Element 'header', attribute 'anchor_name': The attribute 'anchor_name' is not allowed. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(70) } [10]=> object(LibXMLError)#19 (6) { ["level"]=> int(2) ["code"]=> int(1866) ["column"]=> int(0) ["message"]=> string(87) "Element 'header', attribute 'anchor_name': The attribute 'anchor_name' is not allowed. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(84) } [11]=> object(LibXMLError)#20 (6) { ["level"]=> int(2) ["code"]=> int(1866) ["column"]=> int(0) ["message"]=> string(87) "Element 'header', attribute 'anchor_name': The attribute 'anchor_name' is not allowed. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(98) } [12]=> object(LibXMLError)#21 (6) { ["level"]=> int(2) ["code"]=> int(1866) ["column"]=> int(0) ["message"]=> string(87) "Element 'header', attribute 'anchor_name': The attribute 'anchor_name' is not allowed. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(111) } [13]=> object(LibXMLError)#22 (6) { ["level"]=> int(2) ["code"]=> int(1866) ["column"]=> int(0) ["message"]=> string(87) "Element 'header', attribute 'anchor_name': The attribute 'anchor_name' is not allowed. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(141) } [14]=> object(LibXMLError)#23 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(126) "Element 'literal': This element is not expected. Expected is one of ( custom, emphasize, link, strong, embed, embed-inline ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(18) } [15]=> object(LibXMLError)#24 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(126) "Element 'literal': This element is not expected. Expected is one of ( custom, emphasize, link, strong, embed, embed-inline ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(18) } [16]=> object(LibXMLError)#25 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(126) "Element 'literal': This element is not expected. Expected is one of ( custom, emphasize, link, strong, embed, embed-inline ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(28) } [17]=> object(LibXMLError)#27 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(126) "Element 'literal': This element is not expected. Expected is one of ( custom, emphasize, link, strong, embed, embed-inline ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(28) } [18]=> object(LibXMLError)#29 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(126) "Element 'literal': This element is not expected. Expected is one of ( custom, emphasize, link, strong, embed, embed-inline ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(17) } [19]=> object(LibXMLError)#31 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(126) "Element 'literal': This element is not expected. Expected is one of ( custom, emphasize, link, strong, embed, embed-inline ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(42) } } string(3577) "
Comme je l'indiquais dernièrement, j'ai décidé de placer mes photos et mes billets sous Licence Creative Commons CC-By-Sa ce qui implique de citer mon nom (ou je me contente de l'adresse d'origine du site) lors de l'utilisation de ces contenus. Mais je me rend compte en regardant mes statistiques générées avec AWStats que beaucoup de gens hotlink mes photos sur divers blogs, page myspace ou divers forums sans rien mentionner de leur provenance et ça m'énerve un peu... Alors bien sûr, je peux m'inscrire et rajouter les mentions nécessaires dans le topic du forum en question mais :
  1. c'est long et fastidieux ;
  2. parfois impossible ;
  3. bien souvent les administrateurs prennent peur et retirent purement et simplement l'image alors que je demande juste une simple et courte mention.
J'ai donc décider d'automatiser un peu le processus en utilisant quelques règles de Rewriting Apache et un simple script PHP qui ajoute un texte à la volée et met en cache les images hébergées sur ma Dedibox mais utilisées hors de pwet.fr. Je n'aime pas trop le procédé, mais je n'en vois pas d'autre... Techniquement parlant, j'ai mis la configuration suivante dans mon fichier de configuration d'Apache : RewriteCond %{HTTP_REFERER} !^$ [NC] RewriteCond %{HTTP_REFERER} !^http://.*pwet\.fr.*$ [NC] RewriteCond %{HTTP_REFERER} !^http://images\.google\..*$ [NC] RewriteRule .*\.jpg$ /hotlink.php?img=%{SCRIPT_FILENAME}&ref=%{HTTP_REFERER} Ce qui signifie que lors de l'appel à une image si une URL référente est définie et n'est ni pwet.fr, ni Google Images alors l'image renvoyée est en fait traitée par un script. Le script hotlink.php est un traitement qui ajoute un texte blanc en bas de l'image en fonction de la taille de l'image en utilisant les fonctions de traitements d'image de la bibliothèque GD.
" array(21) { [0]=> object(LibXMLError)#31 (6) { ["level"]=> int(2) ["code"]=> int(1845) ["column"]=> int(0) ["message"]=> string(86) "Element 'litteral': No matching global declaration available for the validation root. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(1) } [1]=> object(LibXMLError)#29 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(157) "Element 'litteral': This element is not expected. Expected is one of ( custom, emphasize, embed, embed-inline, strong, link, table, anchor, line, literal ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(1) } [2]=> object(LibXMLError)#27 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(101) "Element 'litteral': This element is not expected. Expected is one of ( paragraph, section, header ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(4) } [3]=> object(LibXMLError)#25 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(95) "Element 'h2': This element is not expected. Expected is one of ( paragraph, section, header ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(4) } [4]=> object(LibXMLError)#24 (6) { ["level"]=> int(3) ["code"]=> int(26) ["column"]=> int(64) ["message"]=> string(27) "Entity 'Acirc' not defined " ["file"]=> string(0) "" ["line"]=> int(13899) } [5]=> object(LibXMLError)#23 (6) { ["level"]=> int(3) ["code"]=> int(26) ["column"]=> int(69) ["message"]=> string(25) "Entity 'deg' not defined " ["file"]=> string(0) "" ["line"]=> int(13899) } [6]=> object(LibXMLError)#22 (6) { ["level"]=> int(3) ["code"]=> int(26) ["column"]=> int(113) ["message"]=> string(27) "Entity 'Acirc' not defined " ["file"]=> string(0) "" ["line"]=> int(294) } [7]=> object(LibXMLError)#21 (6) { ["level"]=> int(3) ["code"]=> int(26) ["column"]=> int(119) ["message"]=> string(26) "Entity 'copy' not defined " ["file"]=> string(0) "" ["line"]=> int(294) } [8]=> object(LibXMLError)#20 (6) { ["level"]=> int(2) ["code"]=> int(1866) ["column"]=> int(0) ["message"]=> string(87) "Element 'header', attribute 'anchor_name': The attribute 'anchor_name' is not allowed. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(59) } [9]=> object(LibXMLError)#19 (6) { ["level"]=> int(2) ["code"]=> int(1866) ["column"]=> int(0) ["message"]=> string(87) "Element 'header', attribute 'anchor_name': The attribute 'anchor_name' is not allowed. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(70) } [10]=> object(LibXMLError)#18 (6) { ["level"]=> int(2) ["code"]=> int(1866) ["column"]=> int(0) ["message"]=> string(87) "Element 'header', attribute 'anchor_name': The attribute 'anchor_name' is not allowed. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(84) } [11]=> object(LibXMLError)#17 (6) { ["level"]=> int(2) ["code"]=> int(1866) ["column"]=> int(0) ["message"]=> string(87) "Element 'header', attribute 'anchor_name': The attribute 'anchor_name' is not allowed. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(98) } [12]=> object(LibXMLError)#16 (6) { ["level"]=> int(2) ["code"]=> int(1866) ["column"]=> int(0) ["message"]=> string(87) "Element 'header', attribute 'anchor_name': The attribute 'anchor_name' is not allowed. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(111) } [13]=> object(LibXMLError)#14 (6) { ["level"]=> int(2) ["code"]=> int(1866) ["column"]=> int(0) ["message"]=> string(87) "Element 'header', attribute 'anchor_name': The attribute 'anchor_name' is not allowed. " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(141) } [14]=> object(LibXMLError)#6 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(126) "Element 'literal': This element is not expected. Expected is one of ( custom, emphasize, link, strong, embed, embed-inline ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(18) } [15]=> object(LibXMLError)#10 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(126) "Element 'literal': This element is not expected. Expected is one of ( custom, emphasize, link, strong, embed, embed-inline ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(18) } [16]=> object(LibXMLError)#15 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(126) "Element 'literal': This element is not expected. Expected is one of ( custom, emphasize, link, strong, embed, embed-inline ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(28) } [17]=> object(LibXMLError)#26 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(126) "Element 'literal': This element is not expected. Expected is one of ( custom, emphasize, link, strong, embed, embed-inline ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(28) } [18]=> object(LibXMLError)#28 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(126) "Element 'literal': This element is not expected. Expected is one of ( custom, emphasize, link, strong, embed, embed-inline ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(17) } [19]=> object(LibXMLError)#30 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(126) "Element 'literal': This element is not expected. Expected is one of ( custom, emphasize, link, strong, embed, embed-inline ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(42) } [20]=> object(LibXMLError)#32 (6) { ["level"]=> int(2) ["code"]=> int(1871) ["column"]=> int(0) ["message"]=> string(126) "Element 'literal': This element is not expected. Expected is one of ( custom, emphasize, link, strong, embed, embed-inline ). " ["file"]=> string(29) "/web/sites/pwet.fr/www2011.7/" ["line"]=> int(42) } }