mardi 1 octobre 2013

Purger la Transaction Log de SQL Server 2005

Il arrive des cas ou on doit purger la log des transactions SQL rapidement : disque saturé à cause d'updates massifs.
Voici comment effacer le fichier en urgence (peut fonctionner au delà de la version 2005, pas testé)

-- Database : nom de la base de  données
-- Logfile_name : nom du fichier log défini dans les propriétés de la base

USE Database
GO
DBCC SHRINKFILE(Logfile_name, 1)
BACKUP LOG Database WITH TRUNCATE_ONLY
DBCC SHRINKFILE(Logfile_name, 1)
GO

Enregistrer les résultats d'un scénario Jmeter dans une base MySQL

Dit comme cela ce n'a pas beaucoup d'intérêt, mais si on veut détourner JMeter de sa vocation première pour faire du monitoring de sites web ou de webservices... ça peut être utile !

L'idée est de remplacer le listener habituel par un script beanshell, à chaque itération le script va être executé et on va donc enregistrer le résultat de l'échantillon en base.

A noter que cette manip nécessite quand même "l'installation" du driver jdbc correspondant à votre version de MySQL dans JMeter (dans le dossier /lib de jmeter, normalement il est chargé automatiquement).

Voici le script :
//superformance.blogspot.com
import org.apache.jmeter.util.JMeterUtils;

import org.apache.jmeter.samplers.SampleResult;

import org.apache.jmeter.assertions.AssertionResult;



import java.sql.DriverManager;

import org.hsqldb.jdbcDriver;

import java.sql.SQLException;

import java.sql.*;



db_url = "jdbc:mysql://localhost/jmeter";

driver = "com.mysql.jdbc.Driver";

user = "jmeter";

password = "jmeter";



Class.forName(driver);

Connection con = DriverManager.getConnection(db_url,user,password);

try {



   long newlong = sampleResult.getStartTime();

   String str = Long.toString(newlong);

   String str3 = str.substring(0,(str.length()-3));

   long lts = Long.parseLong(str3);  



   PreparedStatement pstmt = con.prepareStatement("INSERT INTO test (name ,host ,resp_code ,resp_time, request_time, stamp, resp_size ) VALUES (?, ?, ?, ?,FROM_UNIXTIME(?),?, ? ) ");

   pstmt.setString(1, sampleResult.getSampleLabel() );

   pstmt.setString(2, sampleResult.getURL().getHost());

   pstmt.setString(3, sampleResult.getResponseCode() );

   pstmt.setLong(4, sampleResult.getTime() );

   pstmt.setLong(5,lts );



   pstmt.setLong(6,sampleResult.getStartTime() );

   pstmt.setInt(7,sampleResult.getBytes() );



   int i = pstmt.executeUpdate();

   print(i);

}

catch ( e ) {

   e.printStackTrace();

}

catch (SQLException s) {

  print(s.getSQLState());

}

finally {

  con.close();

}

lundi 9 septembre 2013

Php, ODBC et MSSQLSERVER

Grosse galère pour faire fonctionner le tout ensemble !

