Flyerenv

03 mai 2006

screen

Tips pour screen : nommer ses session

#démarre une session nommée flyer
$> screen -S flyer
#CTRL+d a pour quitter la session

#voir les sessions en cours:
$> screen -list
There is a screen on:
19140.flyer (Detached)

#reprendre la session flyer
$> screen -r flyer

iconv

Un wrapper c++ pour iconv:


#include
using namespace std;

#include
#include

#define CODAGE_NATIF "ISO-8859-15"
#define CODAGE_XML "UTF-8"

int ppIconv(const std::string &pSource,
const std::string &pFrom_charset,
const std::string &pTo_charset,
std::string &pDestination) {

int retour=0;
char *s = (char *)pSource.c_str();
iconv_t cd = iconv_open(pTo_charset.c_str(), pFrom_charset.c_str());
if (cd != (iconv_t) (-1)) {
size_t s_len = pSource.length();
/* the maximum expansion when converting happens when converting
tscii to utf-8; each tscii char can become up to 4 unicode chars
and each one of those unicode chars can be 3 bytes long */
size_t ptr_len = 4 * 3 * s_len;
//alloca alloue sur la pile, la désallocation se fera
//automatiquement au retour de ppIconv
char *buf = (char *)alloca(ptr_len);
char *ptr = buf;
if ((iconv(cd, &s, &s_len, &ptr, &ptr_len)) != (size_t) (-1)) {
*ptr = 0;
pDestination = buf;
retour=true;
}
iconv_close(cd);
}
if(!retour)
pDestination="";
return retour;
}

19 avril 2006

port forward avec netfilter

Voici comment faire un port forward + masquerade avec netfilter (sous linux à priori donc):
  • iptables -F FORWARD
  • iptables -A FORWARD -j ACCEPT
  • iptables -F -t nat
  • iptables -A POSTROUTING -t nat -o eth99 -j MASQUERADE
  • iptables -A PREROUTING -t nat -p tcp --dport 9999 -j DNAT --to 192.168.99.99:9999
  • echo 1 > /proc/sys/net/ipv4/ip_forward

DummyNet


Aujourd'hui on installe FreeBSD et on utilise DummyNet pour ajouter du temps de latence aux paquets IP et limiter la bande passante.
"dummynet is a flexible tool originally designed for testing networking protocols, and since then (mis)used for bandwidth management."

L'outil était prévu pour tester les protocols et quelqu'un a rajouté (sans doute à l'arrache) le controle de bande passante. Par conséquent ce n'est sans doute pas le meilleur outil mais il a le mérite d'être le plus simple que j'ai trouvé.

J'aurais préféré utiliser netem sous linux hélas ce dernier ne traite que le flux sortant. Il faut jouer des pieds et des mains pour lui faire traiter les flûx entrant et sortant.

Notons enfin l'article de Wikipedia sur le sujet: "Network Emulation".

L'installation de FreeBSD est facile mais en mode texte et demande quelques connaissances informatiques. J'ai installé la version 6.1 RC1 par FTP au travers d'un proxy HTTP. C'est plus rapide de télécharger les 24Mo du CD-Rom d'installation minimaliste et de faire l'installation par FTP que de télécharger les ISO complètes.

Une fois installé il faut activer le firewall. Dans /etc/rc.conf ajouter les lignes:
  • firewall_enable="YES"
  • firewall_type="open"
  • gateway_enable="YES" #si besoin
... et rebooter. Je n'ai pas cherché les commandes qui permettrait de ne pas rebooter (sans doute sysctl).

En "pingant" la machine j'obtient moins de 1ms sur un réseau 100Mbits avec un taux de transfert de 8Mo/s : une situation normale.

Il faut déjà recompiler le kernel :) Rien d'étonant pour FreeBSD puisque la section "Common Tasks" du Handbook contient un paragraphe "Building and Installing a Custom Kernel". Ca m'amuse de trouver la recompilation du kernel dans la section "Tâches courante" :)

Si comme moi vous n'aviez pas installé les sources du kernel il faut utiliser sysinstall (menu Configure > Distributions > src > sys) pour installer le paquet manquant.

Copier le fichier /usr/src/sys/i386/conf/GENERIC dans /usr/src/sys/i386/conf/MYKERNEL, puis rajouter les lignes:
  • options IPFIREWALL
  • options IPFIREWALL_DEFAULT_TO_ACCEPT
  • options IPFIREWALL_FORWARD
  • options IPFIREWALL_VERBOSE
  • options IPFIREWALL_VERBOSE_LIMIT=100
  • options DUMMYNET
  • options IPDIVERT
Puis lancer:
  • cd /usr/src/sys/i386/conf
  • /usr/sbin/config MYKERNEL
  • cd ../compile/MYKERNEL
  • make cleandepend #si nécessaire
  • make depend && make && make install
Un petit reboot plus tard (dans un /etc/rc.local par exemple):
  • sysctl net.inet.ip.fw.one_pass=0
  • natd -interface rl0 -redirect_port tcp super.host.com:8888 9999 #on redirige le port 9999 de notre machine vers super.host.com:8888
  • /sbin/ipfw -f flush
  • /sbin/ipfw add pipe 1 ip from any to any
  • /sbin/ipfw pipe 1 config bw 128Kbits/s queue 10 delay 200ms
  • /sbin/ipfw add divert natd ip from any to any
et voilà tout les accès IP à votre machine (même le localhost) sont limités à 128Kbits/s avec une latence de 200ms. On obtient donc un ping de 400ms et un taux de transfert approximatif de 12Ko/s. La machine peut maintenant être utilisée pour filtrer les accès à super.host.com:9999.

