Archives pour mars, 2011

Linux : script de vérification des périphériques RAID

Ce script shell permet de lancer une vérification des périphériques RAID (mdadm). Il est largement inspiré du script checkarray écrit par Martin F. Krafft (intégré à la distribution Debian).

#!/bin/sh
#
# mdcheck.sh
#
# Boris HUISGEN <bhuisgen@hbis.fr>
#

set -eu
PROGNAME=${0##*/}
VERSION="0.1-20010328"

usage()
{
 echo
 echo "Usage: $PROGNAME [OPTIONS] [ARRAY ...]"
 echo
 echo "Options:"
 cat <<EOF | column -s\& -t
    -a|--all & check all assembled arrays.
    -s|--status & show status of arrays.
    -x|--cancel & cancel a running redundancy check.
    -h|--help & show this output.
    -v|--version & show version information.
 EOF
 echo
}

version()
{
 echo "$PROGNAME version $VERSION"
}

SHORTOPTS=asxhv
LONGOPTS=all,status,cancel,help,version

eval set -- $(getopt -o $SHORTOPTS -l $LONGOPTS -n $PROGNAME -- "$@")

arrays=''
all=0
status=0
action=check

for opt in $@; do
 case "$opt" in
 -a|--all) all=1;;
 -s|--status) action=status;;
 -x|--cancel) action=idle;;
 -h|--help) usage; exit 0;;
 -v|--version) version; exit 0;;
 /dev/md/*|md/*) arrays="${arrays:+$arrays }md${opt#*md/}";;
 /dev/md*|md*) arrays="${arrays:+$arrays }${opt#/dev/}";;
 /sys/block/md*) arrays="${arrays:+$arrays }${opt#/sys/block/}";;
 --) :;;
 *) echo "$PROGNAME: invalid option: $opt" >&2; usage; exit 0;;
 esac
done

if [ ! -f /proc/mdstat ]; then
 echo "$PROGNAME: MD subsystem not loaded, or /proc unavailable." >&2
 exit 1
fi

if [ ! -d /sys/block ]; then
 echo "$PROGNAME: /sys filesystem not available." >&2
 exit 2
fi

if [ -z "$(ls /sys/block/md* 2>/dev/null)" ]; then
 echo "$PROGNAME: no active MD arrays found." >&2
 exit 3
fi

if [ -z "$(ls /sys/block/md*/md/level 2>/dev/null)" ]; then
 echo "$PROGNAME: kernel too old, no support for redundancy checks." >&2
 exit 4
fi

if ! egrep -q '^raid([1456]|10)$' /sys/block/md*/md/level 2>/dev/null; then
 echo "$PROGNAME: no redundant arrays present." >&2
 exit 5
fi

if [ -z "$(ls /sys/block/md*/md/sync_action 2>/dev/null)" ]; then
 echo "$PROGNAME: no kernel support for redundancy checks." >&2
 exit 6
fi

[ $all = 1 ] && arrays="$(ls -d1 /sys/block/md* | cut -d/ -f4)"
 for array in $arrays; do
 SYNC_ACTION_CTL=/sys/block/$array/md/sync_action

 if [ ! -e $SYNC_ACTION_CTL ]; then
 echo "$PROGNAME: skipping non-redundant array $array." >&2
 continue
 fi

 cur_status="$(cat $SYNC_ACTION_CTL)"
 if [ $action = status ]; then
 echo "$array: $cur_status"
 continue
 fi

 if [ ! -w $SYNC_ACTION_CTL ]; then
 echo "$PROGNAME: $SYNC_ACTION_CTL not writeable." >&2
 exit 7
 fi

 if [ "$(cat /sys/block/$array/md/array_state)" = 'read-auto' ]; then
 echo "$PROGNAME: array $array in auto-read-only state, skipping." >&2
 continue
 fi

 case "$action" in
 check)
 if [ "$cur_status" != idle ]; then
 echo "$PROGNAME: array $array not idle, skipping." >&2
 continue
 fi

 echo $action > $SYNC_ACTION_CTL
 echo "$PROGNAME: check queued for array $array."
 ;;

 idle)
 echo $action > $SYNC_ACTION_CTL
 echo "$PROGNAME: cancel request queued for array $array."
 ;;
 esac