Voici un mix de plusieurs HOWTOs, car aucun ne fonctionnait pour moi jusqu'au bout
  1. Télécharger le SQL Server Native Client 11.0 on Linux ODBC Driver sur le site de Microsoft
  2. Suivre exactement la procédure décrite dans install instructions (attention nécessite impérativement unixODBC-2.3.0, il faudra peut être le downgrader)
  3. Vérifier la configuration odbc, le fichier /etc/odbcinst.ini doit contenir
  4. [SQL Server Native Client 11.0]
    Description=Microsoft SQL Server ODBC Driver V1.0 for Linux
    Driver=/opt/microsoft/sqlncli/lib64/libsqlncli-11.0.so.1790.0
    Threading=1
    UsageCount=1
  5. Tester !
    En shell (php nom_du_fichier.php) dans un premier temps pour valider que la conf de base fonctionne et que les accès sont ok.

    fichier test_odbc.php (si extention odbc)
  6. <?php
      $conn=odbc_connect("DRIVER={SQL Server Native Client 11.0};Server=IPADDRESS;Database=DATABASE","USERNAME","PASSWORD");
      $sql="SELECT 'OK' as test";
      $rs=odbc_exec($conn,$sql);
      odbc_fetch_row($rs);
      echo odbc_result($rs,"test");
    ?>
    
    fichier test_odbc_pdo.php  (si extention pdo_odbc)
    <?php
      $dbh= new PDO('odbc:DRIVER={SQL Server Native Client 11.0};Server=IPADDRESS;Database=DATABASE', 'username', 'password');
      $query = "SELECT 'OK' as test";
      $stmt = $dbh->prepare("$query");
      $stmt->execute();
      while ($row = $stmt->fetch()) {
          print_r($row["test"]);
      }
      unset($dbh); unset($stmt);
    ?>
    Les scripts PHP ci dessus doivent renvoyer "OK" Si tout fonctionne sinon... tout un tas d'erreurs ! Les problèmes les plus courants sont liés à l'authentification, vérifier la connexion dans SQL Server et qu'elle a des droits suffisants sur la base, (par défaut public n'est pas suffisant !)

dimanche 1 septembre 2013

Configurer Virtualbox pour être sur le même LAN que l'hôte

