Archives pour la catégorie ‘Développement’

PHP : optimisation du cache d’opérations sur les fichiers

# vim /etc/php5/fpm/php.ini
realpath_cache_size=1M
realpath_cache_ttl=300

Pour calculer une valeur précise, le script suivant peut être utile :

# vim /var/www/check_cache.php
<?php echo realpath_cache_size();

Drupal : optimisation du bootstrap sur des scripts backend

Script initial :

# vim /var/www/test1.php
<?php

require_once './includes/bootstrap.inc';

drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);

Version optimisée :

# vim /var/www/test2.php
<?php

require_once './includes/bootstrap.inc';
require_once './includes/common.inc';
require_once './includes/module.inc';

drupal_bootstrap(DRUPAL_BOOTSTRAP_CONFIGURATION); // minimal bootstrap

drupal_load('module', 'my_module');
module_invoke("my_module", "init");

L’impact au niveau du temps de chargement est conséquent :

# curl -o /dev/null -w%{time_total}\\n -s http://www.monsite.fr/test1.php
1.191
# curl -o /dev/null -w%{time_total}\\n -s http://www.monsite.fr/test2.php
0.240

GitLab : désactiver les dépôts publics

# vim ~/config/gitlab.yml
   # Restrict setting visibility levels for non-admin users.
   # The default is to allow all levels.
   restricted_visibility_levels: [ "public", "internal" ]

   ## Default project features settings
   default_projects_features:
      issues: true
      merge_requests: true
      wiki: true
      wall: false
      snippets: false
      visibility_level: "private"  # can be "private" | "internal" | "public"

PHP-FPM : effectuer un strace en live

# ps auxw | grep php | awk '{print"-p " $2}' | xargs strace

Git : squasher des commits (fusion)

Le squash de commit consiste à fusionner plusieurs commits antérieurs en un seul commit.

Pour ce faire, il faut préalablement s’assurer que le dépôt local est clean :

# git status

Pour squasher les deux derniers commits, on se positionne à l’état ultérieur à ceux-ci :

# git reset --hard HEAD~2

Et on merge à partir du niveau +1 jusqu’au début :

# git merge --squash HEAD@{1}
# git commit

Node.js : template de script de démarrage init.d

#! /bin/sh
### BEGIN INIT INFO
# Provides:          app
# Required-Start:    $remote_fs $syslog $network
# Required-Stop:     $remote_fs $syslog $network
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: app
# Description:       app startup script
### END INIT INFO

# Author: Boris HUISGEN <bhuisgen@hbis.fr>

PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin
DESC="app"
NAME=app
DAEMON=/usr/local/bin/node
USER=app
GROUP=app
LOGFILE=/var/log/app/app.log
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME

NODEAPP_DIR=/home/app/
NODEAPP_SCRIPT="app.js"

[ -x "$DAEMON" ] || exit 0

[ -r /etc/default/$NAME ] && . /etc/default/$NAME

. /lib/init/vars.sh
. /lib/lsb/init-functions

do_start()
{
	start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test \
		> /dev/null || return 1
	start-stop-daemon --start --quiet --make-pidfile --pidfile $PIDFILE \
		--exec $DAEMON --chdir $NODEAPP_DIR --chuid $USER:$GROUP \
		--background -- $NODEAPP_SCRIPT >> $LOGFILE 2>&1 || return 2
}

do_stop()
{
        start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE
        RETVAL="$?"
        [ "$RETVAL" = 2 ] && return 2

        start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --pidfile $PIDFILE
        [ "$?" = 2 ] && return 2

	rm -f $PIDFILE
	return "$RETVAL"
}

case "$1" in
  start)
	[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
	do_start
	case "$?" in
		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
	esac
	;;
  stop)
	[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
	do_stop
	case "$?" in
		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
	esac
	;;
  status)
	status_of_proc -p $PIDFILE "$DAEMON" "$NAME" && exit 0 || exit $?
	;;
  restart|force-reload)
	log_daemon_msg "Restarting $DESC" "$NAME"
	do_stop
	case "$?" in
	  0|1)
		do_start
		case "$?" in
			0) log_end_msg 0 ;;
			1) log_end_msg 1 ;;
			*) log_end_msg 1 ;;
		esac
		;;
	  *)
		log_end_msg 1
		;;
	esac
	;;
  *)
	echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
	exit 3
	;;
esac

:

Iptables : redirection de port pour une application Node.js / Express