done

exit 0

Zabbix : monitoring Nginx / PHP-FPM / MySQL

Voici les scripts que j’utilise pour monitorer avec Zabbix des serveurs Nginx / MySQL / PHP-FPM. Je vous livre également une template contenant l’ensemble des items et triggers.

zabbix_agentd.conf :

UserParameter=nginx.active,/etc/zabbix/scripts/nginx.pl|cut -f1|cut -d" " -f2
UserParameter=nginx.requests,/etc/zabbix/scripts/nginx.pl|cut -f2|cut -d" " -f2
UserParameter=nginx.reading,/etc/zabbix/scripts/nginx.pl|cut -f3|cut -d" " -f2
UserParameter=nginx.writing,/etc/zabbix/scripts/nginx.pl|cut -f4|cut -d" " -f2
UserParameter=nginx.waiting,/etc/zabbix/scripts/nginx.pl|cut -f5|cut -d" " -f2
UserParameter=php.ping,/etc/zabbix/scripts/php-fpm_ping.pl
UserParameter=php.conn,/etc/zabbix/scripts/php-fpm_status.pl|cut -f1|cut -d" " -f3
UserParameter=php.idle,/etc/zabbix/scripts/php-fpm_status.pl|cut -f2|cut -d" " -f3
UserParameter=php.active,/etc/zabbix/scripts/php-fpm_status.pl|cut -f3|cut -d" " -f3
UserParameter=php.total,/etc/zabbix/scripts/php-fpm_status.pl|cut -f4|cut -d" " -f3
UserParameter=php.maxchildren,/etc/zabbix/scripts/php-fpm_status.pl|cut -f5|cut -d" " -f3
UserParameter=mysql.status[*],/etc/zabbix/scripts/mysql_status.pl $1

/etc/zabbix/scripts/nginx.pl :

#!/usr/bin/perl#
# Boris HUISGEN <bhuisgen@hbis.fr>

use LWP::UserAgent;

my $URL = "http://127.0.0.1/nginx_status";

#
# DO NOT MODIFY AFTER THIS LINE
#

my $ua = LWP::UserAgent->new(timeout => 15);
my $response = $ua->request(HTTP::Request->new('GET', $URL));

my $active =  0;
my $reading = 0;
my $writing = 0;
my $waiting = 0;
my $requests = 0;

foreach (split(/\n/, $response->content)) {
 $active = $1 if (/^Active connections:\s+(\d+)/);

 if (/^Reading:\s+(\d+).*Writing:\s+(\d+).*Waiting:\s+(\d+)/) {
 $reading = $1;
 $writing = $2;
 $waiting = $3;
 }

 $requests = $3 if (/^\s+(\d+)\s+(\d+)\s+(\d+)/);
}

print "Active: $active\tRequests: $requests\tReading: $reading\tWriting: $writing\tWaiting: $waiting\n";

php-fpm_ping.pl :

#!/usr/bin/perl
#
# Boris HUISGEN <bhuisgen@hbis.fr>

use LWP::UserAgent;

my $URL = "http://127.0.0.1/php5fpm-ping";

#
# DO NOT MODIFY AFTER THIS LINE
#

my $ua = LWP::UserAgent->new(timeout => 15);
my $response = $ua->request(HTTP::Request->new('GET', $URL));

if ($response->is_success) {
 print "1\n";
}
else {
 print "0\n";
}

php-fpm_status.pl :

#!/usr/bin/perl
#
# Boris HUISGEN <bhuisgen@hbis.fr>

use LWP::UserAgent;

my $URL = "http://127.0.0.1/php5fpm-status";

#
# DO NOT MODIFY AFTER THIS LINE
#

