En un servidor están alojadas varias máquinas virtuales. Todas las madrugadas se ejecuta una tarea bastante pesada, en todas ellas a la misma hora, por lo que dejan al servidor medio frito:
- Código: Seleccionar todo
# grep "statistics" /vz/root/*/var/spool/cron/root
/vz/root/1001/var/spool/cron/root:7 4 * * * /usr/local/psa/admin/sbin/statistics >/dev/null 2>&1
/vz/root/1002/var/spool/cron/root:7 4 * * * /usr/local/psa/admin/sbin/statistics >/dev/null 2>&1
/vz/root/1003/var/spool/cron/root:7 4 * * * /usr/local/psa/admin/sbin/statistics >/dev/null 2>&1
/vz/root/1004/var/spool/cron/root:7 4 * * * /usr/local/psa/admin/sbin/statistics >/dev/null 2>&1
/vz/root/1006/var/spool/cron/root:7 4 * * * /usr/local/psa/admin/sbin/statistics >/dev/null 2>&1
/vz/root/1007/var/spool/cron/root:7 4 * * * /usr/local/psa/admin/sbin/statistics >/dev/null 2>&1
/vz/root/1008/var/spool/cron/root:7 4 * * * /usr/local/psa/admin/sbin/statistics >/dev/null 2>&1
/vz/root/1009/var/spool/cron/root:7 4 * * * /usr/local/psa/admin/sbin/statistics >/dev/null 2>&1
/vz/root/1010/var/spool/cron/root:7 4 * * * /usr/local/psa/admin/sbin/statistics >/dev/null 2>&1
Estoy preparando un script para dejar unos minutos entre cada tarea de modo que la carga se reparta a lo largo de la noche. Tengo una versión que ya funciona pero creo que todavía se podría hacer algo más elegante con vuestra experiencia, sobre todo en la parte de sustitución que queda algo chapucera..
Using perl Syntax Highlighting
#!/usr/bin/perl
my $incremento = 5;
my $m = 0;
my $h = 2;
foreach $fichero (glob("/vz/root/*/var/spool/cron/root")) {
open(F, "$fichero") or die "ERROR al abrir $_";
@lineas = <F>;
close(F);
open(F, ">$fichero") or die "ERROR al abrir $fichero en modo escritura";
foreach $A (@lineas) {
$A =~ s/^\d+\s+\d+\s+\*\s+\*\s+\*\s+\/usr\/local\/psa\/admin\/sbin\/statistics\s+>\/dev\/null\s+2>&1/$m\t$h\t*\t*\t*\t\/usr\/local\/psa\/admin\/sbin\/statistics >\/dev\/null 2>&1/g;
print F $A;
}
$m += $incremento;
if ($m > 59) {
$m -= 60;
$h++;
}
close(F);
}
my $incremento = 5;
my $m = 0;
my $h = 2;
foreach $fichero (glob("/vz/root/*/var/spool/cron/root")) {
open(F, "$fichero") or die "ERROR al abrir $_";
@lineas = <F>;
close(F);
open(F, ">$fichero") or die "ERROR al abrir $fichero en modo escritura";
foreach $A (@lineas) {
$A =~ s/^\d+\s+\d+\s+\*\s+\*\s+\*\s+\/usr\/local\/psa\/admin\/sbin\/statistics\s+>\/dev\/null\s+2>&1/$m\t$h\t*\t*\t*\t\/usr\/local\/psa\/admin\/sbin\/statistics >\/dev\/null 2>&1/g;
print F $A;
}
$m += $incremento;
if ($m > 59) {
$m -= 60;
$h++;
}
close(F);
}
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4
La primera cosa que creo que se podría mejorar es la doble apertura del fichero, la primera en modo lectura para cargar el contenido y la segunda de escritura con los cambios en el cron. He estado probando con el switch "-i" que venía usando hasta ahora en los "one-liners" pero no me ha funcionado. En un post reciente de "explorer" he visto un caso similar en el que recomienda usar Sysadm::Install 'pie', la solución es muy buena pero no quisiera tener que instalar módulos adicionales...
La otra chapuza es la expresión regular utilizada para la sustitución... entiendo que todavía se puede reducir mucho más, pero no se cómo.. Las cadenas a cambiar siempre tienen este formato:
- Código: Seleccionar todo
7 4 * * * /usr/local/psa/admin/sbin/statistics >/dev/null 2>&1
Lo único a cambiar serían los dos primeros campos, los minutos y horas.. ¿Cómo mejorarías la expresión regular?
Tras ejecutar el script los crons quedan así:
- Código: Seleccionar todo
/vz/root/1001/var/spool/cron/root:0 2 * * * /usr/local/psa/admin/sbin/statistics >/dev/null 2>&1
/vz/root/1002/var/spool/cron/root:5 2 * * * /usr/local/psa/admin/sbin/statistics >/dev/null 2>&1
/vz/root/1003/var/spool/cron/root:10 2 * * * /usr/local/psa/admin/sbin/statistics >/dev/null 2>&1
/vz/root/1004/var/spool/cron/root:15 2 * * * /usr/local/psa/admin/sbin/statistics >/dev/null 2>&1
/vz/root/1006/var/spool/cron/root:20 2 * * * /usr/local/psa/admin/sbin/statistics >/dev/null 2>&1
/vz/root/1007/var/spool/cron/root:25 2 * * * /usr/local/psa/admin/sbin/statistics >/dev/null 2>&1
/vz/root/1008/var/spool/cron/root:30 2 * * * /usr/local/psa/admin/sbin/statistics >/dev/null 2>&1
/vz/root/1009/var/spool/cron/root:35 2 * * * /usr/local/psa/admin/sbin/statistics >/dev/null 2>&1
/vz/root/1010/var/spool/cron/root:40 2 * * * /usr/local/psa/admin/sbin/statistics >/dev/null 2>&1
/vz/root/1011/var/spool/cron/root:45 2 * * * /usr/local/psa/admin/sbin/statistics >/dev/null 2>&1
/vz/root/1012/var/spool/cron/root:50 2 * * * /usr/local/psa/admin/sbin/statistics >/dev/null 2>&1
/vz/root/1013/var/spool/cron/root:55 2 * * * /usr/local/psa/admin/sbin/statistics >/dev/null 2>&1
/vz/root/1014/var/spool/cron/root:0 3 * * * /usr/local/psa/admin/sbin/statistics >/dev/null 2>&1
/vz/root/1016/var/spool/cron/root:10 3 * * * /usr/local/psa/admin/sbin/statistics >/dev/null 2>&1
/vz/root/1017/var/spool/cron/root:15 3 * * * /usr/local/psa/admin/sbin/statistics >/dev/null 2>&1
/vz/root/1019/var/spool/cron/root:20 3 * * * /usr/local/psa/admin/sbin/statistics >/dev/null 2>&1
A pesar de que el script ya hace su trabajo, creo que se puede mejorar bastante.. cualquier sugerencia es bienvenida
Saludos,