D'autres paramètres peuvent être changé avec DummyNet comme un pourcentage de perte de paquets, de paquets désordonnés, de paquets corrompu ou encore de parquets doublés. On peu aussi simuler des routes variables.

12 avril 2006

Le dernier jour en shell

Q: Comment trouver le numéro du dernier jour du mois en shell?
R: Le dernier jour de février 2008 est le jour n°:
cal 2 2008 | grep -v "^$" | tail -1 | awk '{print $NF}'

Envoyer un mail HTML en Shell

Vous avez un super script CGI qui produit une super page HTML. Vous souhaiter envoyer cette page HTML par mail. Voici comment faire:


( echo "From: michel.martin@laposte.net"
echo "To: odette.martin@laposte.net"
echo "Subject: Le menu du soir"
echo "Content-type: text/html"
echo
/var/www/cgi-bin/mon_super_script.cgi | tail +3
) | /usr/sbin/sendmail -oi -t

07 avril 2006

Practical Extraction and Report Language

Après Bash (utile pour traiter les noms de fichiers et leurs emplacements), voici Perl un langage très pratique et aussi barbare pour traiter le contenu des fichiers.

Voici donc un scipts exemple pour mémoire (vous l'avez compris ce blog me sert surtout comme assistant de mémoire personnelle).

# lancer cpan
perl -MCPAN -e 'shell'

#!/usr/bin/perl

# pour avoir les fonction starthtml, h3...
use CGI qw(:standard);

# pour avoir les erreurs et warnings dans le navigateur web
use CGI::Carp qw(warningsToBrowser fatalsToBrowser);

#pour faire des GET HTTP
use LWP::Simple;

#pour les connexions BDD

use DBI;

#C'est toujours mieux
use strict;
use warnings;

#Ca c'est de la balle, vous comprenez ce que ça fait?
eval get "http://foo.bar/programme.pl";

#encore de la balle, avoir une liste d'éléments uniques à partir d'une liste d'éléments non uniques
my %seen;
my @uniqed = grep !$seen{$_}++, @list;


#Un tri selon 2 clés d'un tableau de hashtables
@clients = sort { $::a->{"nom"} cmp $::b->{"nom"}
or $::a->{"type"} cmp $::b->{"type"}
} @clients;


print header();
print start_html(-title=>'Deadlines',
-style=>{'src'=>'/styles.css'});

#un trim
sub trim {
my $string = shift;
for ($string) {
s/^\s+//;
s/\s+$//;
}
return $string;
}


#Une fonction qui découpe une chaine en sous-chaine de taille égale
sub split_chunks
{
my $texte = shift(@_);
my $taille_chunk = shift(@_);

my @chunks;

while( length($texte)>0 ){
if( length($texte)<$taille_chunk ){
push @chunks, $texte;
$texte="";
}
else{
push @chunks, substr($texte,0,$taille_chunk);
$texte = substr($texte,$taille_chunk);
}
}
return @chunks;
}




#Des jolies fonctions pour créer de beau tableaux

sub tableau
{
print "<p><table cellpadding=\"2px\" cellspacing=\"0\">\n";
}

sub tableau_end
{
print "</table></p>\n";
}

sub entete_colonne
{
my $tmp=shift;
my $align=shift;
$align="center" unless $align;
print "<th align=\"$align\" class=\"HdrClmn\">$tmp</th>\n";
}

sub entete_colonne_end
{
my $tmp=shift;
my $align=shift;
print "<th align=\"$align\" class=\"HdrClmnEnd\">$tmp</th>\n";
}

sub ligne
{
print "<tr>\n";
}

my $couleur="row1";
sub ligne_end
{
if( $couleur eq "row0" ){
$couleur="row1";
}
else{
$couleur="row0";
}
print "</tr>\n";
}

sub colonne
{
my $tmp=shift;
my $align=shift;
$align="left" unless $align;
if( !$tmp or $tmp eq "" ){
$tmp=" " unless $tmp;
}
print "<td align=\"$align\" style=\"border-right: 1px solid black\" class=\"$couleur\">$tmp</td>\n";
}


sub colonne_end
{
my $tmp=shift;
my $align=shift;
$align="left" unless $align;
if( !$tmp or $tmp eq "" ){
$tmp=" " unless $tmp;
}
print "<td align=\"$align\" class=\"$couleur\">$tmp</td>\n";
}


#exmples de connexion BDD
$ENV{'ORACLE_HOME'} ="/oracle/8.1.7";
$ENV{'NLS_LANG'} = "french_france.we8iso8859p1";
$ENV{'LD_LIBRARY_PATH'}="/oracle/8.1.7/lib:/usr/local/lib";

my $dbh = = DBI->connect("DBI:Oracle:montns", "login", "pass", {AutoCommit => 0 } ) or die "$DBI::errstr\n";

#mettre "DBI:mysql:mabdd" pour une connexion Mysql et enlever le dernier paramètre


my $select = $dbh->prepare("select champ1,champ2
from table1
where champ3=? and champ4=? ") or die "$DBI::errstr\n";

$select->execute("var1","var2");

while( ($var1,$var2) = $select->fetchrow() ){

}
#y a aussi $select->finish() si on va pas au bout du fetchrow()

$select->commit(); # ou rollback
$dbh->disconnect();


#Les formulaires
print start_form("POST");
print textarea("nom","contenu",hauteur,largeur);
print submit('envoyer','envoyer');
print checkbox("nom",bool_checked,"valeur","libelle");
print endform;