Ignore a word in a regular expression

Today a friend of mine asked me a tricky regexp related question: he wanted to match against a set of strings like:

WORD_FOO
WORD_BAR
WORD_FOOBAR
WORD_QUUX
WORD_FAR

He did want to match and store any string starting with WORD_ and followed by a valid word, unless it was FOO. So it should match all the aforementioned lines but WORD_FOO.

Tricky.

He was using something like /^(WORD_[^\s]+)$/, so I suggested using [^\s|VERSION] (I did wake up only a few moments before), but of course that doesn’t work, since it would exclude all strings containing the characters V, E, R, S, I, O, N.

It took me some digging, but finally I found this answer on StackOverflow that documents the use of negative look-arounds.

Using these constructs I managed to get this regex: WORD_((?!FOO\W)\S+) that satisfies the requirements (you can check it on Rubular).

How does it work?

(?!FOO\W) checks the next characters of the string. If they DON’T (!) contain the word FOO followed by a non-word (whitespace, etc) character (\W), then the matching will be made against \S+ (one or more non whitespace characters). So you’ll get the second part of the word in your \1, $1, etc.

If you want to ignore all sub-strings starting with FOO, you can get rid of that \W.

Advertisements

OTRS Apache + mod_perl configuration on Debian/Ubuntu

Today I installed OTRS trouble ticketing system for a test (we’re evaluating different solutions). OTRS documentation is quite good, but the installation section could be more accurate.

Since it required to me a lot of searching and some mashing up between the contrib file from OTRS project and some examples found on the Internet, I want to share my configuration for Apache on Ubuntu (but it should work on Debian also). I changed the default vhost /etc/apache2/sites-available/default to:

<VirtualHost *:80>  
  ServerAdmin otrs@example.org
  DocumentRoot /opt/  

  <Directory />    
    Options FollowSymLinks    
    AllowOverride None  
  </Directory>

  # agent, admin and customer frontend  
  ScriptAlias /otrs/ "/opt/otrs/bin/cgi-bin/"  
  Alias /otrs-web/ "/opt/otrs/var/httpd/htdocs/"

  # load perl modules  
  <IfModule mod_perl.c>
    Perlrequire /opt/otrs/scripts/apache2-perl-startup.pl
    PerlModule Apache2::Reload    
    PerlInitHandler Apache2::Reload    
    PerlModule Apache2::RequestRec  
  </IfModule>

  # fallback to index.pl  
  <Location /otrs>    
    ErrorDocument 403 /otrs/index.pl    
    DirectoryIndex index.pl  
  </Location>

  # activate CGI/mod_perl for perl files  
  <LocationMatch /otrs/.*\.pl>    
    Options +ExecCGI    
    SetHandler cgi-script    
    Order allow,deny    
    Allow from all

    <IfModule mod_perl.c>      
      SetHandler perl-script      
      PerlHandler ModPerl::Registry      
      PerlOptions +ParseHeaders      
      PerlOptions +SetupEnv    
    </IfModule>

  </LocationMatch>

  # directory settings  
  <Directory "/opt/otrs/bin/cgi-bin/">    
    AllowOverride None    
    Options +ExecCGI -Includes    
    Order allow,deny    
    Allow from all  
  </Directory>

  <Directory "/opt/otrs/var/httpd/htdocs/">    
    AllowOverride None    
    Order allow,deny    
    Allow from all  
  </Directory>

  <IfModule mod_headers.c>    
    <Directory "/opt/otrs/var/httpd/htdocs/skins/*/*/css-cache">      
      <FilesMatch "\.(css|CSS)$">        
        Header set Cache-Control "max-age=2592000 must-revalidate"      
      </FilesMatch>    
    </Directory>

    <Directory "/opt/otrs/var/httpd/htdocs/js/js-cache">      
      <FilesMatch "\.(js|JS)$">        
        Header set Cache-Control "max-age=2592000 must-revalidate"      
      </FilesMatch>    
    </Directory>  
  </IfModule>

  ErrorLog /var/log/apache2/otrs_error.log  LogLevel warn

  CustomLog /var/log/apache2/otrs_access.log combined

