Je veux pouvoir encore faire quelque chose avec ma machine ! :-)
j'imagine que c'est un dd bien placé dans le cron
Au début (j'ai fait des tests plus poussés après avoir écrit le script, justement en l'utilisant), je craignais de devoir activer le disque avec une périodicité inférieure à 10 secondes (ç'eût été le cas avec hdparm -B 255), donc cron était écarté d'office. De toute façon, je préfère avoir une granularité inférieure à une minute, et puis cron n'est pas sensé non plus garantir un déclenchement très précis.
Qui plus est, l'utilisation de cron pour une très faible périodicité conduit quelquefois en cas de forte charge système à l'accumulation d'appels.
Un simple sleep dans le script suffit à garantir un délai entre les opérations sans inconvénient.
combiné avec sync ?
Je n'étais pas trop chaud pour sync non plus, ayant l'expérience (avec le traitement massifs de mails par le serveur mail après rapatriement par uucp) de la charge système induite par des syncs fréquents (le serveur mail en fait un pour chaque mail).
Comme une écriture sans sync ne force pas d'activité disque, je me suis donc orienté vers une lecture (aléatoire pour essayer d'éviter de tomber sur des données en cache, doublée pour améliorer les chances).
En cas de forte charge en accès disque, logiquement ma demande de lecture doit attendre son tour comme les autres, ce qui tendrait à augmenter la périodicité dans une situation où l'opération est superflue. Tant mieux.
Par ailleurs, pour réduire le risque de délai supplémentaire inopportun au déclenchement en cas de très forte charge CPU, je voulais éviter tout chargement de contexte, donc tout appel d'une commande externe, donc je me suis dirigé vers une solution en Perl pur.
Bon, je ne prétends pas qu'il n'y aurait pas une meilleure solution (fsync, plus léger qu'un sync complet, serait une bonne piste; une lecture planifiée plutôt qu'aléatoire serait plus propre, mais nécessiterait des informations supplémentaires comme la quantité de données mise en cache à chaque accès disque), mais en tout cas, celle à laquelle j'ai abouti fonctionne de manière satisfaisante : pas d'augmentation du nombre de parquage des têtes après le démarrage, plus discrète que ne l'était le parquage, augmentation de la charge du système insensible.
tu aurais pus poster le script car il ne doit pas etre tres grand :)
Il n'est pas hyper petit non plus, vu qu'il contient en plus tout ce qu'il faut pour fonctionner comme un démon.
Enfin voilà :
--------
#!/usr/bin/perl -w
use strict;
# Lecture periodique sur le disque dur pour empecher le parquage des tetes
# alors que le nombre maximal prevu est deja explose depuis longtemps.
# Fonctionne comme un demon si son nom se termine par "d".
# Delai entre deux lectures, valeur a ajuster suivant le materiel.
# ATTENTION : une valeur incorrecte peut ACCELERER la deterioration du disque.
# Il est donc crucial de l'ajuster finement en controlant l'effet avec smartctl.
# La valeur presente dans /etc/sysconfig/no_park est prioritaire et les
# parametres passes en ligne de commande sont encore plus prioritaires.
my $delai = 60;
# Descripteur de peripherique du disque, valeur par defaut normalement ecrasee
# par celle determinee a partir de /etc/fstab.
my $disque = '/dev/hda';
use POSIX;
# Determination du peripherique
if (open FSTAB, '</etc/fstab') {
while (<FSTAB>) {
m:^(\S+?)\d+\s+/\s: and $disque = 1ドル and last;
}
close FSTAB;
}
# Determination du delai entre deux activations
if (open CONF, '</etc/sysconfig/no_park') {
while (<CONF>) {
/^\s*DELAI\s*=\s*(\d+)\s*(#|$)/ and $delai = 1ドル;
}
close CONF;
}
# Prise en compte prioritaire des eventuels parametres de la ligne de commande
foreach (@ARGV) {
if (m:/:) {
$disque = $_;
} elsif (/^\d+$/) {
$delai = $_;
}
}
# Ouverture du disque en lecture
open DD, "<$disque" or die "Impossible d'ouvrir $disque\n";
# Fermeture du disque et sortie en cas de signal d'interruption
$SIG{TERM} = $SIG{INT} = sub {
close DD;
exit;
};
# Si le nom de commande se termine par "d", il s'agit du demon,
if (0ドル =~ /d$/) {
# donc on detache le processus.
my $tent = 0;
DETACH:
if (my $pid = fork()) {
# Processus parent, on ferme.
close DD;
exit;
} elsif (!defined $pid) {
if ($! =~ /No more process/ && $tent++ < 5) {
# Erreur de fork eventuellement recuperable
sleep 5;
redo DETACH;
} else {
# Erreur de fork bizarre
die "Impossible de detacher le processus : $!\n";
}
}
# Processus fils
close STDIN;
close STDOUT;
close STDERR;
POSIX::setsid();
}
# Determination de la fin du disque
seek DD, 0, 2;
my $fin = tell(DD);
# Lecture periodique de donnees au hasard
my $tamp;
while (1) {
seek DD, rand($fin), 0;
read DD, $tamp, 1;
# Une deuxieme lecture pour limiter les risques de tomber sur un secteur en cache
seek DD, rand($fin), 0;
read DD, $tamp, 1;
# On laisse passer le delai entre deux activations.
sleep $delai;
}
----------
Note : si quelqu'un fait un copier-coller du code ci-dessus avec un navigateur qui conserve les espaces insécables à la copie (ce n'est pas le cas de Firefox), il aura intérêt à les enlever avec une commande du style :
sed -e 's/\xC2\?\xA0/ /' code_recupere.txt > /usr/local/sbin/no_parkd
« Le fascisme c’est la gangrène, à Washington comme en Russie. » — adapté de Renaud, Hexagone
[^] # Mon script
Posté par Arthur Accroc . En réponse au journal Canonical aurait des actions de fabricants de disques durs!. Évalué à 4.
Je veux pouvoir encore faire quelque chose avec ma machine ! :-)
Au début (j'ai fait des tests plus poussés après avoir écrit le script, justement en l'utilisant), je craignais de devoir activer le disque avec une périodicité inférieure à 10 secondes (ç'eût été le cas avec hdparm -B 255), donc cron était écarté d'office. De toute façon, je préfère avoir une granularité inférieure à une minute, et puis cron n'est pas sensé non plus garantir un déclenchement très précis.
Qui plus est, l'utilisation de cron pour une très faible périodicité conduit quelquefois en cas de forte charge système à l'accumulation d'appels.
Un simple sleep dans le script suffit à garantir un délai entre les opérations sans inconvénient.
Je n'étais pas trop chaud pour sync non plus, ayant l'expérience (avec le traitement massifs de mails par le serveur mail après rapatriement par uucp) de la charge système induite par des syncs fréquents (le serveur mail en fait un pour chaque mail).
Comme une écriture sans sync ne force pas d'activité disque, je me suis donc orienté vers une lecture (aléatoire pour essayer d'éviter de tomber sur des données en cache, doublée pour améliorer les chances).
En cas de forte charge en accès disque, logiquement ma demande de lecture doit attendre son tour comme les autres, ce qui tendrait à augmenter la périodicité dans une situation où l'opération est superflue. Tant mieux.
Par ailleurs, pour réduire le risque de délai supplémentaire inopportun au déclenchement en cas de très forte charge CPU, je voulais éviter tout chargement de contexte, donc tout appel d'une commande externe, donc je me suis dirigé vers une solution en Perl pur.
Bon, je ne prétends pas qu'il n'y aurait pas une meilleure solution (fsync, plus léger qu'un sync complet, serait une bonne piste; une lecture planifiée plutôt qu'aléatoire serait plus propre, mais nécessiterait des informations supplémentaires comme la quantité de données mise en cache à chaque accès disque), mais en tout cas, celle à laquelle j'ai abouti fonctionne de manière satisfaisante : pas d'augmentation du nombre de parquage des têtes après le démarrage, plus discrète que ne l'était le parquage, augmentation de la charge du système insensible.
Il n'est pas hyper petit non plus, vu qu'il contient en plus tout ce qu'il faut pour fonctionner comme un démon.
Enfin voilà :
--------
#!/usr/bin/perl -w
use strict;
# Lecture periodique sur le disque dur pour empecher le parquage des tetes
# alors que le nombre maximal prevu est deja explose depuis longtemps.
# Fonctionne comme un demon si son nom se termine par "d".
# Delai entre deux lectures, valeur a ajuster suivant le materiel.
# ATTENTION : une valeur incorrecte peut ACCELERER la deterioration du disque.
# Il est donc crucial de l'ajuster finement en controlant l'effet avec smartctl.
# La valeur presente dans /etc/sysconfig/no_park est prioritaire et les
# parametres passes en ligne de commande sont encore plus prioritaires.
my $delai = 60;
# Descripteur de peripherique du disque, valeur par defaut normalement ecrasee
# par celle determinee a partir de /etc/fstab.
my $disque = '/dev/hda';
use POSIX;
# Determination du peripherique
if (open FSTAB, '</etc/fstab') {
while (<FSTAB>) {
m:^(\S+?)\d+\s+/\s: and $disque = 1ドル and last;
}
close FSTAB;
}
# Determination du delai entre deux activations
if (open CONF, '</etc/sysconfig/no_park') {
while (<CONF>) {
/^\s*DELAI\s*=\s*(\d+)\s*(#|$)/ and $delai = 1ドル;
}
close CONF;
}
# Prise en compte prioritaire des eventuels parametres de la ligne de commande
foreach (@ARGV) {
if (m:/:) {
$disque = $_;
} elsif (/^\d+$/) {
$delai = $_;
}
}
# Ouverture du disque en lecture
open DD, "<$disque" or die "Impossible d'ouvrir $disque\n";
# Fermeture du disque et sortie en cas de signal d'interruption
$SIG{TERM} = $SIG{INT} = sub {
close DD;
exit;
};
# Affichage des parametres retenus
warn "no_park : disque $disque, delai : $delai\n";
# Si le nom de commande se termine par "d", il s'agit du demon,
if (0ドル =~ /d$/) {
# donc on detache le processus.
my $tent = 0;
DETACH:
if (my $pid = fork()) {
# Processus parent, on ferme.
close DD;
exit;
} elsif (!defined $pid) {
if ($! =~ /No more process/ && $tent++ < 5) {
# Erreur de fork eventuellement recuperable
sleep 5;
redo DETACH;
} else {
# Erreur de fork bizarre
die "Impossible de detacher le processus : $!\n";
}
}
# Processus fils
close STDIN;
close STDOUT;
close STDERR;
POSIX::setsid();
}
# Determination de la fin du disque
seek DD, 0, 2;
my $fin = tell(DD);
# Lecture periodique de donnees au hasard
my $tamp;
while (1) {
seek DD, rand($fin), 0;
read DD, $tamp, 1;
# Une deuxieme lecture pour limiter les risques de tomber sur un secteur en cache
seek DD, rand($fin), 0;
read DD, $tamp, 1;
# On laisse passer le delai entre deux activations.
sleep $delai;
}
----------
Note : si quelqu'un fait un copier-coller du code ci-dessus avec un navigateur qui conserve les espaces insécables à la copie (ce n'est pas le cas de Firefox), il aura intérêt à les enlever avec une commande du style :
sed -e 's/\xC2\?\xA0/ /' code_recupere.txt > /usr/local/sbin/no_parkd
« Le fascisme c’est la gangrène, à Washington comme en Russie. » — adapté de Renaud, Hexagone