Nom de l’auteur/autrice :yvonh

javascript

Améliorer son code par des cas réels

Lorsque l’on code et que l’on est débutant ou intermédiaire, il y a des bonnes chances de faire du code touffu ou en spaghetti, illisible, et souvent buggé. Nous allons voir avec des exemples concrets comment à partir d’un code issu du monde réel, on peut améliorer la lisibilité du code, la concision, et l’efficacité tout en évitant des bugs.

Lecture d’un tableau d’objet en Javascript

L’exemple ci-dessous est tiré d’une application Handlebars, le snippet lit un tableau d’objet en deux dimensions.

if(enfantsObject.EnfantsComm != null || enfantsObject.EnfantsP1 != null || enfantsObject.EnfantsP2 != null){
            if(Object.keys(enfantsObject).length){
                $.each(enfantsObject, function(index,value){
                    if(value != null && value != "{}" && jQuery.isNumeric( value )){
                        $.each(value, function(index2, value2){
                            if(value2.pension !== undefined){
                                montPens += Number(value2.pension);
                            }
                        })
                    }
                })
            }
        }

Le model à lire était un tableau d’objets avec les propriétés suivantes, un seul niveau d’imbriquement. Il y a plusieurs choses qui me surprennent, le fait d’utiliser la fonction de Jquery each, qui sert à itérer dans les éléments du DOM (les tags HTML), elle est ici utilisée alors qu’elle ne devrait pas l’être, inapproprié.

Le problème c’est que les propriétés sont changeante, elles peuvent ne pas être présentessuivant la façon dont l’objet a été initialisé. Voir l’exemple ci-dessous :

Dans l’exemple ci-dessus, les propriétés pension et pensionDate ne sont pas présentes ! Mauvaise pratique qui va nous compliquer le code, soit on retravaille l’initialisation, soit on checke les objets quand ils sont utilisés.

Ensuite il y a le Object.keys, elle est utilisée ici pour détecter que l’objet possède des clés (enfantCommuns, enfantP1, etc). Ceci n’est pas du tout stable, c’est en amont que les choses devraient être faites, notamment en initialisant proprement les différents propriétés de l’objet enfantsObject, y mettre un objet vide nous assure de la présence de la propriété et ne pas à avoir faire ce check inutile.

Première étape on simplifie le code

Si vous voulez améliorer votre code, mais que vous ne savez pas par où commencer, choisissez la lisibilité, qui doit être l’ultime but recherché, pas de code intelligent qui marche mais difficile à lire pour les autres développeur. Quitte à faire une simple boucle for au lieu de faire un map comme en programmation déclarative.

Ci-dessous, j’ai scindé en trois parties (attention il ya duplication de code similaire), ce qui n’est pas bon, mais cette étape intermédiaire nous permettra de refactorer en une fonction réutilisable.

J’ai du faire varier les différents cas sur l’interface pour voir les cas limites, et vous verrez un check pour s’assurer que c’est un tableau, en effet, quand il n’y a pas d’enfant présent, on n’a pas un tableau vide mais un objet ! (pourquoi ne pas revoir l’initialisation vous me direz? pour des impératifs de budget tout simplement)

Preuve que répéter du code n’est pas bon, parfois j’oublie de renommer à certains endroits et le programme plante.

        var pensionEnfantscommun = 0;
        var pensionEnfantPers1 = 0;
        var pensionEnfantPers2 = 0;

        if(enfantsObject.EnfantsComm != null && Array.isArray(enfantsObject.EnfantsComm)){
            for(i=0;i<enfantsObject.EnfantsComm.length;i++){
                if(enfantsObject.EnfantsComm[i].pension != undefined && enfantsObject.EnfantsComm[i].pension != ""){
                    pensionEnfantscommun += parseInt(enfantsObject.EnfantsComm[i].pension);
                }
            }    
        }

        if(enfantsObject.EnfantsP1 != null && Array.isArray(enfantsObject.EnfantsP1)){
            for(i=0;i<enfantsObject.EnfantsP1.length;i++){
                if(enfantsObject.EnfantsP1[i].pension != undefined && enfantsObject.EnfantsP1[i].pension != ""){
                    pensionEnfantPers1 += parseInt(enfantsObject.EnfantsP1[i].pension);
                }
            }    
        }

        if(enfantsObject.EnfantsP2 != null && Array.isArray(enfantsObject.EnfantsP2)){
            for(i=0;i<enfantsObject.EnfantsP2.length;i++){
                if(enfantsObject.EnfantsP2[i].pension != undefined && enfantsObject.EnfantsP2[i].pension != ""){
                    pensionEnfantPers2 += parseInt(enfantsObject.EnfantsP2[i].pension);
                }
            }    
        }

On vérifie que tout fonctionne (en tant que développeur il faut toujours bien tester ce que l’on fait). Maintenant nous pouvons faire une fonction réutilisable.

Seconde étape on refactore avec des fonctions

        // sous fonction 
        const majorationPension = function(enfant){
            if(enfant.pensionDate != undefined && enfant.pensionDate != ""){
                return Math.min(parseInt(enfant.pension) * 1.25,PARAM.SEUIL_JUGEMENT) 
            } else {
                return parseInt(enfant.pension)
            }
        }

        // fonction locale de calcul de fonction
        const sumPension = function(arrayEnfants){
                            const pensionEnfants = 0
                                if(arrayEnfants != null && Array.isArray(arrayEnfants)){
                                            for(i=0;i< arrayEnfants.length;i++){
                                                if(arrayEnfants[i].pension != undefined && arrayEnfants[i].pension != ""){
                                                    pensionEnfants += majorationPension(arrayEnfants[i]);
                                                }
                                            }    
                                        }
                                        return pensionEnfants
                                    }
        var montPens = 0;
        var pensionEnfantscommun = 0;
        var pensionEnfantPers1 = 0;
        var pensionEnfantPers2 = 0;

        pensionEnfantscommun = sumPension(enfantsObject.EnfantsComm)
        pensionEnfantPers1 = sumPension(enfantsObject.EnfantsP1)
        pensionEnfantPers2 = sumPension(enfantsObject.EnfantsP2)

J’ai ajouté une sous fonction majorationPension parce qu’il était nécessaire de faire un filtrage, et on n’oublie pas le parseInt, qui permet de convertir en véritable entier, sinon on aurait des erreurs de type NaN (not a number)

Notez l’utilisation de const pour des variable locales, une bonne pratique à prendre.

Conclusion

Maintenant on a sauvé quelques lignes, et surtout obtenu un code plus lisible pour la maintenance ou les évolutions plus tard.

php

Surcharger ou annuler une fonction native dans PHP

Comment surcharger une fonction native en PHP

Voilà une fonction intéressante en PHP, elle vus permet de redéfinir ou d’annuler carrément une fonction.

override_function

Annuler une fonction

override('fonction_origine','','');

Surcharger une fonction :

override_function('fonction_origine','$a,$b','nouvelle_fonction');

ou

override_function('fonction_origine','$a,$b','echo "un test";echo $a + $b;');

Ceci dit, je ne vous recommande pas de le faire, c’est juste une curiosité, car quitte à redéfinir une fonction autant en coder une, et encore, si une fonction ne vous satisfait pas comme utf8_encode() ou utf8_decode(), il existe une alternative qui fonctionne bien, dans notre cas c’est iconv().

Configurer PHPStorm pour le rechargement automatique du navigateur

Comment faire recharger la page automatiquement à chaque modification avec PHPStorm

 

Il existe un plugin pratique pour les développeur front end avec HPStorm, LiveEdit (édité par Jetbrain), pour ce faire il faut installer le plugin Chrome IDE Support.

Ensuite dans l’IDE PHPSTORM, il faut installer le plugin LiveEdit, Une fois ceci fait, faites un click droit sur le fichier et lancer debugger.

Comment installer le plugin LiveEdit de Jetbrains sur votre PHPStorm

Allez dans Préférences > Plugins, vous serez sur la page des plugins, si le plugin n’est pas encore installé, allez dans Marketplace, choisissez LiveEdit et installez.

Ensuite sur votre navigateur Chrome, il faut installer le plugin Chrome IDE Support. Lien fourni ci-dessus. Ce plugin permet d’envoyer et lire des informations avec PHPStorm, grâce à ce mécanisme de communication, vous pouvez débugger le javascript depuis votre éditeur PHPStorm !

Comment autoriser le rechargement de la page avec PHPStorm et LiveEdit

Dans PHPStorm, l’explorateur de fichier, faites un clic droit sur le fichier php que vous voulez lancer, cliquez sur Run.

LiveEdit Jetbrains
LiveEdit Jetbrains

Comment démarrer une session de débug avec LiveEdit?

Pour débugger il suffit de cliquer sur Debug à la place de Run. Dans cette situation, vous pouvez débugger aussi bien le Javascript que le PHP ! Mettez « debugger »  à l’endroit où vous voulez que le debug Javascript commence.

 

javascript

Faire des tabulations en Javascript et Jquery

Voici le code minimal pour faire une tabulation (des onglets que l’on peut cliquer pour changer de contenu)

Comment faire des onglets cliquable en javascript?

Le principe :

On a en fait une rangée d’éléments cliquables, que l’on va mettre dans des <li>, mais ce n’est pas obligatoire, et ensuite les différentes <div> que l’on va révéler ou cacher suivant les <lI> cliquer.

<html>
<head>
<title>Tutorial theme</title>
</head>

<body>
    <style>
        .tab-menu {
            padding: 0;
        }
        .tab-menu li {
            display: inline-block;
        }
        .tab-menu .active {
            background: yellow;
        }
    </style>

        <ul class="tab-menu">
            <li><a href="#tab-1">Tab 1</a></li>
            <li><a href="#tab-2">Tab 2</a></li>
            <li><a href="#tab-3">Tab 3</a></li>

        </ul>

<div id="tab-1" class="tab-content" >
Contenu du tab 1
</div>
<div id="tab-2" class="tab-content" >
Contenu du tab 2
</div>
<div id="tab-3" class="tab-content" >
Contenu du tab 3
</div>