*nat
:PREROUTING ACCEPT [7281:438725]
:POSTROUTING ACCEPT [1652:103194]
:OUTPUT ACCEPT [1652:103194]
-A PREROUTING -d 80.80.80.80/32 -p tcp -m tcp --dport 80 -j DNAT --to-destination :3000 
-A OUTPUT -o lo -p tcp -m tcp --dport 80 -j REDIRECT --to-ports 3000
COMMIT
*filter
:INPUT ACCEPT [184:13033]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [46937:6349034]
-A INPUT -d 80.80.80.80/32 -m state --state NEW -p tcp --dport 3000 -j ACCEPT 
-A INPUT -j DROP
-A FORWARD -j DROP
COMMIT

Nginx : exécution FastCGI Perl

Je vous joins ici la dernière version des scripts que j’utilise pour permettre l’exécution Perl en FastCGI avec Nginx (pour SmokePing, BackupPC, etc …)

Le script du démon Perl fcgi-perl.pl est à adapter à votre environnement système (utilisateur d’exécution, chemin de la socket UNIX). Le script de démarrage est à présent intégrable avec Heartbeat/Corosync …

Dépendances logicielles

root@muse:~# aptitude install libfcgi-perl libfile-pid-perl

Script FastCGI Perl

root@muse:~# cat /etc/nginx/fcgi-perl.pl
#!/usr/bin/perl
#
# FastCGI perl daemon
#
# Boris HUISGEN <bhuisgen@hbis.fr>
#

my ($pid_file) = "/var/run/fcgi-perl.pid";       # PID filename
my ($socket_file) = "/var/run/fcgi-perl.sock";   # UNIX socket filename
my ($socket_backlog) = 10;                       # socket backlog
my ($socket_uid) = 33;                           # socket UID
my ($socket_gid) = 33;                           # socket GID
my ($socket_perms) = 0600;                       # socket permissions

#
# script
#

use File::Pid;
use FCGI;
use Socket;
use POSIX qw(setsid);

require 'syscall.ph';

my ($pid_fd);

&daemonize;

*CORE::GLOBAL::exit = sub { die "fakeexit\nrc=".shift()."\n"; };
eval q{exit};
if ($@) {
   exit unless $@ =~ /^fakeexit/;
};

&main;

sub cleanup() {
   $pid_fd->remove if defined $pid_fd;
   unlink($socket_file);
}

sub daemonize() {
   chdir '/' or die "Failed to chdir to /: $!";
   defined(my $pid = fork) or die "Failed to fork: $!";
   exit if $pid;
   setsid or die "Failed to start a new session: $!";
   umask 0022;

   $pid_fd = File::Pid->new({
      file => $pid_file,
   });

   if ($pid_fd->running) { die "Instance already running" };

   $pid_fd->write;
}

sub main {
   $socket = FCGI::OpenSocket($socket_file, $socket_backlog);
   $request = FCGI::Request(\*STDIN, \*STDOUT, \*STDERR, \%req_params, $socket);

   chown($socket_uid, $socket_gid, $socket_file);
   chmod($socket_perms, $socket_file);

   if ($request) {
      request_loop()
   };

   FCGI::CloseSocket($socket);
}

sub request_loop {
   while($request->Accept() >= 0) {

      $stdin_passthrough ='';
      $req_len = 0 + $req_params{'CONTENT_LENGTH'};
      if (($req_params{'REQUEST_METHOD'} eq 'POST') && ($req_len != 0) ){
         my $bytes_read = 0;
         while ($bytes_read < $req_len) {
            my $data = '';
            my $bytes = read(STDIN, $data, ($req_len - $bytes_read));
            last if ($bytes == 0 || !defined($bytes));
            $stdin_passthrough .= $data;
            $bytes_read += $bytes;
         }
      }

      if ( (-x $req_params{SCRIPT_FILENAME}) &&
           (-s $req_params{SCRIPT_FILENAME}) &&
           (-r $req_params{SCRIPT_FILENAME}) ){
         pipe(CHILD_RD, PARENT_WR);
	 my $pid = open(KID_TO_READ, "-|");
         unless(defined($pid)) {
            print "Content-type: text/plain\r\n\r\n";
            print "Error: CGI app returned no output - Executing $req_params{SCRIPT_FILENAME} failed !\n";
            next;
         }

         if ($pid > 0) {
            close(CHILD_RD);
            print PARENT_WR $stdin_passthrough;
            close(PARENT_WR);

	    while(my $s = <KID_TO_READ>) { print $s; }
	    close KID_TO_READ;
	    waitpid($pid, 0);
	 } else {
            foreach $key ( keys %req_params){
               $ENV{$key} = $req_params{$key};
            }

            if ($req_params{SCRIPT_FILENAME} =~ /^(.*)\/[^\/]+$/) {
               chdir $1;
            }

	    close(PARENT_WR);
	    close(STDIN);
	    #fcntl(CHILD_RD, F_DUPFD, 0);
	    syscall(&SYS_dup2, fileno(CHILD_RD), 0);
	    #open(STDIN, "<&CHILD_RD");
	    exec($req_params{SCRIPT_FILENAME});
	    die("exec failed");
	}
     }
     else {
        print "Content-type: text/plain\r\n\r\n";
        print "Error: No such CGI app - $req_params{SCRIPT_FILENAME} may not exist or is not executable by this process.\n";
     }
  }
}