my $ua = LWP::UserAgent->new(timeout => 15);
my $response = $ua->request(HTTP::Request->new('GET', $URL));

my $conn = 0;
my $idle = 0;
my $active = 0;
my $total = 0;
my $maxchildren = 0;

foreach (split(/\n/, $response->content)) {
 $conn = $1 if (/^accepted conn:\s+(\d+)/);
 $idle = $1 if (/^idle processes:\s+(\d+)/);
 $active = $1 if (/^active processes:\s+(\d+)/);
 $total = $1 if (/^total processes:\s+(\d+)/);
 $maxchildren = $1 if (/^max children reached:\s+(\d+)/);
}

print "Accepted conn: $conn\tIdle proc: $idle\tActive proc: $active\tTotal proc: $total\tMax children: $maxchildren\n";

mysql_status.pl :

#!/usr/bin/perl
#
# Boris HUISGEN <bhuisgen@hbis.fr>

my($mysql)   = "/usr/bin/mysql";
my($user)    = "zabbix";
my($passwd)  = "abcdef123";
my($host)    = "localhost";

#
# DO NOT MODIFY AFTER THIS LINE
#

=head1 NAME

mysql_status.pl - show MySQL variable status

=head1 SYNOPSIS

 mysql_status.pl VARIABLE

 --help                      print this help message
 --version                   print version information

=head1 DESCRIPTION

This program shows the status of a MySQL variable.

=head1 AUTHOR

Boris HUISGEN <bhuisgen@hbis.fr>

=cut

use strict;
use warnings;

use Getopt::Long qw(:config auto_help auto_version);
use Pod::Usage;

$main::VERSION = "0.1-2012040501";

exit main();

sub show_variable {
 my ($variable) = $_[0];

 my ($cmd) = "$mysql -u $user -p$passwd -h $host --execute \"SHOW GLOBAL STATUS LIKE '$variable'\" --skip-column-name";
 my ($ret) =`$cmd 2> /dev/null`;
 exit(1) unless($ret);

 $ret =~ m/^$variable.[\s\t]*(.*)/;
 print "$1\n";
}