Par défaut Virtualbox est configuré en Mode NAT (translation d'adresse), ce qui  rend toutes les VM "étanches", car elles ne seront vues que par l'hôte.

Pour que les VM puissent être vues sur le LAN au même titre que l'hôte, il faut le configurer en mode BRIDGE. (cela installe une nouvelle carte réseau)

mercredi 28 août 2013

Une VM Linux en moins de 2

TurnkeyLinux est une distribution à base de Ubuntu (donc Debian) qui propose de télécharger des applications web (ou autres) sur un environnement linux prêt à l'emploi. On peut les monter directement chez Amazon ou bien télécharger des disques virtuels au format vmdk (vmware player ou Virtualbox)

Sinon on peut toujours télécharger le bon vieil iso, mais par défaut c'est la distribution 64 bits qui est proposé au téléchargement, pour avoir la version 32 bits il faut passer par le site de sourceforge: http://sourceforge.net/projects/turnkeylinux/files/iso/

Dans tous les cas, vmdk ou iso, le clavier sera configuré en américain (attention lors de la saisie du mot de passe root), pour le mettre en français il faut faire dans un shell :
apt-get install console-setup

Loadbalancing avec Apache

Le loadbalancing

En français : répartition de charge. On peut y avoir recours pour absorber une trop forte charge applicative, faire de la haute disponibilité, etc...

Les modules apache à charger

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
LoadModule proxy_connect_module modules/mod_proxy_connect.so

La configuration 

Dans l'exemple on a 4 serveurs frontaux 3 nominaux (192.168.1.1, 192.168.1.2 et 192.168.1.3) et 1 backup (192.168.1.4) désactivé par défaut.
On aura besoin d'un sticky session pour forcer le client à retourner toujours sur le même serveur. On peut se servir d'un cookie distribué par l'application ou en attribuer un d'office.
Ne pas oublier d'activer  l'interface d'administration qui permet entre autre de sortir un serveur du groupe.

#definition du groupe de serveurs
<Proxy balancer://load_test>
     BalancerMember http://192.168.1.1:8080/test loadfactor=33 route=serveur1  
     BalancerMember http://192.168.1.2:8080/test loadfactor=33 route=serveur2
     BalancerMember http://192.168.1.3:8080/test loadfactor=33 route=serveur3
     BalancerMember http://192.168.1.4:8080/test loadfactor=33 route=serveur4 status=D
</Proxy>

# stickysession
#Si Application java JSESSIONID
#Si application php  phpsessid
#sinon on cree un cookie contenant le nom du serveur
#Header add Set-Cookie "ROUTEID=.%{BALANCER_WORKER_ROUTE}e; path=/" env=BALANCER_ROUTE_CHANGED    

ProxyPass /test balancer://load_test stickysession=JSESSIONID|jsessionid nofailover=Off timeout=45 failonstatus=503

ProxyPassReverse /test http://192.168.1.1:8080/test
ProxyPassReverse /test http://192.168.1.2:8080/test
ProxyPassReverse /test http://192.168.1.3:8080/test
ProxyPassReverse /test http://192.168.1.4:8080/test

# definition de l'interface d'administration
<Location /balancer-manager>
    SetHandler balancer-manager
    Order Deny,Allow
    Allow from 127.0.0.1
</Location>

Parser de log Apache en Awk

Un petit script awk (1 ligne) pour afficher toutes les pages qui n'ont pas un code http 200 :

awk '{if ($9 != "200") {a[$7"$"$9]+=1} } END{for (i in a) {split(i,b,"$" ); print  a[i] " " b[1] " " b[2] " " } }'  /var/log/httpd/access_log

mardi 27 août 2013

Script de sauvegarde d'un profil Firefox

Quand je disais qu'on peut tout faire en batch !

 Voici un script qui permet de sauvegarder le profil firefox de chaque utilisateur. Pour être efficace, mieux vaut le mettre en ouverture de session, donc mettre un raccouci de ce script dans "all users\démarrage", nécéssite seulement 7zip (installé dans C:\Program Files\7-Zip\ sinon changer le chemin dans le script)

@echo off
rem
echo Backup Firefox profile
echo http://superformance.blogspot.com
rem
set datapath=%~dp0data\
Set counterfile=%datapath%%username%.txt
set logpath=%~dp0%log\
set outputpath=%datapath%%username%\

if not exist %datapath% mkdir %datapath%
if not exist %logpath% mkdir %logpath%
if not exist %outputpath% mkdir %outputpath%
for /f "tokens=2,3 delims=/ " %%a in ('echo %date%') do set logfile=%logpath%%%b-%%a-%username%.log

call :Logadd "Debut de %~nx0"

set counter=0
if exist %counterfile% for /f %%a in ('type %counterfile%') do set counter=%%a
if %counter% LSS 0 set counter=0
if %counter% GTR 15 set counter=0

set /a counter=counter+1
echo %counter% > %counterfile%
set outputfile=%outputpath%%username%-profile-%counter%.zip
if exist %outputfile% del %outputfile%

call :Logadd "Archive N° %counter%"

set ffoxpath=%appdata%\Mozilla\firefox\
if not exist %ffoxpath% goto :eof
for /f "tokens=2 delims==" %%a in ('type %ffoxpath%profiles.ini ^| find /i "path"') do set ffprofile=%ffoxpath%%%a

call :Logadd "Creation de l'Archive %outputfile%"

if exist %outputfile% del %outputfile%

"C:\Program Files\7-Zip\7z.exe" a -tzip %outputfile% %ffprofile%\
if %errorlevel% NEQ 0 call :Logadd "Erreur dans la Creation de l'archive"

call :Logadd "Fin de %~nx0"

goto :eof

:Logadd
Echo %date% - %time% - %~1
Echo %date% - %time% - %~1 >> %logfile%
goto :eof

Avoir les commandes Linux sous Windows

Il existe plusieurs solutions pour pouvoir disposer d'outils en ligne de commande sous Windows. La plus connue et la plus complète est certainement Cygwin qui inclut entre autres un compilateur.


Je préfère Unxutils, car plus léger et qui satisfait amplement  mes besoins (pas de problème de DLL, c'est compilé nativement sous windows)

Pour installer Unxutils

Décompresser le fichier ZIP dans un dossier

Pour utiliser Unxutils

On peut utiliser la plupart des commandes directement dans l'invite cmd.exe, pas besoin d'utiliser le shell sh.exe fourni.
On peut ajouter le dossier usr\local\wbin\ et bin\ dans la variable système PATH pour éviter d'avoir à spécifier le chemin systématiquement. Sinon on peut le faire à la demande, juste avant d'utiliser une commande Unxutils avec
set PATH=%PATH%;c:\unxutils\usr\local\wbin\;c:\unxutils\bin
Attention aux commandes qui portent le même nom et qui font des choses différentes :
  • Find (windows) équivalent à grep
  • Find (Unxutils) qui recherche des fichiers
Par défaut c'est la commande Windows qui sera prise en compte en premier, et il faudra spécifier le chemin complet de find.

Statistiques et charge Apache en live

Pour avoir un état de la santé d'apache, j'utilise 2 outils qui sont complémentaires:
  • apachetop
  • mod_status
Apachetop est un outil en ligne de commande qui permet de voir le top 50 des pages servies par apache, la bande passante, les codes http, etc.. Pour le lancer, il faut lui spécifier le chemin de l'accesslog d'apache (en fait cela dépend des distribs et/ou des options de compilation)

exemple:
Apachetop -f /var/log/httpd/access.log

Mod_status est lui plutôt rustique, pas beau, mais tellement efficace ! On consulte un rapport directement via un navigateur.
Si ce n'est pas déjà fait, il faut commencer par l'activer (loadmodule dans httpd.conf) et le configurer (SetHandler server-status et activer aussi ExtendedStatus tant qu'on y est toujours dans httpd.conf). Voir la doc apache ici pour plus de détails. Comme pour toute modification de configuration Apache, ne pas oublier de faire un restart.

Exemple de config

LoadModule status_module modules/mod_status.so

ExtendedStatus On

<Location /server-status>

     SetHandler server-status

     Order deny,allow

     Deny from all

     Allow from 127.0.0.1

</Location>
Attention : la config ci dessus utilise du filtrage IP, du coup la page n'est accessible que sur la machine locale. Pour sécuriser on peut aussi mettre un htaccess/htpasswd en plus.

Ensuite on se rend sur la page http://localhost/server-status (ou autre suivant la config) et on obtient la fameuse page de rapport.

La partie la plus intéressante du rapport est en rouge ci dessous (et aussi la plus difficile à interpréter) :

1 requests currently being processed, 149 idle workers
________________________________________________________________
________________________________________________________________
_____________________W
Scoreboard Key:
"_" Waiting for Connection, "S" Starting up, "R" Reading Request,
"W" Sending Reply, "K" Keepalive (read), "D" DNS Lookup,
"C" Closing connection, "L" Logging, "G" Gracefully finishing,
"I" Idle cleanup of worker, "." Open slot with no current process
On voit que le serveur n'est chargé ici, on a un maximum de symbole "_" et 1 seul "W" (normal je suis tout seul sur mon serveur !). En cas de problème de charge, c'est l'inverse ! très peu de "_" et beaucoup de "W",'R',"K" etc..
La solution à ce problème de charge est un peu au cas par cas, mais dans un premier temps, on peut augmenter facilement le nombre de workers Apache.

La puissance du batch (partie 1)

Le batch c'est quoi ?

C'est un langage interprété par cmd.exe (l’interpréteur de commandes). Le script est un fichier texte portant l’extension .bat ou .cmd, et qui contient une liste d'instructions. 
A l'heure du Powershell, ou vbscript, c'est vrai que le batch est désuet et de moins en moins utilisé. Malgré tout cela reste un outil puissant et portable (sur tous les systèmes Windows), avec lequel on peut  faire des choses assez surprenantes.

N'en déplaise aux puristes, je vais même aller jusqu'à dire que ce qu'on peut faire en shell bash, on peut aussi le faire en batch, mais pas aussi aisément.


Exemples

Parser un fichier csv
for /f "tokens=1,2 delims=;" %a in (fichier.csv) do echo %a %b
Ce que fait cette commande : affiche les colonnes 1 (variable %a) et 2 (variable %b) de fichier.csv dont le séparateur est ;

Récupérer le texte affiché par un programme dans une variable
for /f %a in (' date /t') do set date=%a
Ce que fait cette commande : exécute la commande date /t et stocke le résultat dans une variable %date%

lundi 26 août 2013

Au programme...


Ce blog sera dédié à l'informatique, vous y trouverez des tutoriaux et des astuces que j'emploie régulièrement, ainsi que mes dernières trouvailles dans le domaine.

Lowtech