END {
   $pid_fd->remove if defined $pid_fd;
   unlink($socket_file);
}

Script de démarrage init.d

root@muse:~# cat /etc/init.d/fcgi-perl
#! /bin/sh
### BEGIN INIT INFO
# Provides:          fcgi-perl
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: fcgi-perl
# Description:       start the fcgi-perl daemon
### END INIT INFO

# Author: Boris HUISGEN <bhuisgen@hbis.fr>

PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC=fcgi-perl
NAME=fcgi-perl

DAEMON=/etc/nginx/$NAME.pl
PIDFILE=/var/run/fcgi-perl.pid
SOCKETFILE=/var/run/fcgi-perl.sock

[ -x "$DAEMON" ] || exit 0

[ -r /etc/default/$NAME ] && . /etc/default/$NAME

. /lib/init/vars.sh
. /lib/lsb/init-functions

do_start()
{
	[ -e $PIDFILE ] && return 1

	echo "Starting $PROVIDES..."
	$DAEMON &

	[ ! -e $PIDFILE ] && sleep 1
	[ ! -e $PIDFILE ] && return 2

	return 0
}

do_stop()
{
	[ ! -e $PIDFILE ] && return 1

	echo "Stopping $PROVIDES..."
	kill `cat $PIDFILE`

	rm -f $PIDFILE
	rm -f $SOCKETFILE

	return 0
}

case "$1" in
  start)
	[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
	do_start
	case "$?" in
		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
	esac
	;;
  stop)
	[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
	do_stop
	case "$?" in
		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
	esac
	;;
  status)
       status_of_proc -p $PIDFILE "$DAEMON" "$NAME" && exit 0 || exit $?
       ;;
  restart)
	log_daemon_msg "Restarting $DESC" "$NAME"
	do_stop
	case "$?" in
	  0|1)
		do_start
		case "$?" in
			0) log_end_msg 0 ;;
			1) log_end_msg 1 ;;
			*) log_end_msg 1 ;;
		esac
		;;
	  *)
		log_end_msg 1
		;;
	esac
	;;
  *)
	echo "Usage: $SCRIPTNAME {start|stop|status|restart}" >&2
	exit 3
	;;
esac

:

Configuration Nginx

server {
   listen 80;
   server_name localhost;

   location / {
      root /var/www/default;
      index index.cgi index.html;
   }

   location ~ \.cgi$ {
      fastcgi_pass unix:/var/run/fcgi-perl.sock;
      fastcgi_index index.cgi;
      fastcgi_param HTTP_ACCEPT_ENCODING gzip,deflate;
      include fastcgi_params;
   }
}

gted : plugin Eclipse d’édition de fichiers Gettext

Gted est un éditeur de fichiers Gettext s’intégrant à l’IDE Eclipse.

Site web : http://www.gted.org/

Ant : génération d’un bundle OSGI avec bnd

Bnd : https://bndtools.ci.cloudbees.com/job/bnd.master/ws/biz.aQute.bnd/generated/

bhuisgen@muse:~/Projects/java/libirc$ cat build.xml
<target name="dist" depends="doc" description="create package">
   <!-- JAR package -->
   <mkdir dir="${dist.home}/bin/${ant.project.name}" />
   <copy todir="${dist.home}/bin/${ant.project.name}">
      <fileset dir="${build.home}" />
   </copy>
   <jar destfile="${dist.home}/${ant.project.name}-${build.version}-bin-${DSTAMP}.jar" basedir="${dist.home}/bin/" />

   <!-- OSGI bundle -->
   <replaceregexp file="myfile.bnd" match="Bundle-Version: (.*)" replace="Bundle-Version: ${build.version}" byline="true" />
   <taskdef resource="aQute/bnd/ant/taskdef.properties" classpath="${lib.home}/bnd-2.0.0.jar"/>
   <bnd classpath="${build.home}" files="myfile.bnd" output="${dist.home}/${ant.project.name}-${build.version}-bundle-${DSTAMP}.jar" />
</target>
bhuisgen@muse:~/Projects/java/libirc$ cat libirc.bnd
Bundle-Name: IRC Client Framework Bundle
Bundle-SymbolicName: fr.hbis.lib.irc
Bundle-Version: 0.2.0

Private-Package: fr.hbis.lib.irc.*
Haut de page