</body>
    <script type="text/javascript">
        $(document).ready(function() {
          $('.tab-content').slice(1).hide();
            $('.tab-menu li').eq(0).addClass('active');
            $('.tab-menu li a').click(function(e) {
                e.preventDefault();
                var content = $(this).attr('href');
                $(this).parent().addClass('active');
                $(this).parent().siblings().removeClass('active');
                $(content).show();
                $(content).siblings('.tab-content').hide();
            });
        });
    </script>
</html>

Donc pour résumer en cliquant un lien, ce lien a sa classe css à active, les autres qui sont à côté sont inactifs, content est égal à ce qu’il y a dans l’attribut href, $(content) va en réalité sélectionner l’élément ayant l’id (unique cela va de soi), et le montre, tous ses voisins sont cachés.

 

 

 

php

Installer PHP sur MacOs

Récemment j’ai voulu installer MAMP (l’équivalent de WAMP sous Mac mais en moins bien je pense), je n’ai pas réussi à configurer les virtual host, la raison est qu’il existe déjà un Apache sous MacOs puisque c’est un système basé sur Unix.

J’ai donc décidé d’installer à la main de quoi faire un serveur PHP avec une base MySQL.

Installation de PHP et configuration sour MacOS

Il faut aller dans le répertoire de configuration d’Apache /etc/apache2/httpd.conf

décommenter la ligne de chargement du module PHP

LoadModule php7_module libexec/apache2/libphp7.so

testez votre script PHP, si apache affiche le code PHP c’est qu’il ne gère pas encore les script PHP, il lui faut dire comment interpréter les fichier avec l’extension php

<FilesMatch .php>
SetHandler application/x-httpd-php
</FilesMatch>

 Normalement redémarrez Apache avec la commande :

sudo apachectl -k restart

Ensuite il faut indiquer quel est le fichier qui servira d’index, en effet ça ne se fait pas tout seul.

<IfModule dir_module>
    DirectoryIndex index.php index.html
</IfModule>

Où se trouve le fichier avec le message It Works !?

Lorsque que vous entrez l’adresse http://localhost/ vous avez une page avec le message « It Works ! », le problème est  de localiser ce fichier.

Allez dans le fichier httpd.conf, et localisez la chaine de caractères « DocumentRoot », et assurez vous d’avoir le script :

DocumentRoot "/Library/WebServer/Documents"
<Directory "/Library/WebServer/Documents">

Pourquoi mon script PHP ne peut écrire sur son répertoire?

Tout simplement (enfin faut le savoir !) parce que c’est Apache qui exécute le script PHP et que par défaut Apache est un autre utilisateur.

Dans le fichier de configuration httpd.conf, cherchez la chaine « Group » et remplacez la

#User _www
#Group _www
User monuser
Group staff

Apache va maintenant s’exécuter en lieu et place de vous.

Note sur quelques commande Apache

# Reloader le fichier configuration sans redémarrer le serveur après une modification du fichier httpd.conf
$ sudo apachectl graceful

# Redémarrage d'Apache
$ sudo apachectl restart

Activer la réécriture d’url mod_rewrite

Certains logiciel ont besoin de ce module d’Apache pour marcher, WordPress par exemple, ou encore Symfony ou Laravel. Le module peut ne pas être chargé par défaut, dans le fichier php.ini, chercher la ligne contenant mod_rewrite et décommenter la ligne, redémarrer Apache.

Utilisation de Awk et Grep pour lister les pages inactives d’un site WordPress

Qu’est qu’une page inactive en SEO?

C’est une page de votre site qui est en ligne, visible par le moteur de recherche, mais n’ayant pas généré de visite. Ces pages sont problématiques, car elles doivent générer des visites, au moins une fois par an. Si aucune visite générée, il est urgent de les détecter, les corriger ou de les supprimer, car elles peuvent nuire à votre SEO.

Comment fait-on pour détecter ces pages inactives?

Tout simplement en regardant les urls qui sont présentes dans votre sites et qui ne le sont pas dans les logs de visite depuis un moteur de recherche, en l’occurence Google. Nous allono svoir comment le faire en PHP, on aura besoin de faire un tableau d’urls existantes du site $available_url, et un tableau d’urls qui ont eu au moins une visite sur une période données $hits, 6 mois ou un an, par exemple. On va appliquer la fonction très pratique array_diff en PHP qui va nous retourner un troisième tableau qui contient les urls de pages inactives.

Préparer le terrain en élaguant ce qui est inutile

On doit d’abord avec par exemple Google Analytics exporter les urls ayant reçu une visite, en allant dans Acquisition > Google Search Console > Landing Page, et choisir une période d’un an ou de six mois, et exporter les urls dans un fichier csv.

Ensuite, pour les urls existantes d’un site WordPress, on va taper directement dans la base de données, en requêtant dans la table wp_posts

--cas d'une boutique Woocommerce
SELECT post_name FROM `wp_posts` WHERE post_status = 'publish' and post_type = 'product' 

--cas d'un blog WordPress
SELECT post_name FROM `wp_posts` WHERE post_status = 'publish' and post_type = 'article'

Note :  je n’ai pas pris en compte les pages, ni les catégories, si vous les voulez il suffit d’inclure and ajoutant une nouvelle clause AND.

Ces deux manipulations vont nous retourner des fichiers csv brut, or on ne veut que l’information de l’url il va falloir nettoyer toutes les données parasites qui ne nous intéressent pas.

Comment nettoyer le fichier export de Google Analytics?

Les fichier CSV Google Analytics

//extrait

/blog/?p=425,104 867,7 876,"7,51 %","6,7",1 018,"88,11 %","1,18",0,"0,00 €","0,00 %"
/portant-garage/,11 683,409,"3,50 %","9,3",330,"44,24 %","3,99",0,"0,00 €","0,00 %"
/blog/?p=374,10 195,802,"7,87 %",17,86,"96,51 %","1,03",0,"0,00 €","0,00 %"
/,8 317,799,"9,61 %",31,652,"25,15 %","9,31",0,"0,00 €","0,00 %"
/sac-moto/,6 651,98,"1,47 %",28,103,"59,22 %","2,69",0,"0,00 €","0,00 %"
/boutons-de-col/,6 044,100,"1,65 %",17,195,"1,03 %","2,53",0,"0,00 €","0,00 %"
/blog/?p=153,3 019,177,"5,86 %",16,23,"100,00 %","1,00",0,"0,00 €","0,00 %"
/boite-japonais/,2 707,19,"0,70 %",25,26,"34,62 %","4,58",0,"0,00 €","0,00 %"
/aimant-en-neodyme/,2 589,3,"0,12 %",11,21,"76,19 %","4,29",0,"0,00 €","0,00 %"

 

Comment nettoyer le fichier export de WordPress?

Le fichier CSV de WordPress

//extrait

"disque-de-frein-8-5cm"
"mousqueton-avec-attache-d-a303"
"lot-de-5-amortisseurs"
"boite-japonaise"
"aimant-pour-fermeture"
"portant-garage"
"pression-aimantee-vendu-par-2"
"bouton-de-col"
"bouton-de-tiroir-argent"
"aimant-en-neodyme"

 

Comment nettoyer un fichier csv en vidéo


Après avoir nettoyé les deux fichiers et rendu utilisable, nous allons les injecter dans des tableaux pour les comparer et extraire les urls d’un tableau qui ne sont pas présents dans l’autre afin d’avoir les urls inactives. Les script PHP est simple :

//open hit csv file
$hithandle = fopen('hits3.csv', 'r');
while(!feof($hithandle))
  {
  $hits[] = fgets($hithandle);
  }
fclose($hithandle);


// open available pages csv file
$availablehandle = fopen('available.csv', 'r');
while(!feof($availablehandle))
  {
  $available_url[] = fgets($availablehandle);
  }
fclose($availablehandle);

//make array of urls in $available that is not present in $hits
//Affiche les urls inactives
$poor = array_diff($available_url,$hits);
echo count($poor).'<br>';
echo '<pre>';
print_r($poor);
echo '</pre>';

Rappel des commandes utilisées

awk  -F/ '{print $2}' test.csv
grep -v 'blog' test.csv
awk -F/ '{print $2}' hits.csv > hits2.csv

sed -i 's/\"//g' available.csv  (edit in place)

 

Mysql

Nettoyer la table USER de Mysql si vous n’arrivez pas à créer d’utilisateur

Il peut arriver qu’il soit impossible de créer un utilisateur car on a l message :

Index for table ‘.\mysql\user.MYI’ is corrupt; try to repair it

Ceci m’est arrivé quand j’ai installé la solution alternative à WAMP qui est WINMP (NGINX au lieu d’Apache), quand j’ai essayé de faire un tuto de migration de Laravel

La solution est de la réparer avec les commandes suivante :

USE mysql;
CHECK TABLE user;
REPAIR TABLE user;

 

 

Linux

Convertissez les videos Youtube en mp3 sous Linux

Voici un tuto rapide à faire sous Linux pour télécharger une vidéo Youtube et la convertir en mp3.

Juste pour vous montrer la commande shell wget et comment manipuler les conversion multimédia.

Wget, une commande bien pratique pour télécharger des fichiers sur le web

J’utilise principalement WGET pour télécharger le dernier zip de WordPress et le décompresser dans le répertoire de mon site web, cela va bien plus vite que de charger depuis votre disque dur via ftp.

Dans sa plus simple expression Wget est suivi de l’url du fichier sur le web, par exemple pour télécharger le fichier de la page d’accueil de Google.fr, on fait:

$wget https://www.google.fr

Ceci aura pour effet de créer un fichier index.html qui contient le source code de la page.

Pour télécharger l’archive de WordPress, il suffit de faire:

$wget https://worpress.org/latest.zip

Télécharger une vidéo Youtube

Pour télécharger une vidéo Youtube, utiliser Wget ne marchera pas car ce dernier va vous télécharger la page web, et en ce qui concerne le fichier de la vidéo, comme c’est du streaming, ce ne sera pas possible.

Fort heureusement sous Linux, il y a un utilitaire qui s’appelle youtube-dl qui fonctionne « à la manière de » wget.