sub main {
 GetOptions ()
 or pod2usage(1);

 pod2usage (1) unless ($#ARGV == 0);

 my ($variable) = $ARGV[0];

 show_variable($variable);
}

# end of script

nginx.conf :

server {
 listen          127.0.0.1:80;
 listen          [::1]:80;
 server_name     localhost;
 root            /var/www/default/www/html;
 access_log      /var/www/default/www/logs/access.log;
 error_log       /var/www/default/www/logs/error.log;
 index           index.html;

 location /nginx_status {
 stub_status on;
 access_log off;
 allow 127.0.0.1;
 deny all;
 }

 location = /php5fpm-status {
 fastcgi_pass    unix:/var/run/php5-fpm.sock;
 fastcgi_index   index.php;
 fastcgi_param   SCRIPT_FILENAME  /var/www/default/www/html$fastcgi_script_name;
 include         fastcgi_params;
 }

 location = /php5fpm-ping {
 fastcgi_pass    unix:/var/run/php5-fpm.sock;
 fastcgi_index   index.php;
 fastcgi_param   SCRIPT_FILENAME  /var/www/default/www/html$fastcgi_script_name;
 include         fastcgi_params;
 }

php-fpm.conf :

pm.status_path = /php5fpm-status
ping.path = /php5fpm-ping
ping.path = /php5fpm-ping

Template Zabbix : [Téléchargement introuvable]

Firewall Builder 4.1.3 : patch IPv6 forwarding

Un petit patch pour corriger les règles automatiques dans le cadre du IPv6 forwarding. Ce cas est injustement oublié par l’option « Add rules to accept IPv6 Neighbor Discovery packets » qu’il convient d’activer dans les paramètres de l’objet firewall.

Dans le cas où vous possédez une version 3, la mise à jour en version 4 est obligatoire.

--- /usr/local/share/fwbuilder-4.1.3/configlets/linux24/automatic_rules.old    2010-12-06 03:00:45.000000000 +0100
+++ /usr/local/share/fwbuilder-4.1.3/configlets/linux24/automatic_rules    2011-02-11 09:39:42.830967384 +0100
@@ -83,12 +83,24 @@
 # rules to permit IPv6 Neighbor discovery
 {{$begin_rule}} INPUT  -p ipv6-icmp -m icmp6 --icmpv6-type router-solicitation -m hl --hl-eq 255 -j ACCEPT {{$end_rule}}
 {{$begin_rule}} OUTPUT -p ipv6-icmp -m icmp6 --icmpv6-type router-solicitation -m hl --hl-eq 255 -j ACCEPT {{$end_rule}}
+{{if ipforw}}
+{{$begin_rule}} FORWARD -p ipv6-icmp -m icmp6 --icmpv6-type router-solicitation -m hl --hl-eq 255 -j ACCEPT {{$end_rule}}
+{{endif}}
 {{$begin_rule}} INPUT  -p ipv6-icmp -m icmp6 --icmpv6-type router-advertisement -m hl --hl-eq 255 -j ACCEPT {{$end_rule}}
 {{$begin_rule}} OUTPUT -p ipv6-icmp -m icmp6 --icmpv6-type router-advertisement -m hl --hl-eq 255 -j ACCEPT {{$end_rule}}
+{{if ipforw}}
+{{$begin_rule}} FORWARD -p ipv6-icmp -m icmp6 --icmpv6-type router-advertisement -m hl --hl-eq 255 -j ACCEPT {{$end_rule}}
+{{endif}}
 {{$begin_rule}} INPUT  -p ipv6-icmp -m icmp6 --icmpv6-type neighbour-solicitation -m hl --hl-eq 255 -j ACCEPT {{$end_rule}}
 {{$begin_rule}} OUTPUT -p ipv6-icmp -m icmp6 --icmpv6-type neighbour-solicitation -m hl --hl-eq 255 -j ACCEPT {{$end_rule}}
+{{if ipforw}}
+{{$begin_rule}} FORWARD -p ipv6-icmp -m icmp6 --icmpv6-type neighbour-solicitation -m hl --hl-eq 255 -j ACCEPT {{$end_rule}}
+{{endif}}
 {{$begin_rule}} INPUT  -p ipv6-icmp -m icmp6 --icmpv6-type neighbour-advertisement -m hl --hl-eq 255 -j ACCEPT {{$end_rule}}
 {{$begin_rule}} OUTPUT -p ipv6-icmp -m icmp6 --icmpv6-type neighbour-advertisement -m hl --hl-eq 255 -j ACCEPT {{$end_rule}}
+{{if ipforw}}
+{{$begin_rule}} FORWARD -p ipv6-icmp -m icmp6 --icmpv6-type neighbour-advertisement -m hl --hl-eq 255 -j ACCEPT {{$end_rule}}
+{{endif}}
 {{endif}}

 {{if drop_invalid}}

Linux : reboot automatique suite à un kernel panic

Par défaut, un « kernel panic » gèle complètement le système. Il n’y a pas de miracle :  il y a un bug logiciel (userland/kernel) voire matériel. Dans le cas d’un serveur/système obsolète, le plus simple reste à activer le reboot automatique par le biais des paramètres noyaux. Par exemple, sur un noyau 2.6 où le reboot est désactivé :

# sysctl -a|grep kernel.panic
kernel.panic = 0
kernel.panic_on_oops = 0

Il faut modifier au moins kernel.panic et kernel.panic_on_oops. Les valeurs associées correspondent au délai en secondes avant le reboot automatique (0 le désactivant).

# nano /etc/sysctl.conf
kernel.panic = 15
kernel.panic_on_oops = 15
# sysctl -p

Moralité : à défaut de vouloir ou pouvoir corriger, on met un pansement pour faire joli :)

Haut de page