</VirtualHost>

Running an external process from Ruby

Running an external process from a Ruby script is quite easy: use backticks (output = `command`) or the %x method (output = %x[command]).

There are more options like system and exec and even more advanced ones like popen, popen3 and popen4 that allow you to manage process stdin/stdout/stderr.

A good resource with more examples is Nate Murray’s 6 Ways to Run Shell Commands in Ruby.

Find packages starting with a string with apt or aptitude

Searching for packages with apt-cache or aptitude is quite easy, but what if we want to find a package name starting with a specific string? With apt-cache:

$ apt-cache search mysql | grep '^mysql'
mysql-cluster-client - MySQL database client (metapackage)
mysql-mmm-agent - Multi-Master Replication Manager for MySQL - agent daemon
mysql-mmm-common - Multi-Master Replication Manager for MySQL - common files
mysql-mmm-monitor - Multi-Master Replication Manager for MySQL - monitoring daemon
mysql-mmm-tools - Multi-Master Replication Manager for MySQL - tools

With aptitude:

$ aptitude search ^mysql
p   mysql-admin  - GUI tool for intuitive MySQL administration
p   mysql-client  - MySQL database client (metapackage)                              
v   mysql-client-4.1  - 
p   mysql-client-5.1  - MySQL database client binaries
i A mysql-client-core-5.1  - MySQL database core client binaries
[...]

JMeter e il load testing che vorrei

Questo è un rant. Ve lo dico subito, così potete non leggerlo.

In questo post voglio lamentarmi di JMeter, non perché sia un cattivo strumento di load testing, anzi, è sicuramente il migliore del panorama open. Il problema è che non è abbastanza.

La complessità delle web application moderne è tale che i test di carico basati su banali sequenze di URL richiamate in serie non garantisce affatto un risultato credibile.

Un tool moderno dovrebbe essere in grado di generare “modelli di comportamento degli utenti”, in modo da poter testare carichi reali delle web app, sia partendo da una singola navigazione (con analisi dei possibili comportamenti applicabili in una pagina), sia estrapolando i modelli da log già esistenti di utilizzo. Inoltre, dovrebbe permettere di emulare automaticamente i comportamenti del browser riguardo al caricamento di immagini, css, js, etc. Ad esempio:

  • l’utente effettua il login alla webmail (load della pagina di login e tutti gli elementi correlati, chiamata POST per il login, caricamento dell’interfaccia della webmail e relativi elementi correlati)
  • l’utente controlla la inbox e clicca su uno dei messaggi (chiamata GET o AJAX per spostarsi alla visualizzazione del singolo messaggio)
  • l’utente risponde al messaggio (ancora, chiamata GET o AJAX per caricare l’interfaccia di composizione del messaggio; all’interno di tale interfaccia potrebbero essere presenti altre chiamate al server, ad esempio per l’auto-completion nel campo degli indirizzi)
  • l’utente invia il messaggio di risposta, viene ricaricata la inbox (chiamata POST o AJAX che implica anche un test di carico per il server di posta, chiamata GET o AJAX per ricaricare la inbox)
  • l’utente effettua il logout (chiamata GET o AJAX, caricamento della pagina di saluto)

Il tool, sostanzialmente, dovrebbe essere in grado di ricostruire le interfacce tra i vari elementi della web app e permettere di costruire i modelli di comportamento senza tener conto dell’implementazione spicciola, ma lavorando su concetti più ad alto livello.

Poi, per replicare un carico reale della piattaforma, si potrebbero creare diversi gruppi a cui applicare diversi comportamenti (ma questo si può già fare con JMeter).

Con una base del genere, poi si potrebbe iniziare a sperimentare sul serio, per misurare le prestazioni del sistema in casi che ancora non si sono verificati (es. pubblicazione in homepage di qualche grosso portale ed “effetto slashdot”, pubblicazione di una news “virale” o vero e proprio attacco virale (facebook worms) alla piattaforma per cui la condivisione tra utenti cresce esponenzialmente, etc).