Tout d’abord nous allons installer youtube-dl, malheureusement ce ne sera pas avec apt-get sous Debian Jessie, vous aurez un message comme quoi le paquet est manquant. En fait il n’est pas dans les dépôts par défaut.

Par contre il est possible de télécharger depuis le site officiel et on va le faire avec wget !

$sudo wget https://yt-dl.org/latest/youtube-dl -O /usr/local/bin/youtube-dl
$sudo chmod a+x /usr/local/bin/youtube-dl
$hash -r

La première ligne va cherche le programme, la seconde va le rendre exécutable, et la troisième ligne permet d’éviter de chercher dans $PATH à chaque fois que vous allez taper la commande youtu-dl.

Télécharger une vidéo Youtube

A noter que youtube-dl peut marcher avec d’autres plateforme de streaming, je n’ai pas essayé.

Voici la commande pour télécharger une vidéo Youtube, d’abord allez sur la vidéo et copiez l’url de la vidéo Youtube et faites cette commande :

$youtube-dl -o /home/myfoldr/mp3 https://www.youtube.com/watch?v=3zy2pBoTuOQ

Ceci sauvegardera dans un répertoire qui aura pour nom le titre de la page web. Le switch -o indique où seront déposés le fichier.

Ensuite il faudra le convertir en mp3

Convertir en mp3 avec Avconv

$sudo apt-get install libav-tools

