Sélectionner une page
Raspberry Pi : envoyer en ftp un fichier à un serveur, par Cron Job

Raspberry Pi : envoyer en ftp un fichier à un serveur, par Cron Job

Comment envoyer, à partir d’un Rasberry Pi, un fichier txt toutes les 20 minutes à un serveur distant ? La réponse passe par une connexion FTP et un cronjob, ou tâche planifiée.

Mes objectifs

Sur un Raspberry Pi, j’ai créé un script Shell qui relève la température, la date et l’heure, le nom du Pi et les écrit dans un fichier txt avec la chaîne de caractère définie dans la commande. Ce script, est décrit dans l’article « Raspberry Pi : Mesurer la température avec un capteur DS18B20. Le fichier texte créé s’appelle [hostname]-status.txt.

Maintenant je veux envoyer ce fichier texte à un serveur distant, en FTP.

Et je veux que cet envoi soit réalisé automatiquement toutes les 20 minutes.

Envoyer un fichier à un serveur distant en FTP

Pour connecter un Pi comme client à un serveur, il faut lui installer une application.

Pour installer le package FTP (j’ai choisi celui qui paraissait le plus léger) :

apt-get install ftp

Maintenant, je peux me connecter à un serveur distant.

Je crée le script send-status.sh, avec droits 744 (exécutable) :

#!/bin/bash

printenv

# check my Hostname variable 
ThisHost=$(hostname) 
date=$(date) 

# There should be no ECHO in a CRON job
echo $ThisHost

# $1 is the variable appended to the file when executed
# example : ./send-status.sh essai would put "essai" in $1

# local file to send
FILE=$ThisHost"-status.txt"   
# local directory to pick the file for upload
REPERTOIRE="/home/jf/temp/"
echo $REPERTOIRE$FILE

# https://www.raspberrypi.org/forums/viewtopic.php?t=68541&p=500070
# https://www.raspberrypi.org/forums/viewtopic.php?f=91&t=51222

#credentials to access the remote directory
USERNAME="USERNAME"
PASSWORD="PWORD"
SERVER="URL-DU-SERVEUR"
 
# remote server directory to upload backup
BACKUPDIR="/My-pi/"

echo "Attempting ftp upload~, ..."

cd $REPERTOIRE
ftp -in $SERVER <<EOMYF
user $USERNAME $PASSWORD
pwd
cd $BACKUPDIR
put $FILE
bye
EOMYF

Lorsque je l’éxécute en ligne de commande (), le serveur reçoit bien le fichier texte.

Le Pi affiche un message de succès (mais si) :

Attempting ftp upload~, ...
257 "/" is the current directory

Donc cette opération est correctement réalisée par la ligne de commande.

Réaliser cette action automatiquement (tâche planifiée)

Nous avons déjà essayé le script à la main avec

cd /home/jf/exec
./send-status.sh OK

Et ça fonctionnait. Maintenant, il faut définir l’environnement d’abord, puis indiquer la commande à exécuter et sa fréquence.

Planifier l’exécution du script

Sur le pi, éditer /etc/crontab avec crontab –e :

Y ajouter à la fin (utiliser SHIFT INS pour coller) :

#env
SHELL=/bin/bash
HOME=/home/jf
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
 
*/20 * * * * bash /home/jf/exec/send-status.sh OK > /dev/null 2>&1
@reboot  bash /home/jf/exec/send-status.sh REBOOT

Attention : il doit obligatoirement y avoir une ligne vide à la fin de crontab….

Il faut créer une première fois /home/jf/snd/cron.log et lui donner des droits d’accès en écriture (664).

Le crontab ne démarrera pas tant qu’on aura pas fait un reboot, donc

reboot

Remarques sur les cron jobs et leur debogage, sur Pi

Cron Job

Un cron job se déclenche dans un environnement différent de celui d’un lancement manuel !

Dans le script j’ai ajouté printenv, qui affiche toutes les variables d’environnement.

Et en principe on peut envoyer le cron vers un fichier log mais sur le Pi en cours, je n’y arrive pas.

Comme le cronjob fonctionne, ça n’est pas grave.

Le fichier /var/log/syslog contient également beaucoup d’informations sur ce qui se passe dans le pi.

le cron job @reboot

la ligne @reboot bash /home/jf/exec/send-status.sh REBOOT  exécute la tâche lors du reboot du Pi.

Si je reboot le pi ‘pi-name’, le serveur distant reçoit un fichier pi-name-status.txt contenant

pi hostname, time, statut, temperature
pi-name, Sun 2 Apr 17:13:35 CEST 2017, REBOOT, 21.875

Et maintenant

J’ai terminé cette opération. A vous maintenant !

Raspberry Pi : Mesurer la température avec un capteur DS18B20

Raspberry Pi : Mesurer la température avec un capteur DS18B20

Le capteur DS18B20 est un capteur à coût réduit (10 € les 5 capteurs étanches avec câble de 1 mètre ou 8 € les 10 capteurs de base), qui utilise le protocole 1-wire. On peut connecter plusieurs capteurs DS18B20 en série sur un même port du Raspberry Pi. Nous allons voir ici comment connecter un seul thermomètre et en écrire la valeur dans un fichier txt par un script Shell ou PHP.

Connecter le capteur DS18B20

Câblage d'un capteur de température DS18B20 à un Raspberry PiUne description détaillée du capteur DS18B20 est disponible en anglais ici. Le capteur peut mesurer des températures entre -55°C et +125°C et reste précis à 0.5°C sur l’intervalle -10°C à +85°C. Chaque capteur a un numéro de série unique (64 bits) et peut donc être identifié précisément.

Pour une seule sonde, on câble comme dans le schéma de droite (note du 29/12/2019 : ATTENTION, le schéma de droite est faux, le connecteur 1 est raccordé à GND, le connecteur 3 à VCC 3.3V !).

On peut mettre plusieurs capteurs en série (en théorie autant qu’on veut, en pratique il semble qu’il vaille mieux se limiter à 10 capteurs). Dans ce cas, on connecte une seule résistance 4.7 K et plusieurs sondes selon le schéma ci-dessous (note du 29/12/2019 : qui est juste, connecteur 1 raccordé à GND, 3 à VDD 3.3 V).

Câblage de plusieurs DS18B20 en série

Paramétrer le Pi pour lire la / les températures

Editer /boot/config.txt pour qu’il contienne la ligne suivante puis redémarrer le Pi :

