{"id":511,"date":"2012-10-12T08:00:17","date_gmt":"2012-10-12T06:00:17","guid":{"rendered":"http:\/\/www.superkikim.com\/?p=511"},"modified":"2015-09-02T16:14:00","modified_gmt":"2015-09-02T14:14:00","slug":"script-de-backup-plesk-9-x-et-superieur","status":"publish","type":"post","link":"https:\/\/akim.sissaoui.com\/en\/informatique\/script-de-backup-plesk-9-x-et-superieur\/","title":{"rendered":"Script de backup plesk (9.x et sup\u00e9rieur)"},"content":{"rendered":"<p><span style=\"font-size: 13.63636302947998px; line-height: 1.8em;\">== Mise \u00e0 jour ==<\/span><\/p>\n<p>Cet article a \u00e9t\u00e9 mis \u00e0 jour le 12 octobre 2012, avec l&#8217;ajout d&#8217;une fonction d&#8217;exclusion permettant d&#8217;exclure certains domaines. J&#8217;ai \u00e9galement repris les utilisateurs SQL dans backup.conf plut\u00f4t que dans le script directement.<\/p>\n<p>J&#8217;utilise ce script au quotidien avec Plesk 9 et Plesk 10. Je ne l&#8217;ai pas test\u00e9 avec Plesk 11. Si quelqu&#8217;un le test, merci de me donner un feedback.<\/p>\n<p>== Introduction ==<\/p>\n<p>Je me suis affranchi de la configuration des sauvegardes plesk depuis le GUI. J&#8217;ai pr\u00e9f\u00e9r\u00e9 faire mon propre script qui backup la configuration du serveur, la configuration de chaque revendeur, et enfin, chaque domaine individuellement. J&#8217;ai cr\u00e9\u00e9 ce script, car en faisant des sauvegardes depuis le plesk panel vers du FTP, j&#8217;avais toujours des probl\u00e8mes. Le FTP tombait, (tr\u00e8s mauvais FTP chez OVH \u00e0 cette \u00e9poque), et j&#8217;avais d&#8217;autres souci comme des faux probl\u00e8mes de droits sur le FTP (alors que ce n&#8217;\u00e9tait pas le cas). Bref, j&#8217;ai beaucoup gal\u00e9r\u00e9&#8230; On est jamais mieux servi que par soi-m\u00eame au final.<\/p>\n<p>Il y a s\u00fbrement milles fa\u00e7ons plus simples, et plus compliqu\u00e9es de faire. Perso, c&#8217;est la m\u00e9thode dont je me suis servi, et je la partage avec vous. Apr\u00e8s, \u00e0 vous de faire avec ou pas&#8230;<\/p>\n<p><!--more--><!--toc--><\/p>\n<p>Ce script a les fonctionnalit\u00e9s suivantes:<\/p>\n<ul>\n<li>Sauvegarde de la configuration du serveur avec notification \u00e0 l&#8217;administrateur du serveur<\/li>\n<li>Sauvegarde de la configuration des revendeurs avec notification aux revendeurs par email<\/li>\n<li>Sauvegarde de chaque domaine individuellement avec notification au revendeur par email<\/li>\n<li>Envoi des fichiers de sauvegarde sur un serveur FTP<\/li>\n<li>R\u00e9tention locale avec suppression des anciens fichiers<\/li>\n<li>R\u00e9tention FTP avec suppression des anciens fichiers<\/li>\n<li>Suppression des fichiers temporaires afin de lib\u00e9rer la place pour la sauvegarde du jour suivant<\/li>\n<li>Rapports d&#8217;erreur par email<\/li>\n<li>Rapport r\u00e9sum\u00e9 de l&#8217;op\u00e9ration par email<\/li>\n<\/ul>\n<p>Ce script utilise le programme ncftp que vous pouvez installer sur votre distribution.<\/p>\n<p>Ma distribution est Debian Lenny. Il se peut que vous deviez apporter des petites adaptations suivant votre distribution. Je vous laisse maitre de \u00e7a.<\/p>\n<p>Le script compose de trois fichiers:<\/p>\n<ol>\n<li>\/root\/backup.conf qui contient les variables modifiables<\/li>\n<li>\/root\/start_backup qui lance l&#8217;ex\u00e9cution, et \u00e9vite qu&#8217;il soit lanc\u00e9 une deuxi\u00e8me fois manuellement par exemple (\u00e7a m&#8217;est arriv\u00e9)<\/li>\n<li>\/root\/backup qui est le script en lui-m\u00eame. Ces trois scripts sont disponibles en entier \u00e0 la fin de cet article<\/li>\n<\/ol>\n<p>== Variables ==<\/p>\n<p>Les variables utilis\u00e9es dans ce scripts sont:<\/p>\n<ul>\n<li>localdaystodel: R\u00e9tention locale en nombre de jours<\/li>\n<li>remotedaystodel: R\u00e9tention distante (sur le serveur FTP) en nombre de jours<\/li>\n<li>blogs: Chemin du dossier de sauvegarde des logs de backup et ftp<\/li>\n<li>mailtodaylog: Nom du fichier de log du jour (ou du moment puisqu&#8217;il inclus l&#8217;heure)<\/li>\n<li>fuser: Nom d&#8217;utilisateur FTP pour la copie distante<\/li>\n<li>fpass: Mot de passe de l&#8217;utilisateur FTP pour la copie distante<\/li>\n<li>fpath: Chemin de sauvegarde sur le serveur FTP<\/li>\n<li>fserv: Nom ou adresse IP du serveur FTP<\/li>\n<li>btmp: Chemin de stockage sauvegardes locales<\/li>\n<li>ccmail: Option et adresse email pour l&#8217;envoi de copies des rapports de sauvegade.<\/li>\n<li>pbpath: Chemin de l&#8217;ex\u00e9cutable pleskbackup<\/li>\n<li>PMMpath: Chemin des fichiers logs de pleskbackup<\/li>\n<li>mysqluser: Nom d&#8217;utilisateur admin MySQL pour plesk<\/li>\n<li>mysqlpwd: Mot de passe de l&#8217;utilisateur pr\u00e9cit\u00e9<\/li>\n<li>excl: Liste de domaines \u00e0 exclure de la sauvegarde, s\u00e9par\u00e9s par un espace<\/li>\n<\/ul>\n<p>Toutes ces variables sont \u00e0 inscrire dans un fichier appeler backup.conf dont vous trouverez un exemple au bas de cet article. La variable ccmail est optionnelle. Attention: le &#8220;-c&#8221; est indispensable. Il fait partie de la commande d&#8217;envoi. Si vous indiquez une adresse email, il FAUT imp\u00e9rativement mettre &#8220;-c&#8221; devant.<\/p>\n<p>== Le script de lancement ==<\/p>\n<p>Celui-ci n&#8217;a que pour but de s&#8217;assurer que le script de backup n&#8217;a pas d\u00e9j\u00e0 \u00e9t\u00e9 ex\u00e9cut\u00e9, et ainsi, d&#8217;\u00e9viter que deux op\u00e9rations de sauvegardes soient en cours simultan\u00e9ment. Il v\u00e9rifie donc dans &#8220;ps ax&#8221; que le script backup n&#8217;est pas en cours d&#8217;ex\u00e9cution.<\/p>\n<p>== Le script de sauvegarde ==<\/p>\n<p>Voici le gros morceau, expliqu\u00e9 point par point. Vous en trouvez une version compl\u00e8te t\u00e9l\u00e9chargeable au bas de l&#8217;article.<\/p>\n<p>On commence bien s\u00fbr par la d\u00e9claration de l&#8217;environnement d&#8217;ex\u00e9cution<\/p>\n<pre lang=\"bash\">#!\/bin\/sh<\/pre>\n<p>On inclut ensuite le fichier backup.conf:<\/p>\n<pre lang=\"bash\">. \/root\/backup.conf<\/pre>\n<p>Le code suivant va supprimer les fichiers plus anciens que la r\u00e9tention locale d\u00e9sir\u00e9e.<\/p>\n<pre lang=\"bash\">rm $btmp\/*`date --date=\"$localdaystodel days ago\" +%Y%m%d`*<\/pre>\n<p>Pleskbackup a la d\u00e9sagr\u00e9able tendance a garder des logs ad eternam. POur \u00e9viter des surprises d&#8217;utilisation du disque, on supprime tous les logs de plus de 30 jours<\/p>\n<pre lang=\"bash\">find \/opt\/psa\/PMM\/sessions -mtime +30 -type d | grep -v archives | xargs rm -Rf<\/pre>\n<p>On cr\u00e9e ensuite le fichier de log, d\u00e9finit par la variable maintodaylog d\u00e9crite plus haut<\/p>\n<pre lang=\"bash\">echo -e \"****************\" Backup Job Started $(date +%A) $(date +%_d) $(date +%B) $(date +%Y) at $(date +%T) \"***************\"\\\\n\\\\n > $maintodaylog<\/pre>\n<p>=== Sauvegarde de la configuration du serveur ===<br \/>\nOn r\u00e9cup\u00e8re l&#8217;adresse email de l&#8217;administrateur de plesk dans la base de donn\u00e9e plesk.<\/p>\n<pre lang=\"bash\">destmail=`mysql -e\"use psa;select email from clients where login='admin'\" -u$mysqluser -p\"$mysqlpwd\" | tail -n +2`<\/pre>\n<p>La variable current va revenir r\u00e9guli\u00e8rement dans le script. Elle permet de savoir \u00e0 quelle t\u00e2che il en est. Ici, on d\u00e9finit le nom de la sauvegarde de la configuration du serveur. Je m&#8217;en sers pour faire un log pour chaque op\u00e9ration.<\/p>\n<pre lang=\"bash\">current=\"ServerConfig_ServerConfig_$(date +%Y%m%d_%H%M%S)\"<\/pre>\n<p>La variable blog est ensuite utilis\u00e9e pour d\u00e9finir le chemin du fichier de log de l&#8217;op\u00e9ration en cours, par opposition \u00e0 &#8220;maintodaylog&#8221; qui est le log global et r\u00e9sum\u00e9 de l&#8217;op\u00e9ration.<\/p>\n<pre lang=\"bash\">blog=\"$blogs\/$current.log\"<\/pre>\n<p>Toujours bas\u00e9 sur la variable &#8220;current&#8221;, je d\u00e9finis le nom du fichier tar pour la sauvegarde locale<\/p>\n<pre lang=\"bash\">nextfile=\"$current.tar\"<\/pre>\n<p>J&#8217;utilise la commande echo pour envoyer des commentaires dans le fichier de log au fur et \u00e0 mesure du script. Ici, je d\u00e9clare le d\u00e9but de l&#8217;op\u00e9ration<\/p>\n<pre lang=\"bash\">echo \"===== Server configuration backup started at $(date +%T) =====\" > $blog<\/pre>\n<p>J&#8217;ex\u00e9cute ma premi\u00e8re op\u00e9ration. Il s&#8217;agit de la sauvegarde de la configuration du serveur:<\/p>\n<pre lang=\"bash\">$pbpath\/pleskbackup --server --configuration --prefix=ServerConfig_ --output-file=$btmp\/$nextfile<\/pre>\n<p>Vous remarquerez que la sauvegarde n&#8217;est pas lanc\u00e9e en arri\u00e8re plan. C&#8217;est donc uniquement \u00e0 la fin de l&#8217;op\u00e9ration de sauvegarde que ce script reprendra sa route.<\/p>\n<p>Je cherche ensuite quel est le chemin du fichier log cr\u00e9\u00e9 par pleskbackup afin de suivre la progression de l&#8217;op\u00e9ration. Et j&#8217;indique ce chemin dans mon fichier de log, de fa\u00e7on \u00e0 pouvoir facilmeent mettre ma main sur le log original en cas de besoin. migres contient un r\u00e9sum\u00e9 de l&#8217;op\u00e9ration, et miglog contient le log complet g\u00e9n\u00e9r\u00e9 par pleskbackup<\/p>\n<pre lang=\"bash\">     migres=\/opt\/psa\/PMM\/sessions\/`ls -lrt \/opt\/psa\/PMM\/sessions\/ | awk '\/^d\/ { f=$NF }; END{ print f }'`\/migration.result\r\n      miglog=\/opt\/psa\/PMM\/sessions\/`ls -lrt \/opt\/psa\/PMM\/sessions\/ | awk '\/^d\/ { f=$NF }; END{ print f }'`\/migration.log\r\n      echo \"----------------------------\" >> $blog\r\n      echo \">>> log files in $migres\" >> $blog\r\n      echo \"----------------------------\" >> $blog<\/pre>\n<p>Dans la partie suivante, je surveille le fichier de log en qu\u00eate de l&#8217;indication de la fin de l&#8217;op\u00e9ration, puis, j&#8217;envoie un commentaire dans le log, et j&#8217;envoie le log \u00e0 l&#8217;adresse de l&#8217;administrateur plesk, ainsi que l&#8217;adresse de copie indiqu\u00e9e dans backup.conf (ccmail). En cas d&#8217;erreur, j&#8217;envoie le log complet, alors qu&#8217;en cas de succ\u00e8s, je n&#8217;envoie que le log r\u00e9sum\u00e9.<\/p>\n<pre lang=\"bash\">resultat=`grep -c \"success\" $migres`\r\n\r\nif [ $resultat != 0 ]\r\nthen\r\n  status=\"ended successfully\"\r\n  echo \"$(date +%H%M%S): The backup $status\" >> $blog\r\n\tcat $migres >> $blog\r\n  cat $blog | mail -s \"Server configuration backup $status on $(date +%d.%m.%Y) at $(date +%T)\" $destmail $ccmail\r\nelse\r\n\tstatus=\"failed\"\r\n  echo \"$(date +%H%M%S): The backup $status\" >> $blog\r\n\tcat $miglog >> $blog\r\n\tcat $migres >> $blog\r\n\tcat $blog | mail -s \"Server configuration backup $status on $(date +%d.%m.%Y) at $(date +%T)\" $destmail $ccmail\r\nfi\r\nunset resultat<\/pre>\n<p>Enfin, je clot\u00fbre le log de l&#8217;op\u00e9ration pass\u00e9e, et je l&#8217;ins\u00e8re dans le log de la journ\u00e9e:<\/p>\n<pre lang=\"bash\">echo -e \"=====\" ServerConfig ended at $(date +%T) \"=====\"\\\\n\\\\n >> $blog\r\n# append log file to main log file\r\ncat $blog >> $maintodaylog<\/pre>\n<p>=== Sauvegarde de la configuration des revendeurs ===<br \/>\nJe r\u00e9cup\u00e8re dans la base de donn\u00e9e la liste des revendeurs:<\/p>\n<pre lang=\"bash\">res_array=( `mysql -e\"use psa;select login from clients where type='reseller' order by login desc\" -u$mysqluser -p\"$mysqlpwd\" | tail -n +2` )<\/pre>\n<p>Pour chaque revendeur, je vais faire les op\u00e9rations d\u00e9crites ci-dessous<\/p>\n<pre lang=\"bash\">for res in ${res_array[@]};\r\ndo<\/pre>\n<p>Je d\u00e9finis les variables propres \u00e0 l&#8217;op\u00e9ration comme plus haut:<\/p>\n<pre lang=\"bash\">\tcurrent=\"$res\"_Config_$(date +%Y%m%d_%H%M%S)\r\n\tblog=\"$blogs\/$current.log\"\r\n\tnextfile=\"$btmp\/$current.tar\"<\/pre>\n<p>Je d\u00e9finis un nom de fichier pour le log de l&#8217;op\u00e9ration, et j&#8217;y ins\u00e8re une ent\u00eate<\/p>\n<pre lang=\"bash\">\ttodaylog=$blogs\/\"$res\"_backup_$(date +%Y%m%d_%H%M%S).log\r\n\techo -e \"****************\" \"$res\" Backup Job Started $(date +%A) $(date +%_d) $(date +%B) $(date +%Y) at $(date +%T) \"***************\"\\\\n > $todaylog<\/pre>\n<p>Je r\u00e9cup\u00e8re l&#8217;adresse email du revendeur dans la base de donn\u00e9e<\/p>\n<pre lang=\"bash\">\tdestmail=`mysql -e\"use psa;select email from clients where login='$res'\" -u$mysqluser -p\"$mysqlpwd\" | tail -n +2`<\/pre>\n<p>J&#8217;indique l&#8217;heure de d\u00e9marrage de l&#8217;op\u00e9ration dans le log et j&#8217;ex\u00e9cute pleskbackup<\/p>\n<pre lang=\"bash\">\techo -e \"===== $res Config backup started at $(date +%T) =====\"\\\\n\\\\n > $blog\r\n\t$pbpath\/pleskbackup --resellers-name $res --configuration -v --prefix=Config\"$res\"_ --output-file=$nextfile<\/pre>\n<p>Comme plus haut, je r\u00e9cup\u00e8re les chemins des logs de pleskbackup<\/p>\n<pre lang=\"bash\">\tmigres=\/opt\/psa\/PMM\/sessions\/`ls -lrt \/opt\/psa\/PMM\/sessions\/ | awk '\/^d\/ { f=$NF }; END{ print f }'`\/migration.result\r\n\tmiglog=\/opt\/psa\/PMM\/sessions\/`ls -lrt \/opt\/psa\/PMM\/sessions\/ | awk '\/^d\/ { f=$NF }; END{ print f }'`\/migration.log\r\n\techo \"----------------------------\" >> $blog\r\n\techo \">>> log files in $migres\" >> $blog\r\n\techo \"----------------------------\" >> $blog<\/pre>\n<p>Ensuite, je cherche le r\u00e9sultat (\u00e9chec ou r\u00e9ussite) et j&#8217;envoie le log dans le log principal, et par email \u00e0 l&#8217;adresse du revendeur, et en copie si demand\u00e9 dans backup.conf<\/p>\n<pre lang=\"bash\">\tresultat=`grep -c \"success\" $migres`\r\n\tif [ $resultat != 0 ]\r\n\tthen\r\n\t\tstatus=\"$res config backup ended successfully\"\r\n\t\techo \"$status\" >> $blog\r\n\t\techo \"Migration result: \" >> $blog\r\n\t\tcat $migres >> $blog\r\n\t\tcat $blog | mail -s \"$status on $(date +%d.%m.%Y) at $(date +%T)\" $destmail $ccmail\r\n\telse\r\n\t\tstatus=\"$res config backup failed\"\r\n\t\techo \"$status\" >> $blog\r\n\t\techo \"Migration log: \" >> $blog\r\n\t\tcat $miglog >> $blog\r\n\t\techo \"Migration result: \" >> $blog\r\n\t\tcat $migres >> $blog\r\n\t\tcat $blog | mail -s \"$status on $(date +%d.%m.%Y) at $(date +%T)\" $destmail $ccmail\r\n\tfi\r\n\tunset resultat<\/pre>\n<p>Je clos ensuite le log de cette op\u00e9ration, et nous passons \u00e0 l&#8217;op\u00e9ration des domaines, qui est imbriqu\u00e9e dans celle des revendeurs:<\/p>\n<pre lang=\"bash\">\techo -e \"===== $res Config ended at $(date +%T) =====\"\\\\n\\\\n >> $blog\r\n\techo -ne \"$status: $res reseller configuration backup on $(date +%d.%m.%Y) at $(date +%T)\"\\\\n >> $todaylog<\/pre>\n<p>Je r\u00e9cup\u00e8re la liste des domaines que poss\u00e8de le revendeur en cours. Cette liste sera tri\u00e9e par taille de domaine. Donc les domaines les plus gros seront sauvegard\u00e9s en premier.<\/p>\n<pre lang=\"bash\">\tunset dom_array\r\n\tdom_array=(`mysql -e\"use psa; select dom from (SELECT clients.login AS parent, clients_1.login as owner, clients.type AS type, domains.name as dom, domains.real_size as domsize FROM domains LEFT JOIN (clients AS clients_1 LEFT JOIN clients ON clients_1.parent_id = clients.id) ON domains.cl_id = clients_1.id) as list where if(parent='admin',owner,parent)='$res' order by domsize desc;\" -u$mysqluser -p\"$mysqlpwd\" | tail -n +2`)<\/pre>\n<p>Je d\u00e9finis un compteur que j&#8217;utilise pour rep\u00e9rer facilement dans les logs le nombre d&#8217;erreur et de r\u00e9ussite \u00e0 la fin de l&#8217;op\u00e9ration.<\/p>\n<pre lang=\"bash\">\tcount=0\r\n\tcount1=0<\/pre>\n<p>Je cr\u00e9e une boucle qui va faire une sauvegarde de chaque domaine. La logique est toujours la m\u00eame. Je ne vous refais pas la d\u00e9coupe.<\/p>\n<pre lang=\"bash\">\tfor dom in ${dom_array[@]};\r\n\tdo<\/pre>\n<p>C&#8217;est ici que l&#8217;exclusion rentre en compte. Si un domaine est list\u00e9 dans la variable $excl, on passe directement au suivant.<\/p>\n<pre lang=\"bash\">            if [[ ${excl[*]} =~ $dom ]]\r\n                then\r\n                        continue\r\n        fi<\/pre>\n<pre lang=\"bash\">\t\tcurrent=\"$dom\"_$(date +%Y%m%d_%H%M%S)\r\n\t\tblog=\"$blogs\/$current.log\"\r\n\t\tcount=$(($count+1))\r\n\t\techo -e \"=====\" $dom started at $(date +%T) \"=====\"\\\\n > $blog\r\n\t\tnextfile=$btmp\/\"$dom\"_$(date +%Y%m%d_%H%M%S).tar\r\n\t\t$pbpath\/pleskbackup --domains-name $dom --output-file=$nextfile\r\n\r\n\t\tmigres=\/opt\/psa\/PMM\/sessions\/`ls -lrt \/opt\/psa\/PMM\/sessions\/ | awk '\/^d\/ { f=$NF }; END{ print f }'`\/migration.result\r\n\t\tmiglog=\/opt\/psa\/PMM\/sessions\/`ls -lrt \/opt\/psa\/PMM\/sessions\/ | awk '\/^d\/ { f=$NF }; END{ print f }'`\/migration.log\r\n\t\techo \"----------------------------\" >> $blog\r\n\t\techo \">>> log files in $migres\" >> $blog\r\n\t\techo \"----------------------------\" >> $blog\r\n\r\n\t\tresultat=`grep -c \"success\" $migres`\r\n\t\tif [ $resultat != 0 ]\r\n\t\tthen\r\n\t\t\tstatus=\"Successful\"\r\n\t\t\tcount1=$(($count1+1))\r\n\t\t\tcat $migres >> $blog\r\n\t\telse\r\n\t\t\tstatus=\"Failed\"\r\n\t\t\tcat $miglog >> $blog\r\n\t\t\tcat $migres >> $blog\r\n\t\t\tcat $blog | mail -s \"$status: $dom backup on $(date +%d.%m.%Y) at $(date +%T)\" $destmail $ccmail\r\n\t\tfi\r\n\t\tunset resultat\r\n\t\techo -e \"=====\" $dom ended at $(date +%T) \"=====\"\\\\n\\\\n >> $blog\r\n\t\techo -ne \"$status: $dom backup on $(date +%d.%m.%Y) at $(date +%T)\"\\\\n >> $todaylog\r\n\tdone<\/pre>\n<p>Une fois tous les domaines sauvegard\u00e9s, je mets \u00e0 jour les logs , et j&#8217;envoie le log final au revendeur.<\/p>\n<pre lang=\"bash\">\techo -e \\\\n\"$count1\/$count successful\" >> $todaylog\r\n\techo -e \\\\n\"***********\" \"$res\" Backup Job Ended $(date +%A) $(date +%_d) $(date +%B) $(date +%Y) at $(date +%T) \"**********\"\\\\n\\\\n >> $todaylog\r\n\tcat $todaylog | mail -s \"$res reseller full backup report $(date +%d.%m.%Y)\" $destmail $ccmail\r\n\tcat $todaylog >> $maintodaylog<\/pre>\n<p>Voil\u00e0 qui cl\u00f4ture, je vous le rappelle, l&#8217;op\u00e9ration globale de sauvegarde du revendeur.<\/p>\n<pre lang=\"bash\">done<\/pre>\n<p>=== Envoi des donn\u00e9es sur le serveur FTP ===<br \/>\nL&#8217;envoi des fichiers est configur\u00e9 pour envoyer tous les fichiers cr\u00e9\u00e9s \u00e0 la date du jour. Vous pouvez adapter cel\u00e0 \u00e0 votre convenance. Pour moi, \u00e7a fait mon affaire.<\/p>\n<p>Nous allons ensuite nous servir de ncftp pour envoyer les fichiers sur le serveur ftp. On ajoute une ent\u00eate dans le fichier log, et on remet \u00e0 z\u00e9ro les compteurs, puis on d\u00e9fini<\/p>\n<pre lang=\"bash\">echo -e \\\\n\"*********** FTP Transfer started $(date +%A) $(date +%_d) $(date +%B) $(date +%Y) at $(date +%T) ***********\"\\\\n >> $maintodaylog\r\ncountf=0\r\ncountf1=0<\/pre>\n<p>On se rend ensuite dans le dossier des sauvegardes locales, et on d\u00e9termine la liste des fichiers \u00e0 envoyer:<\/p>\n<pre lang=\"bash\">cd $btmp\r\nftp_array=( `ls *$(date +%Y%m%d)*` )<\/pre>\n<p>Enfin, pour chaque fichier s\u00e9lectionn\u00e9, on proc\u00e8de aux op\u00e9rations suivantes:<\/p>\n<pre lang=\"bash\">for ftpfile in ${ftp_array[@]};\r\ndo<\/pre>\n<p>On incr\u00e9mente le conteur et on lance le transfert<\/p>\n<pre lang=\"bash\">\tcountf=$(($countf+1))    \r\n\tncftpput -u $fuser -p $fpass $fserv $fpath $ftpfile<\/pre>\n<p>On r\u00e9cup\u00e8re ensuite la variable de r\u00e9sultat de ncftpput afin de savoir si le transfert s&#8217;est bien pass\u00e9. Personnellement, j&#8217;ai utilis\u00e9 l&#8217;anglais. Vous \u00eates tous grands, vous pouvez les traduire si \u00e7a vous chante<\/p>\n<pre lang=\"bash\">\tcountf=$(($countf+1))    \r\n\tncftpput -u $fuser -p $fpass $fserv $fpath $ftpfile\r\n    \tcase $? in\r\n\t0 )\r\n\t\tcountf1=$(($countf1+1))\r\n\t\tstatus=\"Success: \" ;;  \r\n\t1 )\r\n\t\tstatus=\"Could not connect to remote host: \" ;;\r\n\t2 )\r\n\t\tstatus=\"Could not connect to remote host - timed out: \" ;;\r\n\t3 )\r\n\t\tstatus=\"Transfer failed: \" ;;\r\n\t4 )\r\n\t\tstatus=\"Transfer failed - timed out: \" ;;\r\n\t5 )\r\n\t\tstatus=\"Directory change failed: \" ;;\r\n\t6 )\r\n\t\tstatus=\"Directory change failed - timed out: \" ;;\r\n\t7 )\r\n\t\tstatus=\"Malformed URL: \" ;;\r\n\t8 )\r\n\t\tstatus=\"Usage error: \" ;;\r\n\t9 )\r\n\t\tstatus=\"Error in login configuration file: \" ;;\r\n\t10 )\r\n\t\tstatus=\"Library initialization failed: \" ;;\r\n\t11 )\r\n\t\tstatus=\"Session initialization failed: \" ;;\r\n\tesac<\/pre>\n<p>Je r\u00e9cup\u00e8re ensuite le nom du domaine depuis le nom de fichier, et j&#8217;ins\u00e8re un commentaire dans le log<\/p>\n<pre lang=\"bash\">\tftpdom=`echo $ftpfile | cut -d_ -f1`\r\n\techo -e \"$status $ftpdom\" >> $maintodaylog<\/pre>\n<p>Voil\u00e0 qui clot l&#8217;envoi des fichiers sur le serveur FTP. Reste plus \u00e0 cloturer le log. Ensuite j&#8217;envoie le log en question \u00e0 l&#8217;admin plesk pour information.<\/p>\n<pre lang=\"bash\">done\r\n\r\necho -e \\\\n\">>>>> $countf1\/$countf files succesfully transfered. <<<<<\" >> $maintodaylog  \r\necho -e \\\\n\"*********** FTP Transfer ended $(date +%A) $(date +%_d) $(date +%B) $(date +%Y) at $(date +%T) ***********\"\\\\n\\\\n >> $maintodaylog\r\n\r\necho -e \"***********\" Backup Job Ended $(date +%A) $(date +%_d) $(date +%B) $(date +%Y) at $(date +%T) \"*********\"\\\\n\\\\n >> $maintodaylog\r\ndestmail=`mysql -e\"use psa;select email from clients where login='admin'\" -u$mysqluser -p\"$mysqlpwd\" | tail -n +2`\r\ncat $maintodaylog | mail -s \"$res FTP Transfer report $(date +%d.%m.%Y)\" $destmail $ccmail<\/pre>\n<p>Je supprime enfin les fichiers temporaires<\/p>\n<pre lang=\"bash\">rm $blog\r\nrm -rf \/var\/lib\/psa\/dumps\/resellers\/*<\/pre>\n<p>=== Suppression des fichiers sur le serveur FTP ===<br \/>\nAfin de ne pas remplir inutilement le serveur FTP, nous avons d\u00e9fini une dur\u00e9e de r\u00e9tention dans backup.conf. Nous allons maintenant nous en servir pour effacer les anciens fichiers. Pour \u00e7a, on utilise de nouveau ncftp<\/p>\n<pre lang=\"bash\">ftpdeldate=`date --date=\"$remotedaystodel days ago\" +%Y%m%d`\r\nncftp -u $fuser -p $fpass $fserv <<END_OF_CMD\r\ncd $fpath\r\nrm -f *$ftpdeldate*\r\nquit\r\nEND_OF_CMD<\/pre>\n<p>== Scripts ==<\/p>\n<pre lang=\"bash\">localdaystodel=7 # R\u00e9tention locale de 7 jours\r\nremotedaystodel=30 # r\u00e9tention distante de 30 jours\r\nblogs=\"\/var\/lib\/psa\/dumps\/logs\"\r\nmaintodaylog=\"$blogs\/backup_$(date +%Y%m%d_%H%M%S).log\" #Cr\u00e9ation d'un fichier de log dans le dossier pr\u00e9d\u00e9fini\r\nfuser=\"monuser\"\r\nfpass=\"monpassword\"\r\nfserv=\"ftp.monserveur.com\"\r\nfpath=\"\/mes_sauvegardes\"\r\nbtmp=\"\/var\/log\/mes_backups\"\r\nccmail=\"-c mon@adresse.email\"\r\npbpath=\"\/opt\/psa\/bin\"\r\nPMMpath=\"\/opt\/psa\/PMM\"\r\nmysqluser=\"sqluser\"\r\nmysqlpwd=\"sqlpassword\"\r\nexcl=\"domain1.tld domain2.tld\"<\/pre>\n<pre lang=\"bash\">#!\/bin\/sh\r\nif ps ax | grep -v grep | grep \/root\/backup > \/dev\/null;\r\nthen\r\n\techo \"Backup already running\"\r\nelse\r\n\t\/root\/backup &\r\nfi<\/pre>\n<pre lang=\"bash\">#!\/bin\/sh\r\n\r\n. \/root\/backup.conf\r\n\r\n# delete local files from 5 days ago\r\n\r\nrm $btmp\/*`date --date=\"$localdaystodel days ago\" +%Y%m%d`*\r\n\r\n# Delete old pmm sessions log files\r\n\r\nfind \/opt\/psa\/PMM\/sessions -mtime +30 -type d | grep -v archives | xargs rm -Rf \r\n\r\n# create main day log\r\n\r\necho -e \"****************\" Backup Job Started $(date +%A) $(date +%_d) $(date +%B) $(date +%Y) at $(date +%T) \"***************\"\\\\n\\\\n > $maintodaylog\r\n\r\n# Backup Whole server config\r\n\r\n# determine plesk administrator email address\r\n\r\ndestmail=`mysql -e\"use psa;select email from clients where login='admin'\" -u$mysqluser -p\"$mysqlpwd\" | tail -n +2`\r\n\r\n# Define current backup job, log name, and file name\r\n\r\ncurrent=\"ServerConfig_ServerConfig_$(date +%Y%m%d_%H%M%S)\"\r\nblog=\"$blogs\/$current.log\"\r\nnextfile=\"$current.tar\"\r\n# Start log file\r\necho \"===== Server configuration backup started at $(date +%T) =====\" > $blog\r\n\r\n# Proceed to backup\r\n$pbpath\/pleskbackup --server --configuration --prefix=ServerConfig_ --output-file=$btmp\/$nextfile\r\n  # Define log files\r\n      migres=\/opt\/psa\/PMM\/sessions\/`ls -lrt \/opt\/psa\/PMM\/sessions\/ | awk '\/^d\/ { f=$NF }; END{ print f }'`\/migration.result\r\n      miglog=\/opt\/psa\/PMM\/sessions\/`ls -lrt \/opt\/psa\/PMM\/sessions\/ | awk '\/^d\/ { f=$NF }; END{ print f }'`\/migration.log\r\n      echo \"----------------------------\" >> $blog\r\n      echo \">>> log files in $migres\" >> $blog\r\n      echo \"----------------------------\" >> $blog\r\n\r\n# Check status of job\r\nresultat=`grep -c \"success\" $migres`\r\n# Define action for successful backup\r\nif [ $resultat != 0 ]\r\nthen\r\n  status=\"ended successfully\"\r\n  echo \"$(date +%H%M%S): The backup $status\" >> $blog\r\n\tcat $migres >> $blog\r\n  cat $blog | mail -s \"Server configuration backup $status on $(date +%d.%m.%Y) at $(date +%T)\" $destmail $ccmail\r\nelse\r\n\tstatus=\"failed\"\r\n  echo \"$(date +%H%M%S): The backup $status\" >> $blog\r\n\tcat $miglog >> $blog\r\n\tcat $migres >> $blog\r\n\tcat $blog | mail -s \"Server configuration backup $status on $(date +%d.%m.%Y) at $(date +%T)\" $destmail $ccmail\r\nfi\r\nunset resultat\r\n# End log file\r\necho -e \"=====\" ServerConfig ended at $(date +%T) \"=====\"\\\\n\\\\n >> $blog\r\n# append log file to main log file\r\ncat $blog >> $maintodaylog\r\n\r\n# Define list of resellers\r\n\r\nres_array=( `mysql -e\"use psa;select login from clients where type='reseller' order by login desc\" -u$mysqluser -p\"$mysqlpwd\" | tail -n +2` )\r\n\r\n# for each reseller, backup config, and all domains\r\n\r\nfor res in ${res_array[@]};\r\n\r\n  do\r\n\r\n  # Backup reseller config\r\n    current=\"$res\"_Config_$(date +%Y%m%d_%H%M%S)\r\n    blog=\"$blogs\/$current.log\"\r\n    nextfile=\"$btmp\/$current.tar\"\r\n\r\n  # define reseller log file\r\n    todaylog=$blogs\/\"$res\"_backup_$(date +%Y%m%d_%H%M%S).log\r\n  # create reseller log file\r\n    echo -e \"****************\" \"$res\" Backup Job Started $(date +%A) $(date +%_d) $(date +%B) $(date +%Y) at $(date +%T) \"***************\"\\\\n > $todaylog\r\n\r\n  # Define destination email address based on reseller\r\n\r\n    destmail=`mysql -e\"use psa;select email from clients where login='$res'\" -u$mysqluser -p\"$mysqlpwd\" | tail -n +2`\r\n\r\n  # create log file\r\n\t\techo -e \"===== $res Config backup started at $(date +%T) =====\"\\\\n\\\\n > $blog\r\n  # proceed to backup\r\n\t\t$pbpath\/pleskbackup --resellers-name $res --configuration -v --prefix=Config\"$res\"_ --output-file=$nextfile\r\n\r\n  # Define log files\r\n      migres=\/opt\/psa\/PMM\/sessions\/`ls -lrt \/opt\/psa\/PMM\/sessions\/ | awk '\/^d\/ { f=$NF }; END{ print f }'`\/migration.result\r\n      miglog=\/opt\/psa\/PMM\/sessions\/`ls -lrt \/opt\/psa\/PMM\/sessions\/ | awk '\/^d\/ { f=$NF }; END{ print f }'`\/migration.log\r\n      echo \"----------------------------\" >> $blog\r\n      echo \">>> log files in $migres\" >> $blog\r\n      echo \"----------------------------\" >> $blog\r\n\r\n  # Determine status\r\n\t\tresultat=`grep -c \"success\" $migres`\r\n    if [ $resultat != 0 ]\r\n    then\r\n\t\t\tstatus=\"$res config backup ended successfully\"\r\n      echo \"$status\" >> $blog\r\n      echo \"Migration result: \" >> $blog\r\n     \tcat $migres >> $blog\r\n      cat $blog | mail -s \"$status on $(date +%d.%m.%Y) at $(date +%T)\" $destmail $ccmail\r\n    else\r\n\t\t\tstatus=\"$res config backup failed\"\r\n      echo \"$status\" >> $blog\r\n      echo \"Migration log: \" >> $blog\r\n\t    cat $miglog >> $blog\r\n      echo \"Migration result: \" >> $blog\r\n\t    cat $migres >> $blog\r\n\t    cat $blog | mail -s \"$status on $(date +%d.%m.%Y) at $(date +%T)\" $destmail $ccmail\r\n    fi\r\n    unset resultat\r\n\r\n\t\techo -e \"===== $res Config ended at $(date +%T) =====\"\\\\n\\\\n >> $blog\r\n\r\n\t\techo -ne \"$status: $res reseller configuration backup on $(date +%d.%m.%Y) at $(date +%T)\"\\\\n >> $todaylog\r\n\r\n  # Define domain list\r\n\r\n    unset dom_array\r\n    dom_array=(`mysql -e\"use psa; select dom from (SELECT clients.login AS parent, clients_1.login as owner, clients.type AS type, domains.name as dom, domains.real_size as domsize FROM domains LEFT JOIN (clients AS clients_1 LEFT JOIN clients ON clients_1.parent_id = clients.id) ON domains.cl_id = clients_1.id) as list where if(parent='admin',owner,parent)='$res' order by domsize desc;\" -u$mysqluser -p\"$mysqlpwd\" | tail -n +2`)\r\n\r\n  # create counters\r\n    count=0\r\n    count1=0\r\n\r\n    for dom in ${dom_array[@]};\r\n\r\n    do\r\n            if [[ ${excl[*]} =~ $dom ]]\r\n                then\r\n                        continue\r\n        fi\r\n\r\n  # Backup reseller config\r\n      current=\"$dom\"_$(date +%Y%m%d_%H%M%S)\r\n      blog=\"$blogs\/$current.log\"\r\n#     nextfile=\"$btmp\/$current.tar\"\r\n      count=$(($count+1))\r\n      echo -e \"=====\" $dom started at $(date +%T) \"=====\"\\\\n > $blog\r\n      nextfile=$btmp\/\"$dom\"_$(date +%Y%m%d_%H%M%S).tar\r\n      unset pids\r\n  # proceed to backup in background\r\n      $pbpath\/pleskbackup --domains-name $dom --output-file=$nextfile\r\n\r\n      migres=\/opt\/psa\/PMM\/sessions\/`ls -lrt \/opt\/psa\/PMM\/sessions\/ | awk '\/^d\/ { f=$NF }; END{ print f }'`\/migration.result\r\n      miglog=\/opt\/psa\/PMM\/sessions\/`ls -lrt \/opt\/psa\/PMM\/sessions\/ | awk '\/^d\/ { f=$NF }; END{ print f }'`\/migration.log\r\n      echo \"----------------------------\" >> $blog\r\n      echo \">>> log files in $migres\" >> $blog\r\n      echo \"----------------------------\" >> $blog\r\n\r\n      resultat=`grep -c \"success\" $migres`\r\n      if [ $resultat != 0 ]\r\n      then\r\n        status=\"Successful\"\r\n        count1=$(($count1+1))\r\n        cat $migres >> $blog\r\n      else\r\n        status=\"Failed\"\r\n        cat $miglog >> $blog\r\n        cat $migres >> $blog\r\n        cat $blog | mail -s \"$status: $dom backup on $(date +%d.%m.%Y) at $(date +%T)\" $destmail $ccmail\r\n      fi\r\n      unset resultat\r\n      echo -e \"=====\" $dom ended at $(date +%T) \"=====\"\\\\n\\\\n >> $blog\r\n      echo -ne \"$status: $dom backup on $(date +%d.%m.%Y) at $(date +%T)\"\\\\n >> $todaylog\r\n    done    \r\n\r\n  echo -e \\\\n\"$count1\/$count successful\" >> $todaylog\r\n  echo -e \\\\n\"***********\" \"$res\" Backup Job Ended $(date +%A) $(date +%_d) $(date +%B) $(date +%Y) at $(date +%T) \"**********\"\\\\n\\\\n >> $todaylog\r\n  cat $todaylog | mail -s \"$res reseller full backup report $(date +%d.%m.%Y)\" $destmail $ccmail\r\n  cat $todaylog >> $maintodaylog\r\n  done\r\n\r\n  echo -e \\\\n\"*********** FTP Transfer started $(date +%A) $(date +%_d) $(date +%B) $(date +%Y) at $(date +%T) ***********\"\\\\n >> $maintodaylog\r\n\r\n  cd $btmp\r\n  countf=0\r\n  countf1=0\r\n  ftp_array=( `ls *$(date +%Y%m%d)*` )\r\n  for ftpfile in ${ftp_array[@]};\r\n  do\r\n    countf=$(($countf+1))\r\n    ncftpput -u $fuser -p $fpass $fserv $fpath $ftpfile\r\n    case $? in\r\n    0 )\r\n        countf1=$(($countf1+1))\r\n        status=\"Success: \" ;;\r\n    1 )\r\n        status=\"Could not connect to remote host: \" ;;\r\n    2 )\r\n        status=\"Could not connect to remote host - timed out: \" ;;\r\n    3 )\r\n        status=\"Transfer failed: \" ;;\r\n    4 )\r\n        status=\"Transfer failed - timed out: \" ;;\r\n    5 )\r\n        status=\"Directory change failed: \" ;;\r\n    6 )\r\n        status=\"Directory change failed - timed out: \" ;;\r\n    7 )\r\n        status=\"Malformed URL: \" ;;\r\n    8 )\r\n        status=\"Usage error: \" ;;\r\n    9 )\r\n        status=\"Error in login configuration file: \" ;;\r\n    10 )\r\n        status=\"Library initialization failed: \" ;;\r\n    11 )\r\n        status=\"Session initialization failed: \" ;;\r\n    esac\r\n    ftpdom=`echo $ftpfile | cut -d_ -f1`\r\n    echo -e \"$status $ftpdom\" >> $maintodaylog\r\n  done\r\n  echo -e \\\\n\">>>>> $countf1\/$countf files succesfully transfered. <<<<<\" >> $maintodaylog\r\n  echo -e \\\\n\"*********** FTP Transfer ended $(date +%A) $(date +%_d) $(date +%B) $(date +%Y) at $(date +%T) ***********\"\\\\n\\\\n >> $maintodaylog\r\n\r\n  echo -e \"***********\" Backup Job Ended $(date +%A) $(date +%_d) $(date +%B) $(date +%Y) at $(date +%T) \"*********\"\\\\n\\\\n >> $maintodaylog\r\n  destmail=`mysql -e\"use psa;select email from clients where login='admin'\" -u$mysqluser -p\"$mysqlpwd\" | tail -n +2`\r\n  cat $maintodaylog | mail -s \"$res FTP Transfer report $(date +%d.%m.%Y)\" $destmail $ccmail\r\n  rm $blog\r\n\trm -rf \/var\/lib\/psa\/dumps\/resellers\/*  \r\n\r\n  # delete files on the FTP older than xx days ago\r\n\r\nftpdeldate=`date --date=\"$remotedaystodel days ago\" +%Y%m%d`\r\nncftp -u $fuser -p $fpass $fserv <<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>== Mise \u00e0 jour == Cet article a \u00e9t\u00e9 mis \u00e0 jour le 12 octobre 2012, avec l&#8217;ajout d&#8217;une fonction d&#8217;exclusion permettant d&#8217;exclure certains domaines. J&#8217;ai \u00e9galement repris les utilisateurs SQL dans backup.conf plut\u00f4t que dans le script directement. J&#8217;utilise ce script au quotidien avec Plesk 9 et Plesk 10. Je ne l&#8217;ai pas test\u00e9 [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[220],"tags":[205,100,156],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/akim.sissaoui.com\/en\/wp-json\/wp\/v2\/posts\/511"}],"collection":[{"href":"https:\/\/akim.sissaoui.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/akim.sissaoui.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/akim.sissaoui.com\/en\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/akim.sissaoui.com\/en\/wp-json\/wp\/v2\/comments?post=511"}],"version-history":[{"count":23,"href":"https:\/\/akim.sissaoui.com\/en\/wp-json\/wp\/v2\/posts\/511\/revisions"}],"predecessor-version":[{"id":1065,"href":"https:\/\/akim.sissaoui.com\/en\/wp-json\/wp\/v2\/posts\/511\/revisions\/1065"}],"wp:attachment":[{"href":"https:\/\/akim.sissaoui.com\/en\/wp-json\/wp\/v2\/media?parent=511"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/akim.sissaoui.com\/en\/wp-json\/wp\/v2\/categories?post=511"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/akim.sissaoui.com\/en\/wp-json\/wp\/v2\/tags?post=511"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}