Avconv est sensiblement le même que ffmpeg. ffmpeg n’étant plus dans le repo de Jessie (en tout cas je n’ai pas réussi à l’installer, on va se contenter d’utiliser Avcon, la différence notable est que les fichier .srt (sous-titre de film) ne sont pas suportés par Avconv.

 

$avconv -i /chemin-vers-mp4 -vn filename.mp3

A noter que l’argument -vn va rendre votre encodage beaucoup plus rapide, car on n’a pas besoin de la video, on veut que la bande son, donc si vous ne mettez pas cet argument la conversion sera très lente.

Bonus : télécharger directement en mp3 !

Avec la commande suivante vous pouvez télécharger directement en mp3 soit autant de temps gagné :

$youtube-dl -i --extract-audio --audio-format mp3 --audio-quality 0 URL_YOUTUBE

Pour avoir le nom bien formaté (car par défaut il y a l’id de la video qui est dans le nom du fichier) :

$youtube-dl -o "%(title)s.%(ext)s" -i --extract-audio --audio-format mp3 --audio-quality 0 URL_YOUTUBE

 

 

source : https://doc.ubuntu-fr.org/youtube-dl

 

 

Configurer l’éditeur VIM sous Windows, Linux ou MacOS

Configurer votre éditeur VIM pour améliorer votre productivité

Le fichier de configuration se trouve dans le répertoire d’installation C:\Program Files (x86)\Vim.

Le fichier a éditer est _vimrc. Attention il vous faudra ouvrir votre éditeur en mode Administrateur sinon, vous ne pourrez pas modifier le fichier (pas sauvegarder).

Ci-dessous le fichier d’origine :

source $VIMRUNTIME/vimrc_example.vim
source $VIMRUNTIME/mswin.vim
behave mswin

set nobackup
set nowritebackup
set noundofile
set guifont=Courier_New:h11:cANSI

set diffexpr=MyDiff()
function MyDiff()
  let opt = '-a --binary '
  if &diffopt =~ 'icase' | let opt = opt . '-i ' | endif
  if &diffopt =~ 'iwhite' | let opt = opt . '-b ' | endif
  let arg1 = v:fname_in
  if arg1 =~ ' ' | let arg1 = '"' . arg1 . '"' | endif
  let arg2 = v:fname_new
  if arg2 =~ ' ' | let arg2 = '"' . arg2 . '"' | endif
  let arg3 = v:fname_out
  if arg3 =~ ' ' | let arg3 = '"' . arg3 . '"' | endif
  if $VIMRUNTIME =~ ' '
    if &sh =~ '\<cmd'
      if empty(&shellxquote)
        let l:shxq_sav = ''
        set shellxquote&
      endif
      let cmd = '"' . $VIMRUNTIME . '\diff"'
    else
      let cmd = substitute($VIMRUNTIME, ' ', '" ', '') . '\diff"'
    endif
  else
    let cmd = $VIMRUNTIME . '\diff'
  endif
  silent execute '!' . cmd . ' ' . opt . arg1 . ' ' . arg2 . ' > ' . arg3
  if exists('l:shxq_sav')
    let &shellxquote=l:shxq_sav
  endif
endfunction

#dans certaines plateformes, le fichier d'origine peut être vide

Afficher les numéros de ligne dans VIM:

En mode éditeur, vous pouvez faire la commande suivante pour afficher les lignes :

:set number
#cacher les numéros de ligne
:set nonumber
:set nonu

Et on peut avoir les numéros relatifs de façon exclusive ou en même temps que les numéros absolu

:set relativenumber
#ou
:set rnu
#pour enlever
:set nornu

Dans Vim, en mode navigation faire : (deux points) permet d’exécuter des commandes.

De même si vous voulez que les numéro de lignes soient automatiquement affichés à chaque démarage de Vim, il faut le mettre dans le fichier de configuration .vimrc

Changer la police et la couleur de fond à mettre dans le fichier .vimrc :

colorscheme darkblue
set guifont=DejaVu_Sans_Mono:h10:cANSI

Définir la taille par défaut de votre fenêtre d’édition (ceci est un must car la fenêtre fait  640 x 480 par défaut (environ). Avec le terminal multiplexer TMUX, vous pouvez subdiviser votre fenêtre en sous fenêtres.

set columns=200
set lines=50

exemple de configuration : https://alvinalexander.com/linux-unix/vimrc-vim-example-commands-configuration-file

Autres liens vers VIM

Linux

Compiler un programme sous Linux

Pourquoi compiler un programme ?

Pour qui n’a jamais fait ce genre de manipulation ça peut paraître terrifiant.

Mais après avoir passé 3 semaines  scotché sur un problème insoluble autre que  par la montée en version mineure de la bibliothèque ImageMagick. En effet j’avais à convertir un fichier SVG tout en préservant la transparence et aux bonnes dimensions en pixel sur un soft développé à l’origin pour fonctionner avec Imagemagick.

Le problème s’est posé après que j’ai migré l’application sur un nouveau serveur avec une distro Linux différente qui ne proposait pas encore la version 6.9.9 de Imagemagick dans son gestionnaire de package (je parle de Debian 8 qui vient avec Imagemagick 6.8 !). Après des errement avec Inkscape, qui ne résolvait pas le problème, j’ai décidé de faire violence de télécharger la version 6.9.9 d’Imagemagick et de le compiler !

Comment compiler un programme sous Linux?

D’abord il faut télécharger les fichiers sources, mais aussi les dépendances, un bon wget fera l’affaire. décompresser dans un répertoire. J’ai téléchargé le zip sur un site qui héberge la librairie Imagemagick pour Linux.

ensuite il y a la configuration, pour ce faire, aller dans le répertoire, et faire la commande

./configure

Ensuite faire la commande make qui va faire la compilation proprement dite (sous root ou en sudo)

make
ou
sudo make

Si la compilation s’est bien déroulée, il faut  installer le programme dans le système.

make install
ou
sudo make install

Il se peut que vous ne puissiez pas faire marcher le programme, il faut configurer les liens dynamiques de runtime :

ldconfig /usr/local/lib
ou
sudo ldconfig /usr/local/lib

finalement faire un make check pour valider que le programme fonctionne bien.

 

C# SqlServer Faire Un CRUD simplement

Parmi les choses à savoir faire absolument en programmation : dialoguer avec la base de données ! sans quoi il ne sert à rien de programmer, car on a besoin de persister (sauver) des données, et les réutiliser. Nous allons dans un premier temps entrer en contact avec la base de données, et ensuite requêter des données avec du SQL.

Faire du CRUD en C# avec SQL Server

Connexion à la base de données

Tout d’abord sachez qu’il y a deux façons de se connecter à la base de données, la connexion avec les identifiants Windows, ou la connexion avec les identifiant de l’utilisateur de la base de données

Connexion à Sqlserver avec les identifiants de Windows

using System;
using System.Text.RegularExpressions;
using System.Net;
using System.IO;
using System.Data.SqlClient;

namespace scraper
{
    class Program
    {
        // http://lgmorand.developpez.com/dotnet/regex/
        static void Main(string[] args)
        {
            SqlConnection myConnection = new SqlConnection("Server=[myserver];Database=[DBSQL];Trusted_Connection=true");
            myConnection.Open();
           }
    }
}

Il suffit d’ajouter « Trusted_Connection=true » pour indiquer que l’on veut utiliser les identifiants de Windows.

Connexion à Sqlserver avec les identifiants utilisateur

Maintenant, la seconde façon de se connecter est d’utiliser les identifiant de connexion à la base de données de l’utilisateur créé pour la base.

using System;
using System.Text.RegularExpressions;
using System.Net;
using System.IO;
using System.Data.SqlClient;

namespace scraper
{
    class Program
    {
        // http://lgmorand.developpez.com/dotnet/regex/
        static void Main(string[] args)
        {

            SqlConnection myConnection = new SqlConnection("Data Source=myservername;Initial Catalog=DBSQL;User ID=UserName;Password=Password");
            myConnection.Open();
           }
    }
}

Ok là c’est écrit un peu à l’arrache, mais pour bien faire, il faut bien prévoir le cas où la connexion à la base échoue, donc on va mettre dans une clause try-catch.

using System;
using System.Text.RegularExpressions;
using System.Net;
using System.IO;
using System.Data.SqlClient;

namespace scraper
{
    class Program
    {
        // http://lgmorand.developpez.com/dotnet/regex/
        static void Main(string[] args)
        {
            SqlConnection myConnection = new SqlConnection("Server=[servdom];Database=[SAGESQL];Trusted_Connection=true");
            try {
                myConnection.Open();
            }
            catch(Exception e) {
                Console.WriteLine(E.Message);
                Console.ReadLine();
            }
       }
    }
}

Création d’une table

CREATE TABLE [dbo].[references](
  [id] int IDENTITY(1,1) PRIMARY KEY,
  [reference] [varchar](100) NOT NULL,
  [description] [varchar](50) NULL,
  [regroupement] [varchar](50) NULL
) ON [PRIMARY]

Nous allons utiliser Management Studio pour créer la table. Vous insérez ce script dans une fenêtre de Management Studio, sélectionnez le texte et faites F5 pour créer la table.

Insertion d’un enregistrement

Sans plus tarder, faison un INSERT dans la table « references », à noter que references est un mot clé dans sqlServer ! mais on peut quand même l’utiliser en l’entourant de crochet [references]

public void InsertActivity(string activity)
 {
     string userName = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
     SqlConnection conn = GetConnexion();
     SqlCommand sql = new SqlCommand("INSERT INTO [FREZAL_HISTORY] (UserName,Date,TableName,ColumnName) VALUES (@UserName, @Date,@TableName,@ColumnName)", conn);
     conn.Open();
     sql.Parameters.Add("@UserName", System.Data.SqlDbType.VarChar);
     sql.Parameters.Add("@Date", System.Data.SqlDbType.DateTime);
     sql.Parameters.Add("@TableName", System.Data.SqlDbType.VarChar);
     sql.Parameters.Add("@ColumnName", System.Data.SqlDbType.VarChar);

     sql.Parameters["@UserName"].Value = userName;
     sql.Parameters["@Date"].Value = DateTime.Now;
     sql.Parameters["@TableName"].Value = "PriceGrabber";
     sql.Parameters["@ColumnName"].Value = activity;

     sql.ExecuteNonQuery();
     return;
 }

 

Select d’un enregistrement

public bool HasAlready(string reference)
{
    try
    {
        SqlConnection conn = GetConnexion();
        conn.Open();
        SqlCommand sql = new SqlCommand("SELECT count(*) FROM [FREZAL_PG_REFERENCES] WHERE reference = @reference", conn);
        sql.Parameters.Add("@reference", System.Data.SqlDbType.VarChar);
        sql.Parameters["@reference"].Value = reference.Trim();

        int a = (Int32) sql.ExecuteScalar();
        if (a > 0)
        {
            return true;
        } else
        {
            return false;
        }
    }
    catch(Exception e)
    {
        Console.WriteLine(e.Message);
    }

    return false;

}

 

Update d’un enregistrement

public void UpdateVendorUrl(Url url)
{
    SqlConnection conn = GetConnexion();
    SqlCommand sql = new SqlCommand("UPDATE [OMG_PG_URLS] SET url = @url WHERE id = @id",conn);
    sql.Parameters.Add("@url", System.Data.SqlDbType.VarChar);
    sql.Parameters.Add("@Id", System.Data.SqlDbType.Int);


    sql.Parameters["@url"].Value = url.url;
    sql.Parameters["@id"].Value = url.id;

    conn.Open();
    sql.ExecuteNonQuery();

    return;
}

 

Delete d’une enregistrement

public void DeleteReference(string reference)
{
    try
    {
        SqlConnection conn = this.GetConnexion();
        conn.Open();
        SqlCommand sql = new SqlCommand("delete from [OMG_PG_REFERENCES] where reference = '" + reference + "'",conn);
        sql.ExecuteNonQuery();
        sql.Dispose();
        conn.Close();
    } catch(Exception e)
    {
        Console.WriteLine(e.Message);
        Console.ReadLine();
    }
}

 

csharp green logo

C# écrire un programme qui s’exécute à intervalles réguliers

 

Utiliser Timer pour exécuter à interval régulier une méthode

Il faut utiliser l’objet Timer :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;

namespace returning
{
    class Program
    {
        static void Main(string[] args)
        {
            Timer timer = new Timer(TimerCallback, null,0,5 * 1000);// five seconds
            Console.ReadLine();
        }

        private static void TimerCallback(object sender)
        {
            Console.WriteLine("il s'est écoulé 5 secondes");
           
        }


    }
}

 

Que faire quand MYSQL n’arrive pas à se connecter sur son socket?

Avez vous déjà reçu ce message lorsque vus essayer de démarrer MySql Server?

Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2) when trying to connect

 

Il y a moultes raisons pour que Mysql ne fonctionne pas, mais l’objet de ce post est de donner une petit explication sur ce fameux mysqld.sock, central dans le fonctionnement de Mysql.

C’est quoi un socket en particulier dans Linux?

Un socket est un fichier créé par le serveur, il est très spécial qui ne contient pas de données, mais qui est utilisé pour transporter des données. c’est un point d’échange de données entre client server. C’est toujours un fichier local dans le sens où il est utilisé localement et non à travers un réseau.

https://dev.mysql.com/doc/refman/5.7/en/mysqld-safe.html

Quand le fichier socket (qui n’est pas un fichier ordinaire) n’est pas à son emplacement prévu, MySql refuse de démarrer.

Regardez où devrait être ce fichier socket dans le fichier de configuration my.cnf.

Impossibilité de créer un utilisateur dans la table user d emysql

Que faire quand  vous avez un message comme quoi l’index de la table user est :

Index for table ‘.\mysql\user.MYI’ is corrupt; try to repair it ?

Linux

Mettre un process en background

Il est assez intéressant de savoir passer un processus en background si ce dernier dure longtemps, afin d’avoir la main pour lancer autre chose (sans ouvrir une autre fenêtre shell).

Mettre un process en background dès le lancement

Imaginez que vous ayez lancé une commande « find »

find ./ -type f "fichier"

 

Cette commander peut durer plusieurs secondes ou minutes sur un serveur lent. On va le lancer directement en tâche de fond.

find ./ -type f "fichier" &

 

Mettre un process déjà engagé en background

Vous avez lancé une commande mais oublié de le mettre dès le lancement en background, ou alors elle dure plus longtemps que prévu, pas de panique, vous pouvez toujours le mettre en bacground.

find ./ -type f "fichier"
[CTRL+Z]
bg

En faisant Control+Z, vous reprenez la main sur le shell et vous pouvez taper « bg » pour mettre le process background.

Remettre un process en foreground

Finalement vous décidez de remettre en avant le process qui a été mis en background, c’est possible tout simplement avec la commande « fg »

fg

Oui mais ça marche pour le dernier process lancé, comment faire si vous avez lancé plusieurs process? Grâce à la commande « jobs », vous pouvez lister les commandes qui sont en background.

jobs

[1]   Stopped                 vim
[2]-  Stopped                 bash
[3]+  Stopped                 vim 23

fg %3 pour ramener vim 23 en avant plan.

 

Mettre un process en background et le détacher du shell

Ok, tout ce qu’on a vu jusqu’à présent, et relié au shell courant, c’est à dire que si vous fermez la fenêtre du shell, la commande en background va s’arrêter.

Afin de rendre le processus indépendant du shell, il faut le détacher du shell. Ceci se fait grâce à al commande nohup.

nohup find ./ -type f "fichier"

Cette commande va aussi générer un fichier log nohup.out dans le répertoire home.

Détacher un process existant du shell

Avec « nohup » vous détachez d’emblée un process du shell, mais il est possible de détacher après coup.

find ./ -type f "fichier" &
disown

grâce à la commande « disown », on détache après coup un process du shell. Faire le contraire de « disown » n’est pas implémenté dans Linux et ne sera pas traité. Si vous voulez arrêter un job, il faudra utiliser la commande « kill ».

Utilisé de concert avec la commande « jobs », utilisez le paramètre -h pour indiquer quel job détacher du shell.

disown -h %3

 

 

csharp green logo

NewtonSoft la librairie très puissante pour manipuler les chaines JSON

Librairie NewtonSoft pour manipuler les JSON

En C# vous disposez d’une très puissante librairie pour manipuler les chaines et objets JSON. Pour utiliser cette librairie, aidez vous de Nuget pour la télécharger dans votre projet.

Certes .Net possède des méthode pour manipuler les JSON, mais ce n’est pas très pratique. Il est vivement conseillé d’utiliser NewtonSoft.

Cette librairie sert à convertir une chaine JSON en un objet C# s’il existe une classe équivalente. On l’utilise principalement pour lire les informations d’une chaîne JSON.

Nous allons voir comment transformer une chaîne JSON en un objet C# manipulable facilement, comment extraire un tableau d’objets JSON, la  librairie LINQtoJSON permet de traverser un objet construit à partir d’une chaine JSON.

Nous allons partir d’une chaine JSON assez représentative de ce qu’on peut trouver dans la vraie vie, voici ci-dessous une chaine JSON extrait de Mailchimp.

Il existe un outil en ligne qui permet de visualiser le JSON sérialisé, sous forme hiérarchique, très utile pour vous aider à voir plus clair dans une chaine JSON que vous ne connaissez pas => Online JSON Viewer.

Obtenir la librairie NewtonSoft avec Nuget dans Visual Studio

Clickez avec le bouton droit de la souris sur le projet, « Gérer les packages Nuget », tapez le nom « Newtonsoft », et installez. Normalement dans le projet courant une référence à cette librairie est faite.

Obtenir une chaîne JSON (Mailchimp dans notre cas)

Mailchimp a sans doute l’un des services web REST les plus plus facile à utiliser. Avec lui pas besoin d’authentification Oauth2, il suffit d’obtenir une clé secrète (à ne pas dévoiler ! donc exit les usages avec du Javascript côté client).

Vous pouvez télécharger le fichier JSON échantillon pour faire des tests.

Copiez le contenu et allez sur le site Online JSON Viewer et visualisez le contenu de la chaine.

Une fois l’arbre reconstitué, vous pouvez naviguer dans le contenu. On voit un tableau de JSON « lists ».

Chinae JSON

On continue à inspecter le contenu, nous pouvons voir la structure qui s’affiche clairement, les éléments de ce tableau sont des JSON, en langage C# ce sont des IEnumerable, dont les objets pourront être appelé List. Mais comme en C# List est déjà existant, ici on va plutôt appeler MailChimpList. Cette MailchimpList contient des propriétés dont certaines sont des objets (Contact, CampaignDefault,Modules,Stats, Links).

chaine JSON

Bonus : en C# tout est typé, donc il y a des classes pour tout. Dans le cas de Mailchimp, vous recevez le JSON mais ce serait bien de convertir ça en objet, le problème c’est que bien que vous connaissiez la structure du JSON qui vous permettra de créer vos classes, c’est super fastidieux, il existe un site (et sans doute des librairies) qui transforme votre JSON sérialisé en objet C# !

Voici le site qui permet les conversions en ligne :  http://json2csharp.com/

Créer des définitions de classe à partir des chaînes JSON

Objectif : créer une définition de classes pour pouvoir convertir la chaine JSON en objet C# afin de travailler dans le monde de la programmation orientée objet. En effet notre objet MailchimpList pourrait être comme ci-dessous :

MailchimpList{

    Contact contact {get;set;}
    CampaignDefaults campaignDefault {get;set;}
    List<Modules> listModules {get;set;}
    Stats stats {get;set;}  
    List<Link> listLinks {get;set;} 

}

Donc ce qu’il faut faire c’est copier coller un élément de la liste « lists » et non les 6 éléments, et coller dans l’interface du site de conversion.

 

Et voilà magique non? C’est quand j’étais à deux doigts de coder à la main les classes que je me suis mis à chercher une solution qui le ferai pour moi sans efforts. L’image ci-dessus n’est qu’un extrait pour vous montrer.

Parsons la chaîne JSON avec les méthodes de la librairie NewtonSoft

La librairie est riche en méthodes, et l’on peut se perdre facilement, car il y a plusieurs façons de faire les choses, mais essayons de lister des méthodes courantes méthodiquement pour ne pas perdre de temps à chercher.

Dans la première image on voit dans le JSON qu’il peut y avoir deux type de choses : un tableau de JSON, des propriétés.

Conversion de base en JObject

La méthode la plus générique, convertir n’importe quel JSON en JObject. C’est à dire que quelque soit le contenu du JSON (propriété + tableau), ça marche.

JObject o = JObject.Parse(jsonString);

jsonString est une chaîne de caractère qui contient

Désérialisation partielle (partial deserialization)

Très pratique, imaginons que vous ayez un gros objet JSON, amis qu’il n’y a qu’un partie de cet objet JSON qui vous intéresse, grâce à JSONtoLINQ, vous pourrez accéder à une propriété de cet objet JSON et le parser, vous évitant ainsi d’écrire des classes inutilement.

JObject o = JObject.Parse(jsonString)
List<JToken> list = o["lists"].Children().ToList();

Ici on accède à une propriété particulière du JObject, prenons les élément du tableau et on les transforme en List, via la notation Linq.

Sérialiser un JSON

La sérialisation est le contraire de la désérialisation, elle consiste à transformer un objet en une chaine de caractères afin de pouvoir la transporter ou la stocker. En général, des guillemets sont ajoutés.

Product product = new Product();

product.Name = "Apple";
product.ExpiryDate = new DateTime(2008, 12, 28);
product.Price = 3.99M;
product.Sizes = new string[] { "Small", "Medium", "Large" };

string output = JsonConvert.SerializeObject(product);

//{
//  "Name": "Apple",
//  "ExpiryDate": "2008-12-28T00:00:00",
//  "Price": 3.99,
//  "Sizes": [
//    "Small",
//    "Medium",
//    "Large"
//  ]
//}

 

Convertir un JSON Array en « IEnumerable » avec JArray

Pratique lorsque qu’une propriété du JSON est un tableau et que l’on souhaite extraire tous les éléments du tableau.

Si vous disposez d’un tableau de JSON, vous pouvez le transformer en JArray en une seule commande

string json = @"['Small','Medium','Large']";
JArray a = JArray.Parse(json);
var z = a.First().GetType();
Console.WriteLine(a.ToString());
// [
//   "Small",
//   "Medium",
//   "Large"
// ]

SI vous survolez la variable z, vous aurez le type d’un élément du tableau, qui est un JToken.

Last thing : JProperty

JProperty représente une propriété d’un objet JSON.

En notation JSON on met les clé:valeur de cette façon :

{
   nom:"Dupont",
   prenom:"Yves",
   age:34,
   voiture:[{marque:"alfa Romeo",modele:"Giulietta"},{marque:"BMW",model:"Z4"}],
   hobby:["sport","informatique"]
}

La propriété nom a pour valeur « Dupont ». La méthode Properties() permet d’extraire les propriétés, utile si vous voulez sélectionner une en particulier ou tester la présence d’une propriété.

foreach (JProperty property in o.Properties())
{
    Console.WriteLine(property.Name + ":" + property.Value);
}

// sortie console

nom:Dupont
prenom:Yves
age:34
voiture:[
 {
 "marque": "alfa Romeo",
 "modele": "Giulietta"
 },
 {
 "marque": "BMW",
 "model": "Z4"
 }
]

 

JToken, JObject, JArray ?

JToken est une classe abstraite qui sert de base  aux classes JObject, JArray, JProperty et JValue qui sont des données.

Caster un JObject en un objet C#

La partie la plus intéressante ! Enfin nous allons convertir en objet C# la chaine JSON. Pour ce faire on va utiliser JSONConvert.

#j est un objet de type JToken


JObject o = JObject.Parse(Jsonstring);
List<JToken> list = o["lists"].Children().ToList();

List<MCList> mcList = new List<MCList>();

foreach(JToken j in lists){
        mcList.Add(JsonConvert.DeserializeObject(j.ToString()));
    }

En plaçant un espion, nous pouvons voir le résultat de la conversion et le résultat est étonnant :

visual studio espion

Pour un conversion fortement typée, il se peut que le snippet ci-dessus ne marche pas, or ce lien explique qu’il faut la syntaxe suivante :

JObject o = JObject.Parse(Jsonstring); 
List<JToken> list = o["lists"].Children().ToList(); 
List<MCList> mcList = new List<MCList>(); 
foreach(JToken j in lists){     
    mcList.Add(JsonConvert.DeserializeObject<MCList>(j.ToString()));
}

 

La conversion est parfaite ! Nous retrouvons toutes les valeurs de la chaines JSON, la fonction de desérialisation est vraiment puissante ! nous pouvons travailler dans notre univers C# comme si de rien n’était.

csharp green logo

WPF : Retrouver l’index d’une cellule

WPF est un framework MVVM, pour ceux ayant fait du Angular, c’est la même approche. Il y a la View, le Model et le ViewModel.

Le ViewModel et en quelquesorte l’objet qui contient les données et est lié à la vue (View), vient tout de suite la notion de binding (unidirectionnel ou bidirectionnel. Le binding est la lisaison qui assur la synchronisation des valeurs entre le ViewModel et la vue.

Binding bidirectionnel

Toute modification d’une valeur d’un champs texte aura une répercussion sur la même valeur dans le ViewModel. Et toute modification de valeur dans le ViewModel (via du code bien sûr puisque l’utilisateur n’a pas accès au ViewModel) aura une répercussion dans la vue.

Dans AngularJS, on a souvent parlé de cette notion de binding bidirectionnel car c’est ce qui a fait vendre ce framework.

Le problème posé en WPF avec la Datagrid

Le Datagrid est un peu comme une feuille de calcul Excel, c’est un ensemble de lignes et de colonnes. On a souvent besoin de déclencher une action (d’édition par exemple) quand on clique ou double clique sur une cellule, éditer l’entité qui contient cette cellule et mettre à jour dans la base de données cette entité.

La difficulté (ou non) est de retrouver l’id de cette rangée quand on a capturé l’entité. Sur le Net, j’ai vu des tuto alambiqués, qui font peur par leur complexité. En fait c’est plus simple que ça en a l’air. Ceci à condition d’avoir bien balisé  le noeud XAML avec un identifiant unique. Cet identifiant unique, on va le faire intelligemment c’est l’id dans la table de la base de données.

Supposons que vous ayez bindé une List<Url> à Datagrid.ItemsSource, tous vos Url sont mappés aux rangées de la Datagrid. Et chaque propriété de Url est dans une cellule de la rangée.

Utiliser la classe Helper VisualTreeHelper

Cette classe a plusieurs méthodes qui vous aident à traverser le visual tree de votre application WPF, on peut faire le parallèle avec une page HTML. Donc ça peut être très compliqué. Nos allons utiliser la méthode GetParent, qui va retourner le parent de la cellule.

Exemple de pistage de la cellule cliquée

Soit le code XAML suivant :

<TabItem Header="Visualisation des Urls">
    <DataGrid x:Name="ListeUrls" AutoGenerateColumns="False" Margin="1,0,-1,27" >
        <DataGrid.Resources>
            <Style TargetType="{x:Type DataGridCell}">
                <EventSetter Event="MouseDoubleClick" Handler="DataGridCell_MouseDoubleClick"/>
            </Style>
        </DataGrid.Resources>
        <DataGrid.Columns>
            <DataGridTextColumn Binding="{Binding Id}" Visibility="Hidden"></DataGridTextColumn>
            <DataGridTextColumn Header="Vendor" Binding="{Binding Vendor}" Foreground="red" FontWeight="Bold" ></DataGridTextColumn>
            <DataGridTextColumn Header="Url" Binding="{Binding url}" ></DataGridTextColumn>
            
        </DataGrid.Columns>
    </DataGrid>
</TabItem>

On y met un DataGridTextColumn qui contient l’Id, qu’on a bindé, et on le met caché.

Un double Click sur la rangée va nous retourner un objet DataGridCell

private void DataGridCell_MouseDoubleClick(object sender, MouseButtonEventArgs e)
       {
           var dataGridCellTarget = (DataGridCell)sender;
           var parent = VisualTreeHelper.GetParent(dataGridCellTarget);
           .....
       }

La DataGridCell ne contient que la valeur de la cellule (plus d’autres paramètres), en mode débuggage lorsque vous inspectez la valeur de parent, vous verrez les 3 propriétés (Id,Vendor,url), dans la propriété DataContext de parent. Bingo ! Ce DataContext contient le nom de la classe Url.

 

Requêter la base Sql Server en php via Odbc

PHP requêter sur une base Sql Server

On a l’habitude de requêter une base MySql en PHP, mais sur une base Sql Server c’est moins facile à mettre en oeuvre. Microsoft n’a pas développé de driver pour la version 64 bit de WAMP, il a fallu se rabattre sur le driver Odbc.

Requêter vec ODBC n’est pas très difficile, mais plutôt rustique, ce dernier ne bénéficiant sans doute pas de toutes les optimisations (je pense), donc sur de faibles volumétries, ça le faire. J’ai dû le faire pour un récent projet où je devais attaquer la base SQL Server.

Pré requis

Placez un fichier phpinfo(), et regardez si le driver ODBC est installé, si non allez dans le fichier php.ini et vérifiez que la ligne est présente.

vous devez aussi être à l’aise avec le langage SQL, vous pouvez suivre un cours SQL sur Internet

Le driver ODBC lui-même

Su Windows vérifiez que le driver ODBC est installé avec la manipulation suivante :

Dans la boite d’entrée Cortana tapez : odbc

php odbc windows

Cliquez sur « source de données odbc 64 bits »

odbc php

Ici on a la version 13 du driver.

Connexion à la source de données

La grosse différence est la façon de se connecter à la base de données

$data_source='Driver={ODBC Driver 13 for SQL Server};Server=SERV\SAGESQL;Database=MA_BASE';
$user = 'login';
$password = 'motdepasse';

Voici un exemple complet d’une requête :

$conn=odbc_connect($data_source,$user,$password);
if (!$conn){
      exit("Connection Failed:" . odbc_errormsg() );
    }

$sql = 'SELECT * FROM MA_TABLE';
//query
$result = odbc_exec($conn,$sql);
echo odbc_num_rows($result)." results<br>";
//read
$s = odbc_fetch_row($result,0);

echo odbc_result($result,"Siret");

Odbc_exec, odbc_result

odbc_exec exécute la requête, tandis que odbc_result lit un enregistrement. On lui passe deux arguments le premier est la ressource odbc, le second est le nom du champ, ou le numéro de colonne du champ

Parcourir les résultats

//Connaitre le nombre de résultats retournés:

echo odbc_num_rows($result);

Afficher un résultat

Pour une requête retournant un seul résultat, pas d’ambiguité, odbc_result($result, »Siret ») ou odbc_result($result,3) si la colonne Siret est en 4èmeposition.

Chercher une ligne de résultat spécifique:

$s = odbc_fetch_row($result,3);// on cherche la 3ème ligne

echo odbc_result($result,"SIRET");

Afficher une liste de résultats

Dans ce cas la meilleure façon est de faire une boucle while

while($row = odbc_fetch_array($result)){
  echo $row['CT_NUM'] . '-' .$row['SIRET'].'<br>';
}

odbc_free_result($result);

Créer une machine virtuelle sur VMWare Windows 10

Créer une machine virtuelle Linux dans Windows

Préparation de l’installation

  • Téléchargez le VMWare Workstation Player SVP
  • Téléchargez l’iso de la dernière distro d’Ubuntu 16 (ou toute autre distro)
  • Créez une machine virtuelle, nommez la (voir les images).

Le plus important c’est de s’assurer que le réseau marche (il y a deux possibilités : la machine virtuelle s’adosse au réseau de la machine physique via NAS ou Bridge). Je laisse tomber les détails, ce qui nous importe c’est l’installation de la distribution Ubuntu.

 

Création d’une machine virtuelle from scratch

VMWare Windows

Sélection de l’image ISO

D’emblée il vous est proposé d’installer un système d’opération, remplissez quelques informations au passage.

 

 

Allocation de mémoire sur le disque dur et récapitulatif

 

 

Une fois le paramétrage effectué, il vous est proposé de démarrer la machine virtuelle , ce qui a pour effet de provoquer le boot sur l’iSIO Linux, et donc son installation.

Voilà la suite c’est comme d’habitude si vous avez déjà installé une distribution Linux.

Locker un fichier pour éviter qu’il ne soit exécuté deux fois en même temps

Parfois il est nécessaire qu’un fichier ne s’exécute qu’en une seule instance. Par exemple un fichier php qui est inscrit dans une tâche CRON et qui doit mettre à jour une table soit être le seul à tourner, sinon on saboterait l’intégrité des données de la table.

Sous Linux, pour éviter qu’une tâche CRON soit la seule à tourner, il y a différentes manières plus ou moins simples.

Locker un fichier

CRON lui même ne sait pas empêcher qu’un fichier puisse être appelé plusieurs fois en concurrence. Il n’y a aucun moyen d’empêcher cela. LE concept d’empêchement de lancer un second processus s’appelle le locking.

* * * * flock -n /var/lock/myjob.lock /path/to/script

dans l’exemple ci-dessus, la commande flock crée un fichier de lock, pour l’exécution du fichier script.

Il existe un programme qui s’appelle lockrun et qui permet de lancer un job et de locker le fichier en une seule commande.

Lockrun

lockrun --lockfile=/var/tmp/mylock myscript.sh

 

 

Checklist pour développer une PWA (Progressive Web App)

J’essais de créer une PWA depuis quelques temps, et je m’aperçois qu’il y a pas mal de choses à connaitre (vraiment), les connaissances que j’ai acquises en deux ans de JS et d’Angular, ne sont pas suffisantes. Je me fais une liste des pré-requis pour développer une PWA afin d’avoir une feuille de route pour avoir le parcours optimal. Les informations ci-dessous sont tirées du site Google Developer.

Introduction aux Progressives Web App (PWA)

Les PWA sont des pages web dynamiques, offrant des fonctions équivalentes aux applications natives, c’est récent à la date du 2017. Pourquoi a-t-on inventé ça? Pour répondre à plusieurs problématiques inhérentes aux applications natives.

Pourquoi parier sur les PWA?

1/Réduire le travail de développement.

Souvenez vous il n’y a pas si longtemps, on avait Ios, Android et Windows Phone (ce dernier est enterré). Il nous reste donc IOS et Android. Donc si vous voulez développer une application pour ces deux plateformes, vous devez faire deux fois le travail.

2/Les utilisateurs n’installent plus les applications natives

, et seulement une poignée est utilisée régulièrement.

3/Réduire la taille des applications (ou la friction d’installation)

C’est le côté progressif. On ne vous oblige pas à installer une application, mais à tester en douceur le site web, et aller plus loin si vous êtes intéressé.

Ce sont les trois avantages majeurs des PWA. Nous allons voir qu’elles n’ont pratiquement rien à envier aux applications natives. Donc plutôt que d’apprendre à programmer en Java ou Swift, voire en C# si vous voulez utiliser Xamarin (la solution la plus aboutie actuellement), vous allez pouvoir programmer pour toutes les plateformes en Javascript seulement! Donc gros avantage pour les développeurs front-end qui connaissent déjà le Javascript !

Les notions à connaître en PWA

1/Web Push Notification

Les notifications sont les messages que vous voyez apparaitre en haut de l’écran de votre smartphone. Push veut dire qu’il n’est pas besoin (après que vous ayez opté pour les recevoir) pour vous de faire quoique ce soit pour les recevoir. C’est intéressant car pour les marketeurs et pour les développeurs, vous pouvez entrer dans l’intimité d’une personne.

2/Service Worker

C’est l’élément essentiel de la PWA et c’est un gros morceau. Le Service Worker est un thread du processus du navigateur qui tourne en parallèle à côté de la page web proprement dite (le DOM) qui est un autre thread, c’est du code javascript, qui rend les choses hors connexion possibles entre autre (et aussi les Push Notification), le stockage des informations même quand vous êtes hors ligne. Le service worker peut accéder au thread de la page web, donc à l’objet window. Mais il n’y accède pas avec l’objet window qui n’est pas disponible dans le thread, mais via self qui est l’équivalent de window.

Dans le cadre de la programmation d’un service worker, il faut connaitre les Promise, une façon moderne de programmer le JS asynchrone sans faire appel aux callback.

3/Accès aux fonctions natives du smartphone

Ce point est bien sûr très important, à quoi bon si vous ne pouvez pas prendre des photos, enregistrer des vidéos et sons, vous localiser avec le GPS, connaitre l’orientation de l’écran, chatter en vidéoconférence? La réalité virtuelle est aussi disponible quoique encore expérimentale. Donc en résumé voici ce que permet de faire une en 2020 une progressive Web App.

  • géolocalisation GPS
  • Caméra
  • Sensors
  • Payment Request pour les paiements
  • auto update

4/Add to Home screen

C’est pour avoir l’équivalen et de l’installation des application natives depuis le store des applications.

5/ Le fonctionnement hors ligne

C’est une des proposition de valeur majeure des PWA, grâce au Service Worker, votre application web va pouvoir fonctionner hors ligne, et dès que la connexion au web sera restaurée, les données peuvent être synchronisée (moyennant un code bien sûr).

6/Le fichier manifest.json

Un fichier manifest en général décrit le contexte ou le paramétrage de l’application. La première fois que j’ai vu ce concept c’est dans les applications mobiles Android, où il y a un fichier manifest, sur IOS il porte un autre nom info.plist.

Maintenant que vous avez une idée plus claire commençons à développer un PWA ! Le plus didactique est de convertir un site web traditionnel en PWA, plutôt que de faire un PWA de zéro.

linux logo

Linux customiser son bash shell

Le shell est l’invite de commande du terminal Linux (ou Unix), c’est cet écran noir qui fait un peu peur au début, mais qui est très puissant, et quand vous aurez commencé à le maitriser, vous ne pourrez plus vous en passer, et sera une arme à votre trousse d’outils de développeur.

Où se trouve le fichier de customisation du shell?

Le fichier s’appelle ou .bash_profile (ou .bashrc) et se trouve dans le répertoire home de l’utilisateur. Mais attention au démarrage du shell, le fichier .bashrc n’est pas lu pour plus d’informations voir cette source.

Que customiser ?

Le $PATH

Le $PATH est l’ensemble des chemins de fichiers vers des exécutables, voici un extrait :

export PATH="~/.composer/vendor/bin"
alias composer="php /usr/local/bin/composer.phar"
export PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/X11/bin:/usr/local/mysql/bin:$PATH
 

Note : J’ai passé pas mal de temps sur MacOS à faire marcher le path pour Mysql, j’avais le fichier comme ceci :

export PATH=/usr/local/mysql/bin:$PATH
export PATH="~/.composer/vendor/bin"
alias composer="php /usr/local/bin/composer.phar"
export PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/X11/bin:/usr/local/mysql/bin:$PATH

Je n’ai jamais réussi à faire marche le PATH de cette façon, il a fallu que je l’incorpore dans la dernière ligne pour la mettre à la suite des autres déclaration pour que le shell en tienne compte.

Pour confirmer que la variable $PATH contient bien les chemin, faites la commande :

echo $PATH

Notez que si vous venez de faire le changement dans le fichier .bash_profile, quand vous sortez de l’éditeur texte, les changements ne sont pas appliqué, il vous faut sour ouvrir un nouveau shell (ce qui aura pour effet de lire le fichier .bash_profile), ou alors si vous voulez appliquer les changemnet dans la fenêtre courante :

source ~/.bash_profile
. ~/bash_profile (version courte)

Changer la couleur du prompt

Par défaut dans le bash, il y a deux couleurs, une couleur PS1 lorsque le shell est prêt à lire une commande, et une couleur PS2 quand le prompt attend un argument à la commande. Le bash permet de customiser ces couleurs. Regardons ce que donne l’écho de la variable d’environnement PS1 :

echo $PS1

\[\e]0;\u@\h: \w\a\]${debian_chroot:+($debian_chroot)}\u@\h:\w\$

Que signifient les caractères anti slashés?

\h : le nom du host

\u : le user name

\w : le répertoire courant

\$ :  affiche # si le user est root, UID = 0, sinon affiche $

Pour changer la couleur du prompt tapez cette commande :

export PS1="\e[0;31m[\u@\h \W]\$ \e[m "

Le 0;31 est la couleur rouge, pour le vert c’est le 0;32, vraiment pas facile à se rappeler, n’oubliez pas que ça date tout ça ! Pour avoir la version couleur plus light, rouge light  : 1;31.

L’autocomplétion

L’autocomplétion peut se paramétrer pour l’utilisateur non root en touchant au fichier /etc/passwd

Ce fichier qui n’est modifiable que par root contient les mot de passe de chaque utilisateur, et aussi son shell. Pour l’utilisateur apache le shell est nologin, ce qui veut dire que que cet utilisateur ne peut pas se logger. L’utilisateur root est /bin/bash, les autres utilisateurs sont souvent en /bin/sh, qui ne proposent pas l’autocomplétion. Donc il vous suffit de modifier en /bin/bash pour avoir l’autocomplétion.

Navigation dans l’historique

Saviez vous qu’il n’était pas utile de retaper une commande si vous l’avez déjà tapé? pour ce faire il vous suffit d’utiliser les toucher fléchées, HAUT et BAS pour naviguer entre les commandes déjà tapées. L’historique bash se trouve dans un fichier .bash_history.

Installer le shell Linux (ubuntu) dans Windows 10 !

Un shell Linux dans Windows

Il est loin le temps où Microsoft voulait imposer sa technologie (perfectible la plupart du temps) à tout le monde, et maintenant doit faire des concessions au monde du libre  qu’il a tant détesté car ne générant pas d’argent pour lui. Aujourd’hui Microsoft s’ouvre de plus en plus au monde du libre, jusqu’à avoir une shell embarqué Linux !

C’est une super nouvelle pour moi qui suit habitué à Linux, j’adore le bash, je déteste le Powershell qui est une abomination selon moi. Je vais vous montrer comment activer dans votre Ubuntu dans Windows !

Activer le mode développeur

Dans le champ en bas à gauche de votre écran (champ Cortana) tapez « paramètres », entrez dans le programme et allez dans Security&Updates, puis cochez activer pour développeur, attendez une dizaine de minutes.

Activer la fonctionnalité Linux

Pour ce faire tapez dans le champ Cortana « Panneau », cliquez sur « Programme et Fonctionnalités », puis « Activer ou désactiver des fonctionnalités Windows », puis cocher la case Sous-système Windows pour Linux.

Installation de Ubuntu

Ensuite toujours dans le champs Cortana, tapez « bash », cliquez dessus, une fenêtre de commande s’active, et vous dit de télécharger depuis l’appstore, tapez le lien fournit, et installez Ubuntu, ça prendre une dizaine de minutes (une url vous sera donnée pour accéder à l’appstore).

Dans le champs Cortana, tapez « bash », vous verrez le programme Ubuntu, épinglez à la barre des tâches pour un accès facile plus tard l’icône Ubuntu. Il vous sera demandé de créer votre compte. Vous devez redémarrer l’ordinateur.

ubuntu windows

 

Ensuite collez l’url montrée sur l’écran pour aller à l’appstore de Microsoft

 

Cliquer sur une distribution pour l’installer (Ubuntu)

Ensuite le bash s’ouvre et il vous sera demandé de créer votre user.

Accéder à la partition de Windows

Voilà, c’est tout. Maintenant voyons comment accéder à la partition de Windows, car une fois le compte créé vous êtes dans Ubuntu, donc en principe par grand intérêt.

Dans Linux, il y a la notion de montage de partition. On monte un disque dur virtuel ou réel, comme on monte une clé usb, un drive en réseau, c’est très puissant comme concept, mais en plus c’est très intuitif, tout est traité sur un pieds d’égalité ce qui facilite la compréhension.

Le point de montage est dans le répertoire /mnt/c, allez y vous allez trouver le drive c, qui est votre disque C.

 

 

linux logo

Changer les attribut de fichier dans Linux avec Chattr

Récemment  j’ai eu un site victime d’injection de code, plus exactement le fichier de paiement a été modifié pour intégrer une page de paiement factice afin de siphonner les numéros de carte bancaire.

Ce fichier PHP était modifié à chaque fois que je remettais le fichier non corrompu !

Il a fallu le rendre immuable avec une commande Linux, chattr (change attribute)

Syntaxe :

chattr +i nom_fichier

Si vous le faites sous root, c’est bon, à moins que le pirate n’ai eu accès en root à votre console !

Pour voir que le fichier a bien été modifié, utilisez la commande lsattr.

lsattr nom_fichier
----i----------- nom_fichier

Maintenant essayez d’effacer le fichier

rm nom_fichier
rm: cannot remove 'nom_fichier' : Operation not permitted

Pour enlever l’immuabilité :

chattr -i nom_fichier

 

Autres attributs

Append avec +a, en rendant un fichier +a, tout le monde pourra ajouter du contenu (append), mais ne pourra pas effacer le contenu précédemment entré

chattr +a toto.txt

Et si on essaye de remplacer le texte on aura une erreur :

echo 'un autre texte' > toto.txt
-bash: toto.txt: Operation not permitted

 

 

 

 

debian

Maîtriser les liens symboliques dans Linux

Les liens symboliques dans Linux un must-know

Les liens symboliques sont comme des raccourcis dans Windows,

Création d’un lien symbolique

Faire attention à l’ordre du lien symbolique et du chemine du fichier vers lequel on pointe

ln -s /path/to/file /path/to/symbolic_link

Le paramètre -s spécifie la création de lien symbolique et non de lien dur (symbolic link contre hard link). La distinction est expliquée sur cette page.

Effacer un lien symbolique

rm /path/to/symbolic_link

 

Résoudre les problèmes avec les liens symbolique

Le lien apparait en rouge

lien symbolique

Le lien pointe sur une ressource qui n’existe plus (en général vous avez mal orthographié)

Pour voir plus sur le status du lien faire :

>file apache-accesses
apache-accesses: broken symbolic link to `/usr/share/munin/plugin/apache-accesses'

Pour réparer, eh bien effacez le et recommencer la création du lien

 

debian

Monitorez des serveurs Linux avec Munin

Munin

Monitorez plusieurs serveurs dédiés depuis une seule interface web

Munin est un script pour monitorer un serveur Linux, il monitore des programme comme Apache, Mysql, l’activité du disque, le CPU,les process, le serveur de mail Postfix et plus encore, via un système de plugin, donc une installation standard nécessite d’activer des plugin pour aovir tout ça. On va voir tout ça ne vous inquiétez pas !

Munin a la capacité de monitorer des serveurs autres que ceux sur lequel il est installé. Par exemple, soit le serveur principal sur lequel vous installez Munin Master, ce serveur aura l’affichage sur une page web des graphiques.

Pour monitorer un second serveur dédié, sur ce dernier il faut installer Munin Node, un programme différent spécialement pour ça. Un node est un serveur Linux qui n’est pas principal.

Peu importe le système d’exploitation (Linux, Windows), les données sont rapatriés en mode texte vers le node maître. Donc il suffit pour vous d’installer et de configurer le node secondaire, faire un petit paramétrage, et du côté du node maître de configurer le node secondaire (donc faire une configuration sur les deux serveurs).

Installation de Munin Master

Je suppose que Apache a été déjà installé, on va installer munin maître, cette installatin est plus longue que pour  installer munin-node sur un serveur à monitorer.

apt-get install -y munin

Configurer le fichier /etc/munin/munin.conf, décommenter les lignes suivantes en début de fichier

dbdir     /var/lib/munin
htmldir   /var/www/munin
logdir    /var/log/munin
rundir    /var/run/munin
tmpldir /etc/munin/templates

Créer un utilisateur munin, et le répertoire web dans lequel Apache va accéder pour afficher les informations

Ensuite notion important, configurer le host tree pour le node master (oui on surveille le master et d’autres serveur dédiés)

[MuninMaster]  # avant renommage [localhost.localdomain]
    address 127.0.0.1
    use_node_name yes

Ensuite éditer le fichier apache24.conf

Alias /munin /var/www/munin

Ensuite effacer la section Directory pour la remplacer par ça :

<Directory /var/www/munin>
        Require all granted
        Options FollowSymLinks SymLinksIfOwnerMatch
</Directory>

Et pour la section Location, remplacer Require local par Require all granted pour permettre à toutes les IP de consulter la page de graphique Munin.

 

 

Installation de Munin Node

Sur le serveur node 91.111.111.110 :

#debian
apt-get install -y munin-node

#centos
yum install munin-node -y

Ensuite autoriser l’IP d’écoute dans le fichier /etc/munin/munin-node.conf,

allow ^111\.111\.111\.145$
allow ^::1$

Puis redémarrer le noeud

#centos
service munin-node restart

#debian
systemctl restart munin-node

Sur le serveur maître 111.111.111.145, configurer le node dans /etc/munin/munin.conf (ensuite redémarrer):

[MuninNode]
    address 91.111.111.110
    use_node_name yes

Dupliquez ces 3 lignes pour tout noeud supplémentaire.

Activation des plugins

Les plugins sont situés dans le répertoire /usr/share/munin/plugins, pour les activer il faut créer un lien symbolique vers le plugin dans le répertoire /etc/munin/plugins.

Il existe un utilitaire munin-node-configure qui permet d’auditer en ligne de commande les plugins.

Régler  les problèmes de Munin

 Le node secondaire n’apparait pas dans le panneau d’administration

Pour détecter ce qui ne vas pas, souvent pourquoi le node master n’arrive pas à rapatrier des données d’un node secondaire, il est utile de surtout regarder le fichier munin-update.log. Les raisons peuvent être multiples, vérifiez que vous pouvez  réussir un telnet vers l’adresse IP sur le port 4949.(ne pas utiliser nmap).

 

telnet 91.111.111.110:4949

Si vous avez un message d’erreur, service inaccessible, il se peut qu’une règle du firewall empêche la transmission de données. Ou alors que le service node secondaire n’ai pas redémarré.

 

Certains processus sont invisibles

Il peut apparaitre que certains processus ne soient pas visibles après le démarrage de munin-node, j’ai eu le cas d’Apache non visible. Dans ce cas l’utilitaire munin-node-configure peut être utile.

Un service n’est pas présent? vous pouvez utiliser munin-node-configure pour voir la liste des services :

munin-node-configure #va donner la liste des plugin actifs et non actifs.

munin-node-configure  --suggest #va suggérer la liste des plugins à utiliser, et donne aussi un message sur la raison de la non activation.

Voici un cas réel de message suite à l’ajout du paramètre –suggest :

Plugin                     | Used | Suggestions
------                     | ---- | -----------
acpi                       | no   | no [cannot read /sys/class/thermal/thermal_zone*/temp]
amavis                     | no   | no
apache_accesses            | no   | no [apache server-status not found. check if mod_status is enabled]
apache_processes           | no   | no [apache server-status not found. check if mod_status is enabled]
apache_volume              | no   | no [apache server-status not found. check if mod_status is enabled]
apc_envunit_               | no   | no [no units to monitor]
bonding_err_               | yes  | yes (bond0)
courier_mta_mailqueue      | no   | no [spooldir not found]
courier_mta_mailstats      | no   | no [could not find executable]
courier_mta_mailvolume     | no   | no [could not find executable]
cps_                       | no   | no
cpu                        | yes  | yes
cpuspeed                   | no   | no [missing /sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state]
cupsys_pages               | no   | no [could not find logdir]
df                         | yes  | yes
df_inode                   | yes  | yes
diskstats                  | yes  | yes
entropy                    | yes  | yes
exim_mailqueue             | no   | no [no exiqgrep]
exim_mailstats             | no   | no ['/usr/sbin/exim -bP log_file_path' returned an error]
fail2ban                   | no   | no
forks                      | yes  | yes
fw_conntrack               | yes  | yes
fw_forwarded_local         | yes  | yes
fw_packets                 | yes  | yes
hddtemp_smartctl           | yes  | yes
http_loadtime              | yes  | yes
if_                        | yes  | yes (bond0 dummy0 eth0 ip6tnl0 tunl0)
if_err_                    | yes  | yes (bond0 dummy0 eth0 ip6tnl0 tunl0)
interrupts                 | yes  | yes
ip_                        | no   | no [could not run iptables as user nobody]
ipmi_                      | no   | no [missing ipmitool command]
irqstats                   | yes  | yes
load                       | yes  | yes
lpstat                     | no   | no [lpstat not found]
memory                     | yes  | yes
munin_stats                | no   | no [munin-update was not found at /usr/share/munin/munin-update]
mysql_                     | no   | no [Missing dependency Cache::Cache]
netstat                    | yes  | yes
nfs4_client                | yes  | yes
nfs_client                 | yes  | yes
nfsd                       | yes  | yes
nfsd4                      | yes  | yes
nginx_request              | no   | no [no nginx status on http://localhost/nginx_status]
nginx_status               | no   | no [no nginx status on http://localhost/nginx_status]
ntp_kernel_err             | no   | no
ntp_kernel_pll_freq        | no   | no
ntp_kernel_pll_off         | no   | no
ntp_offset                 | no   | no [no ntpq program]
ntp_states                 | no   | no [ntpq not found]
nvidia_                    | no   | no [no nvclock executable at /usr/bin/nvclock, please configure]
open_files                 | yes  | yes
open_inodes                | yes  | yes
pgbouncer_connections      | no   | no
pgbouncer_requests         | no   | no
postfix_mailqueue          | yes  | yes
postfix_mailvolume         | yes  | yes
postgres_autovacuum        | no   | no
postgres_bgwriter          | no   | no
postgres_cache_            | no   | no
postgres_checkpoints       | no   | no
postgres_connections_      | no   | no
postgres_connections_db    | no   | no
postgres_locks_            | no   | no
postgres_oldest_prepared_xact_ | no   | no
postgres_prepared_xacts_   | no   | no
postgres_querylength_      | no   | no
postgres_scans_            | no   | no
postgres_size_             | no   | no
postgres_transactions_     | no   | no
postgres_tuples_           | no   | no
postgres_users             | no   | no
postgres_xlog              | no   | no
proc                       | no   | no
proc_pri                   | yes  | yes
processes                  | yes  | yes
ps_                        | no   | no
qmailqstat                 | no   | no
selinux_avcstat            | no   | no [missing /selinux/avc/cache_stats file]
sendmail_mailqueue         | no   | no
sendmail_mailstats         | no   | no [no mailstats command]
sendmail_mailtraffic       | no   | no [no mailstats command]
slapd_                     | no   | no [IO::Socket::INET: connect: Connection refused]
slapd_bdb_cache_           | no   | no [Can't execute db_stat file '/usr/bin/db4.6_stat']
slony_lag_                 | no   | no
smart_                     | no   | no [no drives accessible]
snort_alerts               | no   | no [/var/snort/snort.stats not readable]
snort_bytes_pkt            | no   | no [/var/snort/snort.stats not readable]
snort_drop_rate            | no   | no [/var/snort/snort.stats not readable]
snort_pattern_match        | no   | no [/var/snort/snort.stats not readable]
snort_pkts                 | no   | no [/var/snort/snort.stats not readable]
snort_traffic              | no   | no [/var/snort/snort.stats not readable]
squeezebox_                | no   | no [no connection on localhost port 9090]
squid_cache                | no   | no [could not connect: Connection refused]
squid_objectsize           | no   | no [could not connect: Connection refused]
squid_requests             | no   | no [could not connect: Connection refused]
squid_traffic              | no   | no [could not connect: Connection refused]
swap                       | yes  | yes
threads                    | yes  | yes
uptime                     | yes  | yes
users                      | yes  | yes
varnish_                   | no   | no [varnishstat could not be found]
vmstat                     | yes  | yes
vserver_cpu_               | no   | no [/proc/virtual/info not found]
vserver_loadavg            | no   | no [/proc/virtual/info not found]
vserver_resources          | no   | no [/proc/virtual/info not found]
yum                        | no   | no [Could not find statefile.  Please read 'munindoc yum']
# The following plugins caused errors:
# fail2ban:
#       Junk printed to stderr
# pgbouncer_connections:
#       Junk printed to stderr
# pgbouncer_requests:
#       Junk printed to stderr
# postgres_autovacuum:
#       Non-zero exit during autoconf (255)
# postgres_bgwriter:
#       Non-zero exit during autoconf (255)
# postgres_cache_:
#       Non-zero exit during autoconf (255)
# postgres_checkpoints:
#       Non-zero exit during autoconf (255)
# postgres_connections_:
#       Non-zero exit during autoconf (255)
# postgres_connections_db:
#       Non-zero exit during autoconf (255)
# postgres_locks_:
#       Non-zero exit during autoconf (255)
# postgres_oldest_prepared_xact_:
#       Non-zero exit during autoconf (255)
# postgres_prepared_xacts_:
#       Non-zero exit during autoconf (255)
# postgres_querylength_:
#       Non-zero exit during autoconf (255)
# postgres_scans_:
#       Non-zero exit during autoconf (255)
# postgres_size_:
#       Non-zero exit during autoconf (255)
# postgres_transactions_:
#       Non-zero exit during autoconf (255)
# postgres_tuples_:
#       Non-zero exit during autoconf (255)
# postgres_users:
#       Non-zero exit during autoconf (255)
# postgres_xlog:
#       Non-zero exit during autoconf (255)
# proc:
#       In family 'auto' but doesn't have 'autoconf' capability
# slony_lag_:
#       Junk printed to stderr

Donc pour activer les affichage de Apache, il faut que mod_status soit activé, normalement c’est le cas. Il ne vous reste plus qu’à créer un lien symbolique linux dans le répertoire /etc/munin/plugins  vers un fichier du répertoire /usr/share/munin/plugins/

ln -s /usr/share/munin/plugins/apache_accesses apache_accesses
ln -s /usr/share/munin/plugins/apache_processes apache_processes
ln -s /usr/share/munin/plugins/apache_volume apache_volume

 

 

 

 

 

Retour en haut