dtoverlay=w1-gpio

Tester le/les capteurs

En ligne de commande, taper les lignes suivantes

sudo modprobe w1-gpio
sudo modprobe w1-therm
cd /sys/bus/w1/devices
ls
cd 28-xxxx (changer pour correspondre aux numéros de série qui s'affichent)
cat w1_slave 

Si le capteur est correctement câblé, on voit apparaître quelque chose qui ressemble à ce qui suit, où t=20187 signifie que la température est 20.187°C :

43 01 4b 46 7f ff 0d 10 bd : crc=bd YES
43 01 4b 46 7f ff 0d 10 bd t=20187

S’il y a plus d’un capteur de température,  ls dans /sys/bus/w1/devices affichera plusieurs répertoires.

Installer les drivers sur le Pi

modprobe w1-gpio et modprobe w1-therm sont les drivers pour les capteurs de température. Ils doivent démarrer lorsque le Pi démarre. Pour celà, ajouter les lignes suivantes à /etc/modules  :

w1‐gpio
w1‐therm

On redémarre le Pi et les drivers sont maintenant chargés.

Un script PHP pour lire les différentes températures

Noter que pour exécuter un script PHP en ligne de commande, il faut avoir préalablement installé PHP-CLI, avec la commande apt-get install php5-cli .

Le script read-temperature.php (exécutable) contient :

#!/usr/bin/env php
<?php

if (!defined("THERMOMETER_SENSOR_PATH")) {
	define("THERMOMETER_SENSOR_PATH", "/sys/devices/w1_bus_master1/28-0000046766b0/w1_slave"); 	
}


// Open resource file for thermometer
$thermometer = fopen(THERMOMETER_SENSOR_PATH, "r"); 

// Get the contents of the resource
$thermometerReadings = fread($thermometer, filesize(THERMOMETER_SENSOR_PATH)); 

// Close resource file for thermometer
fclose($thermometer); 

// We're only interested in the 2nd line, and the value after the t= on the 2nd line
preg_match("/t=(.+)/", preg_split("/\n/", $thermometerReadings)[1], $matches);
$temperature = $matches[1] / 1000; 


// Output the temperature
print $temperature . " °C. \n\r"; 
?>

On l’exécute avec la commande en ligne php read-temperature.php .

Dans mon cas, il affiche 20.875 ▒C.

Un script Shell pour lire la température

Voir ce projet, en anglais. Il lit plusieurs températures à la fois et les affiche à l’écran du Pi sous la forme 28-0000046766b0=20.937 .

Pour ma part, je n’ai qu’une seule température à lire et je veux l’écrire dans un fichier texte que j’enverrai ultérieurement à un serveur distant.

Je crée le script read-status.sh, (avec encodage UTF8 sans BOM, retours chariot UNIX et droits d’accès 744) qui contient :

#!/bin/bash

# afficher les variables d'environnement (utile pour un cron job)
printenv

# check my Hostname variable 
ThisHost=$(hostname) 

# Get UTC time
UtcNow= date -u 

# There should be no ECHO in a CRON job, so comment this !
echo $ThisHost

# $1 is the variable appended to the file when executed
# example : ./send-status.sh essai would put "essai" in $1

# local file to write into
FILE=$ThisHost"-status.txt" 
# local directory to write to file and pick it for upload
REPERTOIRE="/home/jf/temp/"
echo $REPERTOIRE$FILE

#Read last temperature 
temperature=$(find /sys/bus/w1/devices/ -name "28-*" -exec cat {}/w1_slave \; | grep "t=" | awk -F "t=" '{print $2/1000}')

# create file and add content to it
cd $REPERTOIRE
cat > $FILE <<EOF # single > will empty and overwrite the file
pi hostname, time, statut, temperature
$ThisHost, $UtcNow, $1, $temperature 
EOF

Attention, ce script ne lit que le dernier des capteurs de température.

On l’exécute avec la commande en ligne ./read-status.sh OK  .

Dans le répertoire temp, j’ai maintenant un fichier piname-status.txt, qui contient :

pi hostname, time, statut, temperature
piname, Sun 2 Apr 15:01:44 CEST 2017, OK, 21.312

Et maintenant ?

Je peux lire la température mesurée par le Pi et la noter dans un fichier texte à chaque fois que j’exécute ./read-status.sh OK  en commande en ligne.

La prochaine étape sera d’envoyer les informations du fichier texte à un serveur externe de manière automatique. J’ai déjà décrit l’utilisation d’un cron job dans l’article « Cron Job sur un hébergement mutualisé OVH » mais je vais le réaliser sur un Raspberry Pi. Cest l’objet de l’article « Raspberry Pi : envoyer en ftp un fichier à un serveur, par Cron Job ».

Transfert d’un site vers un hébergement Infomaniak

Transfert d’un site vers un hébergement Infomaniak

Excédée par le mauvais fonctionnement du serveur cloud managé de mon ancien fournisseur, je me suis tournée vers l’offre d’Infomaniak. Je suis stupéfaite par la clarté et la simplicité d’accès. Les prix sont plus élevés mais comme je dispose d’une solution satisfaisante de sauvegardes, je n’ai plus besoin d’acheter une solution complémentaire. Je m’y retrouve donc.

J’explique ici comment transférer un site existant vers son nouvel hébergement. Cet article est rédigé comme aide-mémoire pour moi mais il pourra également être utile à d’autres.

Situation initiale

Domaine testal.com géré par OVH, avec un hébergement sur un serveur cloud OVH. Le site est sous WordPress, avec un certificat SSL.

Je laisse les domaines sur OVH mais je transfère les sites sur des hébergements d’un serveur cloud managé d’Infomaniak.

Les grandes lignes du transfert

On procède en grandes étapes :

  1. sauvegarde des fichiers spécifiques et de la base de données du site initial ;
  2. création d’un site WordPress « blanc » sur l’hébergement Infomaniak ;
  3. Réglages du site WordPress Infomaniak ;
  4. Pointage des DNS vers le nouvel hébergement ;
  5. Activation d’un certificat SSL Let’s Encrypt.

C’est seulement durant la quatrième étape que les internautes sont dirigés vers la nouvelle version du site. Pendant la phase de réglages du site, on peut y accéder (visualisation et tableau de bord WordPress) grâce à un lien de prévisualisation très efficace.

Au fur et à mesure du processus, on note les informations importantes dans un fichier, par exemple la check-list de transfert que j’ai créée en divers formats :

Etape 1 sauvegarde du site initial ;

MAJ du 30/07/2018 : on peut aussi utiliser l’excellente extension gratuite Updraft Plus pour gérer les sauvegardes et transferts.

Voir l’article Sauvegarde d&rsquo;un site WordPress avec Updraft Plus, gratuit et très bien pour savoir comment sauvegarder sur un autre hébergement en FTP.

On veut conserver des fichiers spécifiques et la base de données.

Dans l’ancien hébergement, sauvegarder le contenu de wp-content (hors sauvegardes, on peut zapper les répertoires « langages », « cache » et « upgrade » ) et la base de données (avec un dump, ou directement via phpMyAdmin de l’hébergeur).

On a donc deux fichiers :

  • Le contenu de la base de données, au nom du type exemple_2017-03-30_11-41-38.sql.zip
  • Les fichiers spécifiques, au nom du type exemple_file_2017_03_30.zip

Etape 2 création d’un site WordPress « blanc » sur l’hébergement Infomaniak ;

2.1 Console d’administration

Accès à la console d’administration Infomaniak avec l’adresse mail et l’identifiant noté sur la check-list (dans les informations à conserver).

2.2 Créer un compte FTP dans l’hébergement infomaniak correspondant

Aller dans l’hébergement défini pour le site à transférer (Anne-Laure pour moi). Créer un utilisateur (accès à l’ensemble du répertoire ou un répertoire spécifique), dans l’onglet FTP/SSH, bouton « AJOUTER ».

Noter les informations suivantes dans la check- list (dans les informations à conserver, partie A) :

Serveur hôte abcd.vps.infomaniak.com
Nom compte abcd_exemple
Mot de passe mot-de-passe2

2.3 Avec filezilla, transférer les fichiers dans le nouvel hébergement

Les fichiers zip de plus de 40 Mo doivent être uploadés avec filezilla et pas le gestionnaire de fichier en ligne d’infomaniak.

MAJ du 30/07/2018 : on peut aussi utiliser l’excellente extension gratuite Updraft Plus pour gérer les sauvegardes et transferts.

Voir l’article Sauvegarde d&rsquo;un site WordPress avec Updraft Plus, gratuit et très bien pour savoir comment sauvegarder sur un autre hébergement en FTP.

Dans Filezilla, on paramètre le compte comme dans cette copie d’écran, avec les informations notées lorsqu’on a créé le compte FTP de l’hébergement Infomaniak :

Réglage de Filezilla pour un accès FTP à un hébergement Infomaniak

dans le compte FTP infomaniak, créer un répertoire ald-utils et y placer le fichier zippé des fichiers de l’ancien site (le répertoire wp-content, exemple_file_2017_03_30.zip). Ca prend du temps. En attendant, on peut créer le site wordpress.

2.4 Création du site WordPress Infomaniak ;

Dans le tableau de bord Infomaniak, cliquer sur le bouton « ajouter un site »

Infomaniak Créer un nouveau domaine

(en fait j’ai créé testal.com et pas test.com) Puis « enregistrer »

On arrive alors à une page « assistant de démarrage ». Cliquer sur « installer mon site wordPress » puis « installation avancée »

Infomaniak : installer un site WordPress

Puis installer

Noter l’identifiant WordPress et son mot de passe dans la check-list (partie B).

Nota si on avait déjà créé le site, mais pas installé WordPress, il suffit de cliquer sur le bouton « OFF » de la colonne WordPress pour le site concerné, directement dans l’écran Tableau de bord Infomaniak.

Infomaniak : installer un site WordPress (alternative)

2.5 Créer une base de données à partir du tableau de bord Infomaniak

La base de données créées automatiquement par Infomaniak est malheureusement affublée d’un nom illisible, de type abcd_WP124026, et il n’est pas possible de modifier les informations textuelle pour spécifier à quel site se rapporte la base.

Je préfère donc créer une nouvelle base de données, avec un nom clair du type ‘abcd_testal’ que j’associe ensuite au site WordPress testal.com.

Pour cela, c’est l’onglet « bases de données » puis le bouton « ajouter une base de données ».

lui donner un nom intelligible, ici abcd_testal et activer « créer un nouvel utilisateur ».

Noter qu’on peut créer un mot de passe de bonne qualité simplement en cliquant sur le cadenas ouvert à droite de « mot de passe ». Le cadenas devient alors fermé et vert.

On note soigneusement les informations :

serveur hôte abcd.myd.infomaniak.com
Nom de la base abcd_testal
Nom compte abcd_testal
Mot de passe mot-de-passe3

Puis cliquer sur Enregistrer

2.6 paramétrage du site WordPress Infomaniak

Pour prévisualiser le site avant de faire le transfert de DNS, Infomaniak a une url de prévisualisation très bien faite.

Pour pouvoir voir et modifier ce site qui n’existe pas pour les internautes, il faut signifier au serveur Infomaniak d’utiliser le lien preview plutôt que l’url habituelle du site.

Aller dans Site Web / Mon Site WordPress. La liste des sites de l’hébergement s’affiche. Cliquer sur le bouton « Configurer » du site en cours de transfert.

Infomaniak : Configurer le site WordPress

On voit que l’adresse du site est http://testal.com, (et aussi que la base de données est celle créée par Infomaniak).

Infomaniak : Configurer le site WordPress - lien de "prévisualisation"

Cliquer sur le bouton « paramètres ».

Dans « site internet à utiliser », choisir l’adresse preview, de type ‘’ http://abcdgalg.preview.infomaniak.website puis « valider ».

Dans paramètres du site, sélectionner le site internet à utiliser en mode preview, et pas l’adresse normale du site.

Copier-coller l’adresse dans la check-list. On peut par exemple cliquer sur le nom de la base de données et copier le nom du site dans la table  prefix_options, champ siteurl

2.7 Modifier la base de données nouvellement créée

https://h2-phpmyadmin.infomaniak.ch/MySQLAdmin/

ouvrir la base de données créée manuellement (pas celle créée par infomaniak)

Y importer la bdd du site d’origine (exemple_2017-03-30_11-41-38.sql.zip)

dans la table  prefix_options, modifier :

  • siteurl  site de prévisualisation http://abcdgalg.preview.infomaniak.website
  • home  site de prévisualisation http://abcdgalg.preview.infomaniak.website

Copier le prefixe utilisé, par exemple Zzr4ez_, pour les tables et le coller dans la checklist (zone D).

2.8 Décompresser et déplacer les fichiers zippés avec le ftp infomaniak

MAJ du 30/07/2018 : on peut aussi utiliser l’excellente extension gratuite Updraft Plus pour gérer les sauvegardes et transferts.

Voir l’article Sauvegarde d&rsquo;un site WordPress avec Updraft Plus, gratuit et très bien pour savoir comment sauvegarder sur un autre hébergement en FTP.

ftp en ligne https://admin2.infomaniak.com/ftp/index.php?sServer=abcd.vps.infomaniak.com

Dans ald-utils, décompresser exemple_file_2017_03_30.zip.

Ensuite, déplacer les fichiers au bon endroit dans le répertoire wp-content du site en cours de transfert. Je laisse les extensions et thèmes installés automatiquement par infomaniak. Je supprime le sous-répertoire  2017 créé par infomaniak  dans le répertoire uploads.

2.9 modifier wp-config

Avec le FTP en ligne Infomaniak éditer wp-config.php

Il contient

define('DB_NAME', DB_NAME');

/** MySQL database username */

define('DB_USER', 'DB_USER');

/** MySQL database password */

define('DB_PASSWORD', 'DB_PASSWORD');

/** MySQL hostname */

define('DB_HOST', 'DB_HOST');

et plus loin

$table_prefix  = 'table_prefix';

Remplacer les contenus par les informations suivantes, notées dans la checklist (parties C et D) :

  • DB_NAME par le Nom de la base – abcd_testal
  • DB_USER par le Nom compte – abcd_testal
  • DB_PASSWORD par le Mot de passe – mot-de-passe3
  • DB_HOST par le serveur hôte – abcd.myd.infomaniak.com
  • et $table_prefix par le Préfixe de base de données – Zzr4ez_

Puis Enregistrer.

Maintenant, lorsqu’on visualise le site, on a le site initial.

2.10 Tester la vitesse du site avant transfert (optionnel)

On peut tester la vitesse des sites dans l’hébergement initial avant de le quitter. On peut utiliser les sites suivants et faire une copie d’écran pour conserver l’information.

Etape 3 Réglage du site (peut être fait après aussi)

Infomaniak installe automatiquement deux extensions intéressantes (les autres ne me semblent pas intéressantes) :

  • Count Per Day, qui permet de suivre le nombre de visiteur et le nombre de fois où une page a été lue.
  • WP Super Cache, qui accélère les sites.

On peut accéder au tableau de bord WordPress du futur site en suivant le lien de preview et en ajoutant wp-login à la fin. On se connecte avec les informations notées dans la partie B de la check-list.

Je réactive ces deux extensions (elles sont désactivées du fait du changement de base de données).

Etape 4 Pointage des DNS vers le nouvel hébergement

4.1 Pointer vers les bonnes adresses IP

Dans le tableau de bord Infomaniak, un bandeau indique que certains noms de domaines ne sont pas correctement liés à cet hébergement.

C’est normal puisqu’on n’a pas encore indiqué la nouvelle adresse IP de l’hébergement. Pour tous les internautes, l’url du site pointe toujours vers l’ancien hébergement.

Infomaniak : diagnostic DNS

Il suffit de cliquer sur « afficher les diagnostics » pour visualiser les recommandations d’Infomaniak :

testal.com AAAA 2001:db8:0:85a3:0:0:ac1f:8001
testal.com A 81.174.114.61
www. testal.com CNAME testal.com.

On peut suivre la propagation avec le tableau de bord Infomaniak ou whatsmydns.

4.2 Modifier l’URL du site

Comme dans le paragraphe 2.6 (paramétrage du site WordPress Infomaniak), on modifie le « site internet à utiliser » pour qu’il redevienne http://testal.com

Etape 5 Activation d’un certificat SSL Let’s Encrypt.

Installation d’un certificat SSL Let’s Encrypt

Cette action ne peut être réalisée que lorsque la propagation des nouveaux DNS est suffisante. Il y aura donc une période d’une durée variant entre quelques dizaines de minute et quelques heures (24 heures max) durant laquelle le site ne sera accessible qu’en http.

Dans le tableau de bord Infomaniak, choisir Certificats SSL dans le menu vertical à gauche.

Sélectionner le site pour lequel on veut un certificat puis cliquer sur « installer ».

Tant que les DNS ne sont pas suffisamment propagé (jusqu’au serveur Let’s Encrypt), on a un message d’erreur comme ci-dessous pour le certificat SSL gratuit :

Infomaniak : certificat SSL gratuit avec erreur

Une fois que l’erreur a cessé, on sélectionne ce certificat et on l’installe.

Régler l’url utilisée pour le site (https)

Comme dans le paragraphe 2.6 (paramétrage du site WordPress Infomaniak), on modifie le « site internet à utiliser » pour qu’il redevienne https://testal.com . Cette option n’est proposée que lorsqu’on a installé un certificat SSL.

Autres réglages

Je n’ai pas eu besoin de modifier le .htaccess puisqu’Infomaniak gère tout seul.

Optionnel : mesurer la vitesse du site après transfert

https://gtmetrix.com/

https://testmysite.thinkwithgoogle.com/

Il n’y a aucune amélioration liée au nouvel hébergement.

Si maintenant j’active WP Super Cache, avec ses réglages par défaut. Les résultats sont les mêmes, assez décevants…

Et maintenant ?

Je vais maintenant travailler sur le transfert des serveurs de mail et sur l’optimisation de la vitesse des sites.

Partager son écran avec Google Hangout

Partager son écran avec Google Hangout

Pour partager un contenu ou faire du dépannage, nous pouvons avoir besoin de partager notre écran avec d’autres personnes. C’est très simple si vous avez un compte GMail, il suffit d’utiliser Google Hangout.

Ce qu’il vous faut

Un compte Gmail et c’est tout.

Comment faire

Dans Gmail, cliquer sur la caméra dans la colonne de gauche de l’écran :

Démarrer appel vidéo - Hangout

Inviter les destinataires

Un écran Google Hangout s’ouvre. Au bout de quelques secondes, l’écran nous invite à envoyer des invitations.

Inviter au Hangout

Les destinataires recoivent un mail avec un lien de connexion. c’est très simple pour eux.

Régler le type de partage d’écran

Une fois les invitations lancées, en attendant que tout le monde se connecte, on règle le type de partage d’écran :

  • écran entier (onglet par défaut)
  • fenêtre d’une application spécifique, choisie parmi celles qui sont déjà ouvertes (deuxième onglet)

Hangout Partage de tout l'écran Hangout Partage d'écran d'une application

Et voilà, notre écran, ou la fenêtre choisie, devient visible de nos invités.

Autres sources d’information

Le document d’aide de Google qui m’a aidé la première fois est Partager votre écran au cours d’un Hangout.

Sauvegarder automatiquement avec Snapshot Pro de wpmudev

Sauvegarder automatiquement avec Snapshot Pro de wpmudev

Dans le cadre de mon abonnement annuel à wpmudev (voir le premier article de cette série ), j’ai accès à différentes extensions très intéressantes. L’une d’elle est Snapshot Pro, qui permet de sauvegarder les sites automatiquement et de les restaurer en un clic. J’explique ici comment la régler, c’est très simple et très efficace.

L’intérêt de Snapshot Pro

Snapshot Pro est accessible aux abonnés à wpmudev. Lorsqu’on a un abonnement, on peut l’installer sur autant de sites que l’on veut. Cette extension a des fonctionnalités intéressantes :

  • Accès à un stockage cloud de WPMU DEV de 10 Go ;
  • Sauvegarde en FTP ou SFTP, sur Amazon S3, Dropbox ou Google Drive ;
  • Sauvegarde de tout ou partie du site ;
  • Automatisation des sauvegardes à périodicité définie ;
  • Sauvegarde de sites WordPress simples ou multisites ;
  • Restauration de site (multisites compris) en un clic, y compris à partir de la sauvegarde vers Dropbox.

Configuration de Snapshot Pro

Une fois Snapshot Pro installé et activé, il faut le régler. Ca se passe dans le menu Snapshot >> Settings de WordPress.

Je laisse tout tel que c’est réglé initialement. En particulier, les sauvegardes réalisées directement sur l’hébergement du site seront placées dans un répertoire « snapshots », sous /wp-content/uploads/.

Réglage des destinations de sauvegardes

dans le menu Snapshot >> Destinations de WordPress, on règle les destinations possibles pour les sauvegardes. Pour ma part, il y a Dropbox et un hébergement tiers, en FTP.

Destination Dropbox

On donne un nom à cette destination puis on clique sur « save destination ». On donne ensuite l’autorisation dans la fenêtre qui s’ouvre (WPMU DEV Snapshot souhaite accéder à son propre dossier, « Applications › WPMU DEV Snapshot« , dans votre Dropbox.) et c’est fait.

Destination FTP

Pour l’instant, je veux sauvegarder dans un hébergement pro d’OVH. Je remplis donc les informations suivantes :

Destination Name nom hébergement FTP
server Address ftp.clusterxxxxx.hosting.ovh.net
user name unusername
Password unmotdepasse
Remote Path /Plesk-snapshots/
Connection Protocol FTP
Server Port (vide)
Server Timeout (vide)
Passive Mode No

Attention le ‘remote path’ doit avoir été créé au préalable sur l’hébergement cible.

Une fois que j’ai sauvegardé chaque destination, l’écran « Snapshot » >> « Destination » est comme suit :

Destinations Snapshot Pro (WPMU DEV)

Réglage des sauvegardes sur le cloud wpmudev

Dans « Snapshot » >> « Destination », cliquer sur le bouton « Configure Full Backups ». On doit récupérer la clé API de Snapshot et la coller dans notre tableau de bord WordPress. Ensuite, on clique sur « activate managed backup ».

On est alors renvoyé à « Snapshot » et on peut si on le souhaite modifier la fréquence des sauvegardes et le type de messages d’erreur à gérer. J’ai laissé une fréquence hebdomadaire et le log des erreurs cochées par défaut.

Planification des sauvegardes

Dans Snapshot >> Add New, on peut créer de nouvelles planifications de sauvegardes.

Pour une sauvegarde FTP

Réglage d'une sauvegarde planifiée en FTP sur Snapshot Pro - écran 1

Réglage d’une sauvegarde planifiée en FTP sur Snapshot Pro – écran 1

Réglage d'une sauvegarde planifiée en FTP sur Snapshot Pro - écran 2

Réglage d’une sauvegarde planifiée en FTP sur Snapshot Pro – écran 2

Réglage d'une sauvegarde planifiée en FTP sur Snapshot Pro - écran 3

Réglage d’une sauvegarde planifiée en FTP sur Snapshot Pro – écran 3

 

Pour une sauvegarde Dropbox

On fait exactement la même chose (avec évidemment une destination différente).

Pour ma part, j’utilise les mêmes réglages que pour le FTP à deux différences près :

  • backup interval : daily managed snapshot
  • keep local archives = yes

Et voilà ! On a maintenant des sauvegardes automatiques sur plusieurs destinations.

Installer wpmudev Dashboard

Installer wpmudev Dashboard

Une fois que l’on a souscrit un abonnement annuel à wpmudev, il faut installer un « dashboard » sur chaque site. Il s’agit d’une extension, disponible sur wpmudev ici. Ses principales fonctionnalités sont :

  • Mise à jour automatique des extensions et thèmes wpmudev (pas des autres) ;
  • Accès à un tableau de bord global, avec tous les sites gérés ;
  • Installation en un clic des extensions wpmudev ;
  • Accès temporaire pour le support techniques aux sites ;

Installation du dashboard

On télécharge le fichier zippé en cliquant sur le bouton « download » de la page de l’extension wpmudev dashboard.

Une fois l’extension activée, le site apparaît automatiquement dans la liste des sites gérés dans mon « hub » wpmudev.

Suivi des interruptions de fonctionnement

On peut activer le suivi des « uptimes » dans le hub. wpmudev suit maintenant les pannes du site. Mais je ne reçois pas de notification en cas de panne. Je continue donc à utiliser simultanément le système d’alerte que j’ai créé avec Google Sheets, système que j’ai décrit dans l’article Surveiller des sites automatiquement (http 200) avec Google Sheets et un script.

Et maintenant ?

Dans le prochain article de cette série , je vais voir comment créer des sauvegardes automatiques vers wpmudev, DropBox et en FTP.

Utiliser un abonnement WPMuDev

Utiliser un abonnement WPMuDev

Lorsqu’on gère plusieurs sites, on a besoin de pouvoir automatiser certains actes de gestion courante. Au stade où j’en suis, j’ai besoin d’automatiser les actes suivants :

  • créer un nouvel hébergement ou un nouveau site (à l’intérieur d’un hébergement), avec des paramètres précis (version de PHP par exemple).
  • installer automatiquement les extensions WordPress requises.
  • Mettre à jour les extensions de manière centralisée.
  • Suivre les pannes.
  • Créer des sauvegardes périodiques.

L’hébergement VPS Classic d’OVH, avec Plesk for Resellers, répond correctement aux besoins pour les 4 premiers points. Mais il n’y a aucune alerte automatique en cas de panne et le système intégré de sauvegardes périodique ne m’inspire pas totalement confiance car je ne suis pas certaine de pouvoir restaurer la sauvegarde en cas de problème.

J’ai essayé une option qui me paraissait intéressante en 2016 : ManageWP qui gérait les sauvegardes, le clonage de sites et autres options pour 5 domaines (les sous-domaines sont aussi gérés) moyennant environ $100 par an.  Mais après l’été, ils ont installé un nouveau système de sauvegarde et il y avait des erreurs fréquentes. Et comme ce système est incapable de gérer des multisites, j’ai commencé à chercher une autre solution.

La solution que j’ai adoptée pour 2017 est un abonnement à wpmudev. J’ai acheté 1 an d’abonnement pour environ $290 un jour où il y avait une réduction de 50%. C’est cher, mais pour ce prix, on peut gérer un nombre illimité de domaines, on bénéficie d’une assistance 24/24 et 7/7 et d’un accès illimité à une large gamme d’extensions intéressantes (dont certaines pour les multisites). Le seul inconvénient est que l’ensemble de la documentation est en anglais.

Dans les prochains articles de cette série , je vais explorer les possibilités ouvertes par cet abonnement.

Surveiller des sites automatiquement (http 200) avec Google Sheets et un script

Surveiller des sites automatiquement (http 200) avec Google Sheets et un script

Nous allons voir comment lire le statut HTTP d’un site internet avec Google Sheets et envoyer un email automatique en cas d’anomalie.

J’ai rencontré des soucis (non résolus 10 jours après mon premier signalement…) avec mon hébergement Plesk. Il arrive que la base de données de l’hébergement soit en panne et on n’a aucun moyen de le savoir sans essayer d’accéder à l’un des sites de l’hébergement. Les systèmes habituels de vérification par « ping » ne donne pas satisfaction car les sites répondent à un ping mais sont inaccessible depuis un navigateur (le code HTTP n’est pas 200). Comme mon fournisseur d’hébergement se montre incapable d’accepter qu’il y a un problème ou au moins de générer une alerte automatique en cas de panne de la base de données, j’ai décidé de créer un système d’alerte automatique.

Obtenir le code HTTP de réponse d’un site avec Google Sheets

Je me suis inspirée de cet article : How to Pull an HTTP Response Code in Google Sheet.

J’ai créé un fichier Google Sheets dans lequel j’ai placé le tableau suivant :

site url statut
parcours-P parcours-performance.com =VALUE(HTTPResponse(B3))
knowledge PP knowledge.parcours-performance.com =VALUE(HTTPResponse(B4))

Ce qui donne ce qui suit dans Google Sheets :

Google Sheets : surveiller le code httpde sites

Google Sheets : surveiller le code httpde sites

 

Avec l’éditeur de scripts (menu « Outils »), j’ai créé la fonction HTTPResponse .

/*****************************************************************
* check websites for http response
*****************************************************************/

function HTTPResponse( uri )
{
 /* source https://atulhost.com/how-to-pull-an-http-response-code-in-google-sheet */
 var response_code ;
try {
 response_code = UrlFetchApp .fetch( uri ) .getResponseCode() .toString() ;
 }
catch( error ) {
 response_code = error .toString() .match( / returned code (\d\d\d)\./ )[1] ;
 }
finally {
 return response_code ;
 }
}

J’ai ensuite cliqué sur « enregistrer ».

Lorsque je retourne dans ma feuille de calcul, si les sites fonctionnent, je vois « 200 » dans la troisième colonne de mon tableau, celle qui contient =VALUE(HTTPResponse(Bx)) .

Régler la fréquence de vérification

Je veux vérifier au moins toutes les heures que les sites sont opérationnels.

Dans l’éditeur de scripts, je sélectionne (A) la fonction HTTPResponse puis je clique sur le bouton « déclencheur du projet actuel » (B). Ensuite, je régle le déclenhement pour que le script s’exécute à chaque heure :

Régler le déclencheur d'un script Google Sheets

Régler le déclencheur d’un script Google Sheets

Déclencher un script Google Sheets toutes les heures

Déclencher un script Google Sheets toutes les heures

Générer un mail automatique en cas d’anomalie avec Google Sheets

Pour cette partie, je me suis beaucoup inspirée de « Automating Google Spreadsheets – Email Reminders« .

Dans l’éditeur de script, j’ai placé la fonction checkStatut() :

/*****************************************************************
* Send an alert if somme http responses are not 200 OK
*****************************************************************/
function checkStatut() {
  
  /* source https://www.withoutthesarcasm.com/automating-google-spreadsheets-email-reminders/ */
  
  // get the spreadsheet object
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  // set the first sheet as active
  SpreadsheetApp.setActiveSheet(spreadsheet.getSheets()[0]);
  // fetch this sheet
  var sheet = spreadsheet.getActiveSheet();
   
  // figure out what the last row is
  var lastRow = sheet.getLastRow();
 
  // the rows are indexed starting at 1, and the second row
  // is the headers, so start with row 3
  var startRow = 3;
 
  // grab column 3 (the 'statut' column) 
  // getRange(row, column, numRows, numColumns)
  var range = sheet.getRange(startRow, 3,lastRow-startRow+1,1 );
  var numRows = range.getNumRows();
  var statut_values = range.getValues();

  // Now, grab the site name column (2)
  range = sheet.getRange(startRow, 2, lastRow-startRow+1, 1);
  var site_name_values = range.getValues();
  var warning_count = 0;
  var msg = "";
   
  // Loop over statut values
  for (var i = 0; i <= numRows - 1; i++) {
    var statut = statut_values[i][0];
    if(statut != 200) {
      var site_name = site_name_values[i][0];
       
      msg = msg + "Site : "+site_name+" ne fonctionne pas HTTP code "+statut+" .\n";
      warning_count++;
    }
  }
   
  if(warning_count) {
    MailApp.sendEmail("mail@parcours-performance.com", 
        "Des sites en panne", msg);
  }
};

Cette fonction identifie le bon onglet (0) de la feuille de calcul puis lit toutes les données de statut. Lorsqu’un statut n’est pas égal à 200 (OK), la fonction lit le nom du site correspondant. La fonction crée un message (msg) avec tous les dysfonctionnements puis, s’il y a des alertes, m’envoie un mail pour m’en informer.

Le déclencheur de la fonction est un changement dans la feuille de calcul (lorsque  HTTPResponse se déclenche et indique une réponse différente de ce qui précédait) :

Déclencher un script Google Sheets lorsque la feuille change

Déclencher un script Google Sheets lorsque la feuille change

 

J’ai vérifié que ça fonctionne en placant « 404 » dans l’une des cellules de statut et je reçois bien un mail d’alerte.

Et maintenant

Je suis en train de regarder comment changer d’hébergeur mais je dispose maintenant d’un système d’alerte des anomalies. Si je reçois un mail, je me connecte à mon interface client et je redémarre le VPS. En quelques minutes tous mes sites fonctionnent de nouveau.

Transformer un site WordPress Multisite en site individuel

Transformer un site WordPress Multisite en site individuel

Dans ce dernier article de la série , nous allons voir comment ressortir un site d’un multisite WordPress.

Le fonctionnement multisite de WordPress est très pratique et simple mais je suis contrainte de scinder un multisite (heureusement encore peu fourni) car je transfère le site sur un VPS avec Plesk et il est pour l’instant impossible d’avoir plusieurs domaines distincts avec des certificats Let’s Encrypt distincts sur un seul hébergement Plesk…

Les spécificités du multisite

Si on veut sortir un site d’un multisite, il faut le « détricoter » :

  • Pour les fichiers, il faut remettre toutes les extensions du site principal dans le site devenu orphelin et il faut également lui transférer ses fichiers médias. C’est simple à faire.
  • Dans la base de données, c’est plus compliqué. Il y a des tables spécifiques au site à séparer mais certaines sont partagées entre tous les sites du multisite. C’est là que le détricotage est un peu fastidieux.

Trouver l’identifiant du site à sortir

Dans le tableau de bord du multisite, aller sur mes sites > Admin du Réseau > Sites.

Passer la souris sur le nom du site à déplacer (disons « subdomain.com »). Son url complète s’affiche en bas de la fenêtre, sous la forme https://domaine.comwp-admin/network/site-info.php?id=3. Ici l’identifiant est donc « 3 ». On en aura besoin pour la suite.

christmas project #3 : advent boxes

Sauvegarder le multisite

Sauvegarder les fichiers

Avec Filezilla : sauvegarder le répertoire /www/wp-content/uploads/sites/3  (3 est l’identifiant du site que l’on veut sortir).

Sauvegarder la base de données

Nota du 23/11/216 : pour des raisons que j’ignore, l’export via PHPMyAdmin provoque parfois une erreur : les index et auto-incrémentations ne sont pas transférés. Dans ce cas, il faut aller dans l’interface client de l’hébergement OVH original et demander une sauvegarde de la base de données (un dump) que l’on reçoit quelques minutes plus tard par mail. Cette sauvegarde s’importe ensuite sans souci dans la base Plesk.

Noter les informations du site

On a intérêt à bien noter (copies d’écran) les informations suivantes :

  • quel est le nom du thème (stargazer pour moi) et ses réglages ?
  • quelles sont les extensions utilisées et faisant l’objet d’un réglage spécifique ? Pour mon cas, Cookie Notice, Floating Social Bar
  • Quels sont les utilisateurs de ce site ?

Installer WordPress sur un nouvel hébergement

J’utilise maintenant un VPS avec Plesk for Resellers. J’installe donc WordPress conformément à Transférer un hébergement mutualisé OVH sur un VPS Plesk d’OVH.

Transférer les fichiers

Dans l’installation de WordPress, copier /www/wp-content/uploads/sites/3 de l’ancien site vers /www/wp-content/uploads/  dans le nouveau. Je copie aussi les fichiers de tous les plugins et thèmes que je veux utiliser. C’est plus rapide qu’une installation par le tableau de bord.

Transférer les bons éléments de la base de données

Sauvegarder la base de donnée du site cible

Disons que son prefixe est ‘cible_ ‘.

Importer la base de données du multisite d’origine

En principe elle n’a pas les mêmes préfixes (‘source_’ ) et ne va pas supprimer les tables du site cible.

Supprimer les tables ‘source_’

Les seules qu’on conserve sont :

  • source_3_options ;
  • source_options ;
  • source_usermeta ;
  • source_users.

Supprimer les tables du site cible

On ne touche pas à cible_options, cible_usermeta et cible_users) et on supprime :

  • cible_comments
  • cible_links
  • cible_postmeta
  • cible_posts
  • cible_termmeta
  • cible_terms
  • cible_term_relationships
  • cible_term_taxonomy

Renommer les tables

  • source_comments en cible_comments
  • source_links en cible_links
  • source_postmeta en cible_postmeta
  • source_posts en cible_posts
  • source_termmeta en cible_termmeta
  • source_terms en cible_terms
  • source_term_relationships en cible_term_relationships
  • source_term_taxonomy en cible_term_taxonomy

Modifier à la main certaines entrées de cible_options

Il faut faire du sur mesure… Le site que je détricotais était heureusement très simple. J’ai simplement dû aller chercher dans la table source_3_options  les valeurs des éléments qui nous semblent mériter d’être transféré et copier-coller la valeur dans l’option de même nom de la table cible_options .

Conserver une trace de certaines entrées

Certaines entrées n’existent pas encore puisqu’il faut activer le thème ou l’extension, puis faire une petite modification des réglages pour qu’elles se créent.

J’ai copié-collé dans un éditeur de texte les valeurs de current_theme, theme_mods_stargazer et cookie_notice_options pour les avoir plus tard.

Modifier les enregistrements DNS

Pointer le domaine subdomain.com vers le nouvel hébergement.

Avec whatsmydns.net, voir la propagation du nouveau DNS.

Créer le certificat Let’s encrypt de subdomain.com (en cochant l’option www).

Faire les derniers réglages

Pour une raison que j’ignore, Chrome conserve longtemps l’ancienne adresse IP du site. J’ai trouvé que c’était très irritant puis maintenant c’est très pratique !

Je tape subdomain.com dans firefox (réglé pour ne conserver aucun historique) et il affiche le nouveau site. Je peux me connecter à son tableau de bord.

Pendant ce temps, Chrome continue à afficher l’ancien site et si on se connecte, on se connecte à l’ancien tableau de bord. C’est pratique si on ne trouve pas les bonnes infos dans la base de données.

Modifier à la main les données

J’ai activé le thème stargazer puis fait une toute petite modification de son apparence. Ainsi, theme_mods_stargazer apparait maintenant dans cible_options. Je peux y copier-coller la valeur qui était dans la table du site source. Et automatiquement tous les réglages sont repris (sauf pour l’image de header, qu’il faut désactiver puis réactiver pour qu’elle s’affiche).

Dans les réglages de l’extension cookie-notice, j’ai également fait une toute petite modification. Dans la table cible_options, l’option cookie_notice_options est maintenant visible. Je peux aussi y copier-coller la valeur qui était dans la table source-options.

Pour le reste, j’ai copié-collé les réglages entre l’ancien site visible sur chrome et le nouveau visible sur firefox.

Rajouter les utilisateurs du site source

Il faut rajouter à la main les utilisateurs du site source. Comme on a conservé les tables source_3_usermeta et source_3_users, on peut assez facilement retrouver les bonnes informations.

Et malheureusement si l’id des users a changé, on risque d’être obligé d’aller réaffecter les contenus aux bons users…

Modifier wp-config.php et .htaccess

Vu que le site créé est crypté (certificat Let’s encrypt), il faut modifier certains éléments. Et je veux aussi interdire l’édition de fichiers dans le tableau de bord WordPress et limiter le nombre de révisions à 5.

Dans wp-config.php (avant la ligne  /* That’s all, stop editing! Happy blogging. */  ), ajouter les lignes suivantes :

// Forcer l'accès SSL (https) pour le tableau de bord WordPress
define('FORCE_SSL_ADMIN', true);

// interdire l'édition de fichiers dans le tdb WordPress
define('DISALLOW_FILE_EDIT', TRUE);

define('WP_POST_REVISIONS', 5);
// max 5 stored revisions per posts

Et dans .htaccess, le contenu devrait être le suivant :

RewriteEngine on
 
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ https://%1/$1 [R=301,L]
 
RewriteCond %{HTTPS} !on
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

# END WordPress

Et maintenant ?

Une fois que la propagation des DNS est terminée (il vaut mieux attendre 24h), je peux supprimer le site dans son multisite source. Notre site est maintenant autonome.

 

PHP : obtenir automatiquement le chemin d’accès

J’essaie de toujours créer des chemins relatifs, pour éviter de devoir modifier des documents si leur racine change.
Pour lire les données de mon Pi sur un site web en PHP, j’avais besoin de trouver automatiquement l’url du site, avec son protocole http ou https selon les cas.
Je me suis inspirée de PHP Document Root, Path and URL detection.

Dans un fichier php, il suffit de placer le code suivant pour savoir à quoi chaque élément correspond :

	<?php
	// http://blog.lavoie.sl/2013/02/php-document-root-path-and-url-detection.html
	$base_dir  = __DIR__; // Absolute path to your installation, ex: /var/www/mywebsite
	$doc_root  = preg_replace("!${_SERVER['SCRIPT_NAME']}$!", '', $_SERVER['SCRIPT_FILENAME']); # ex: /var/www
	$base_url  = preg_replace("!^${doc_root}!", '', $base_dir); # ex: '' or '/mywebsite'
	$protocol  = empty($_SERVER['HTTPS']) ? 'http' : 'https';
	$port      = $_SERVER['SERVER_PORT'];
	$disp_port = ($protocol == 'http' && $port == 80 || $protocol == 'https' && $port == 443) ? '' : ":$port";
	$domain    = $_SERVER['SERVER_NAME'];
	$full_url  = "${protocol}://${domain}${disp_port}${base_url}"; # Ex: 'http://example.com', 'https://example.com/mywebsite', etc.
	?>


<table>
<tbody>
<tr>
<td width="102">$base_dir</td>
<td width="512"><?php echo $base_dir  ; ?></td>
</tr>
<tr>
<td width="102">$doc_root</td>
<td width="512"><?php echo $doc_root  ; ?></td>
</tr>
<tr>
<td width="102">$base_url</td>
<td width="512"><?php echo $base_url  ; ?></td>
</tr>
<tr>
<td width="102">$protocol</td>
<td width="512"><?php echo $protocol  ; ?></td>
</tr>
<tr>
<td width="102">$port</td>
<td width="512"><?php echo $port  ; ?></td>
</tr>
<tr>
<td width="102">$disp_port</td>
<td width="512"><?php echo $disp_port  ; ?></td>
</tr>
<tr>
<td width="102">$domain</td>
<td width="512"><?php echo $domain  ; ?></td>
</tr>
<tr>
<td width="102">$full_url</td>
<td width="512"><?php echo $full_url  ; ?></td>
</tr>
</tbody>
</table>

On obtient le résultat suivant :

$base_dir /var/www/vhosts/domaine.com/pi.domaine.com
$doc_root /var/www/vhosts/domaine.com/pi.domaine.com
$base_url
$protocol https
$port 443
$disp_port
$domain pi.domaine.com
$full_url https://pi.domaine.com

A quoi ça sert ?

Si je veux que le fichier PHP ailler chercher un fichier css dans un répertoire /css, il me suffit maintenant d’ajouter dans <head> :

	<?php
	// http://blog.lavoie.sl/2013/02/php-document-root-path-and-url-detection.html
	$base_dir  = __DIR__; // Absolute path to your installation, ex: /var/www/mywebsite
	$doc_root  = preg_replace("!${_SERVER['SCRIPT_NAME']}$!", '', $_SERVER['SCRIPT_FILENAME']); # ex: /var/www
	$base_url  = preg_replace("!^${doc_root}!", '', $base_dir); # ex: '' or '/mywebsite'
	$protocol  = empty($_SERVER['HTTPS']) ? 'http' : 'https';
	$port      = $_SERVER['SERVER_PORT'];
	$disp_port = ($protocol == 'http' && $port == 80 || $protocol == 'https' && $port == 443) ? '' : ":$port";
	$domain    = $_SERVER['SERVER_NAME'];
	$full_url  = "${protocol}://${domain}${disp_port}${base_url}"; # Ex: 'http://example.com', 'https://example.com/mywebsite', etc.
	?>
   <link rel="stylesheet" href="<?php echo $full_url . '/css/pi-stylesheet.css' ; ?>">