20091021

$ wget --no-verbose --no-clobber --continue --span-hosts --page-requisites --user-agent mozilla \
http://www.boston.com/bigpicture/2009/10/saturn_at_equinox.html
2009-10-21 23:43:52 URL:http://www.boston.com/bigpicture/2009/10/saturn_at_equinox.html [119997] ->
"www.boston.com/bigpicture/2009/10/saturn_at_equinox.html" [1]
2009-10-21 23:43:53 URL:http://cache.boston.com/robots.txt [333/333] -> "cache.boston.com/robots.txt" [1]

[...]

2009-10-21 23:44:13 URL:http://an.tacoda.net/an/13651/slf.js [18648/18648] -> "an.tacoda.net/an/13651/slf.js" [1]
FINISHED --2009-10-21 23:44:13--
Downloaded: 41 files, 4.3M in 0s (8471005 GB/s)

Update: Cuanto más se baje uno, mejor se pone la cosa!


Downloaded: 114 files, 299M in 0s (583398562 GB/s)

20091010

Me encontré esta semana a mi compañero de curro en mi anterior empresa (de la que tantas historias paranormales salieron), con quien podía expresarme realmente en mi idioma, y en nuestra breve conversación me recordó la existencia de este montoncito de telarañas llamado $RANDOM.


Y en fin, se da la casualidad de que hace un rato, un día y medio después de aquel feliz (re)encuentro, he estado haciendo un poquillo de magia en la terminal de aquí al lado, magia digna de ser compartida con el multiverso para regocijo de algunos y vergüenza ajena de otros. Me puse a darle vueltas a la idea de agrupar semanal, mensual y anualmente los datos de bolsa almacenados en una base de datos SQL. He aquí el formato de la tabla (con datos salidos de mi /dev/urandom)


hue@localhost:hue> SELECT * FROM data;
+----+------------+------------+-------+-------+-------+-------+--------+
| id | date_ini | date_end | open | high | low | close | vol |
+----+------------+------------+-------+-------+-------+-------+--------+
| 1 | 2009-08-27 | 2009-08-27 | 46.90 | 47.35 | 46.08 | 46.63 | 115623 |
| 2 | 2009-08-28 | 2009-08-28 | 46.55 | 47.93 | 46.27 | 47.39 | 100148 |
| 3 | 2009-08-29 | 2009-08-29 | 42.80 | 43.26 | 41.83 | 42.68 | 112355 |
| 4 | 2009-08-30 | 2009-08-30 | 43.90 | 45.22 | 43.07 | 44.84 | 110152 |
| 5 | 2009-08-31 | 2009-08-31 | 43.45 | 43.76 | 42.70 | 43.72 | 105615 |
| 6 | 2009-09-01 | 2009-09-01 | 45.89 | 46.37 | 44.71 | 46.15 | 110194 |
[...]
| 36 | 2009-10-01 | 2009-10-01 | 50.40 | 50.48 | 49.74 | 50.47 | 110431 |
| 37 | 2009-10-02 | 2009-10-02 | 46.75 | 47.98 | 45.09 | 46.92 | 110365 |
| 38 | 2009-10-03 | 2009-10-03 | 46.66 | 48.50 | 46.24 | 47.27 | 100076 |
| 39 | 2009-10-04 | 2009-10-04 | 48.13 | 49.85 | 47.58 | 48.69 | 114055 |
| 40 | 2009-10-05 | 2009-10-05 | 47.62 | 49.55 | 47.24 | 47.33 | 118031 |
+----+------------+------------+-------+-------+-------+-------+--------+
40 rows in set (0.00 sec)

La gracia de este asunto es obtener una columna significativa sobre la cual poder hacer un GROUP BY. Tras un ratejo de sesudas cavilaciones y algo de Google, obtuve esto:


hue@localhost:hue> hue@localhost:hue> SELECT id,
-> date_ini, YEARWEEK(date_ini, 1) week_ini, DATE_FORMAT(date_ini, '%Y%m') month_ini, YEAR(date_ini) year_ini,
-> date_end, YEARWEEK(date_end, 1) week_end, DATE_FORMAT(date_end, '%Y%m') month_end, YEAR(date_end) year_end
-> FROM data;
+----+------------+----------+-----------+----------+------------+----------+-----------+----------+
| id | date_ini | week_ini | month_ini | year_ini | date_end | week_end | month_end | year_end |
+----+------------+----------+-----------+----------+------------+----------+-----------+----------+
| 1 | 2009-08-27 | 200935 | 200908 | 2009 | 2009-08-27 | 200935 | 200908 | 2009 |
| 2 | 2009-08-28 | 200935 | 200908 | 2009 | 2009-08-28 | 200935 | 200908 | 2009 |
| 3 | 2009-08-29 | 200935 | 200908 | 2009 | 2009-08-29 | 200935 | 200908 | 2009 |
| 4 | 2009-08-30 | 200935 | 200908 | 2009 | 2009-08-30 | 200935 | 200908 | 2009 |
| 5 | 2009-08-31 | 200936 | 200908 | 2009 | 2009-08-31 | 200936 | 200908 | 2009 |
| 6 | 2009-09-01 | 200936 | 200909 | 2009 | 2009-09-01 | 200936 | 200909 | 2009 |
[...]
| 36 | 2009-10-01 | 200940 | 200910 | 2009 | 2009-10-01 | 200940 | 200910 | 2009 |
| 37 | 2009-10-02 | 200940 | 200910 | 2009 | 2009-10-02 | 200940 | 200910 | 2009 |
| 38 | 2009-10-03 | 200940 | 200910 | 2009 | 2009-10-03 | 200940 | 200910 | 2009 |
| 39 | 2009-10-04 | 200940 | 200910 | 2009 | 2009-10-04 | 200940 | 200910 | 2009 |
| 40 | 2009-10-05 | 200941 | 200910 | 2009 | 2009-10-05 | 200941 | 200910 | 2009 |
+----+------------+----------+-----------+----------+------------+----------+-----------+----------+
40 rows in set (0.00 sec)

Los datos _end son mayormente inútiles, en tanto en cuanto coinciden con los _ini, pero eso no se me ocurrió mientras lo hacía. Bien, teniendo esto, ya podemos hacer GROUP BY, pero todavía queda una complicación: para cada período, nos interesa tener:



No está mal el batiburrillo eh? xD. Para el mayor, el menor y la suma, se pueden usar sin más complicaciones las funciones MAX, MIN y SUM, pero en MySQL no tenemos funciones FIRST ni LAST para poder usar en los otros cuatro casos. Una búsqueda rapidita en Google tampoco me mostró muchas cosas para PostgreSQL. Lo único que encontré fue una pequeña trampa que no me tiene del todo contento pero que funciona: SUBSTR(GROUP_CONCAT):


hue@localhost:hue> SELECT id, GROUP_CONCAT(date_ini ORDER BY id) date_ini, YEARWEEK(date_ini,1) week_ini FROM data GROUP BY week_ini;
+----+------------------------------------------------------------------------------+----------+
| id | date_ini | week_ini |
+----+------------------------------------------------------------------------------+----------+
| 1 | 2009-08-27,2009-08-28,2009-08-29,2009-08-30 | 200935 |
| 11 | 2009-08-31,2009-09-01,2009-09-02,2009-09-03,2009-09-04,2009-09-05,2009-09-06 | 200936 |
| 18 | 2009-09-07,2009-09-08,2009-09-09,2009-09-10,2009-09-11,2009-09-12,2009-09-13 | 200937 |
| 25 | 2009-09-14,2009-09-15,2009-09-16,2009-09-17,2009-09-18,2009-09-19,2009-09-20 | 200938 |
| 32 | 2009-09-21,2009-09-22,2009-09-23,2009-09-24,2009-09-25,2009-09-26,2009-09-27 | 200939 |
| 39 | 2009-09-28,2009-09-29,2009-09-30,2009-10-01,2009-10-02,2009-10-03,2009-10-04 | 200940 |
| 40 | 2009-10-05 | 200941 |
+----+------------------------------------------------------------------------------+----------+
7 rows in set (0.00 sec)

GROUP_CONCAT nos da todos los elementos que se han agrupado en virtud del GROUP BY. A partir de ahí, con SUBSTR cogemos el dato que nos interesa:


hue@localhost:hue> SELECT id, SUBSTR(GROUP_CONCAT(date_ini ORDER BY id), 1, 10) date_ini, YEARWEEK(date_ini, 1) week_ini FROM data GROUP BY week_ini;
+----+------------+----------+
| id | date_ini | week_ini |
+----+------------+----------+
| 1 | 2009-08-27 | 200935 |
| 11 | 2009-08-31 | 200936 |
| 18 | 2009-09-07 | 200937 |
| 25 | 2009-09-14 | 200938 |
| 32 | 2009-09-21 | 200939 |
| 39 | 2009-09-28 | 200940 |
| 40 | 2009-10-05 | 200941 |
+----+------------+----------+
7 rows in set (0.00 sec)

Para coger la última fecha, usamos GROUP_CONCAT(date_end ORDER BY id DESC) sin modificar el SUBSTR. Para los precios, no hay que usar una longitud de 10 caracteres, sino de 5, y esta es la mayor debilidad del sistemita este.


En fin, sin más verborrea por mi parte, he aquí los datos agregados, in all their full glory:


hue@localhost:hue> -- weekly
hue@localhost:hue> SELECT id,
-> SUBSTR(GROUP_CONCAT(date_ini ORDER BY id ), 1, 10) date_ini, YEARWEEK(date_ini, 1) week_ini,
-> SUBSTR(GROUP_CONCAT(date_end ORDER BY id desc), 1, 10) date_end, YEARWEEK(date_end, 1) week_end,
-> SUBSTR(GROUP_CONCAT(open ORDER BY id), 1, 10) open,
-> MAX(high) high,
-> MIN(low) low,
-> SUBSTR(GROUP_CONCAT(close ORDER BY id DESC), 1, 5) close,
-> SUM(vol) vol
-> FROM data
-> GROUP BY week_ini;
+----+------------+----------+------------+----------+-------+-------+-------+-------+--------+
| id | date_ini | week_ini | date_end | week_end | open | high | low | close | vol |
+----+------------+----------+------------+----------+-------+-------+-------+-------+--------+
| 1 | 2009-08-27 | 200935 | 2009-08-30 | 200935 | 46.90 | 47.93 | 41.83 | 44.84 | 438278 |
| 11 | 2009-08-31 | 200936 | 2009-09-06 | 200936 | 43.45 | 48.25 | 41.82 | 43.00 | 738213 |
| 18 | 2009-09-07 | 200937 | 2009-09-13 | 200937 | 44.17 | 49.67 | 42.00 | 47.58 | 781974 |
| 25 | 2009-09-14 | 200938 | 2009-09-20 | 200938 | 47.73 | 49.52 | 44.30 | 47.08 | 793317 |
| 32 | 2009-09-21 | 200939 | 2009-09-27 | 200939 | 49.24 | 50.64 | 43.96 | 47.14 | 781979 |
| 39 | 2009-09-28 | 200940 | 2009-10-04 | 200940 | 47.79 | 50.48 | 45.09 | 48.69 | 774646 |
| 40 | 2009-10-05 | 200941 | 2009-10-05 | 200941 | 47.62 | 49.55 | 47.24 | 47.33 | 118031 |
+----+------------+----------+------------+----------+-------+-------+-------+-------+--------+
7 rows in set (0.00 sec)

hue@localhost:hue> -- monthly
hue@localhost:hue> SELECT id,
-> SUBSTR(GROUP_CONCAT(date_ini ORDER BY id ), 1, 10) date_ini, DATE_FORMAT(date_ini, '%Y%m') month_ini,
-> SUBSTR(GROUP_CONCAT(date_end ORDER BY id desc), 1, 10) date_end, DATE_FORMAT(date_end, '%Y%m') month_end,
-> SUBSTR(GROUP_CONCAT(open ORDER BY id), 1, 5) open,
-> MAX(high) high,
-> MIN(low) low,
-> SUBSTR(GROUP_CONCAT(close ORDER BY id DESC), 1, 5) close,
-> SUM(vol) vol
-> FROM data
-> GROUP BY month_ini;
+----+------------+-----------+------------+-----------+-------+-------+-------+-------+---------+
| id | date_ini | month_ini | date_end | month_end | open | high | low | close | vol |
+----+------------+-----------+------------+-----------+-------+-------+-------+-------+---------+
| 1 | 2009-08-27 | 200908 | 2009-08-31 | 200908 | 46.90 | 47.93 | 41.83 | 43.72 | 543893 |
| 27 | 2009-09-01 | 200909 | 2009-09-30 | 200909 | 45.89 | 50.64 | 41.82 | 47.21 | 3329587 |
| 36 | 2009-10-01 | 200910 | 2009-10-05 | 200910 | 50.40 | 50.48 | 45.09 | 47.33 | 552958 |
+----+------------+-----------+------------+-----------+-------+-------+-------+-------+---------+
3 rows in set (0.00 sec)

hue@localhost:hue> -- yearly
hue@localhost:hue> SELECT id,
-> SUBSTR(GROUP_CONCAT(date_ini ORDER BY id ), 1, 10) date_ini, YEAR(date_ini) year_ini,
-> SUBSTR(GROUP_CONCAT(date_end ORDER BY id desc), 1, 10) date_end, YEAR(date_end) year_end,
-> SUBSTR(GROUP_CONCAT(open ORDER BY id), 1, 5) open,
-> MAX(high) high,
-> MIN(low) low,
-> SUBSTR(GROUP_CONCAT(close ORDER BY id DESC), 1, 5) close,
-> SUM(vol) vol
-> FROM data
-> GROUP BY year_ini;
+----+------------+----------+------------+----------+-------+-------+-------+-------+---------+
| id | date_ini | year_ini | date_end | year_end | open | high | low | close | vol |
+----+------------+----------+------------+----------+-------+-------+-------+-------+---------+
| 1 | 2009-08-27 | 2009 | 2009-10-05 | 2009 | 46.90 | 50.64 | 41.82 | 47.33 | 4426438 |
+----+------------+----------+------------+----------+-------+-------+-------+-------+---------+
1 row in set (0.00 sec)

El weekly se comporta bien ante un cambio de año, como es preceptivo. En PostgreSQL no hay GROUP_CONCAT pero Google menciona algo en plan ARRAY(SELECT ...) que parece majete. Tampoco hay YEARWEEK ni DATE_FORMAT pero el primero se puede emular con el segundo, y para el segundo hay alternativa (aunque con una semántica distinta para numerar las semanas).


Me gustaría tener la posibilidad de agrupar según criterios un poquito más libres, en plan "de 2 en 2 meses" o "de 3 en 3 semanas". Aquí entra otro factor a considerar: ¿cuándo empieza un período? El de 2 meses es sencillo, puede empezar el 1 de Enero y sería bastante lógico, pero ¿y si determinamos 5 meses? Entonces ya no habría un número entero de períodos en un año, igual que con las 3 semanas, y se hace necesario (o conveniente cuando menos) determinar un punto inicial. Se podría, por ejemplo, empezar el grupo de 3 semanas en el primer Lunes que nos topemos, y el grupo de 5 meses en el primer día 1. Ojito, que ese Lunes y ese día 1 no tienen por qué ser días hábiles, y no aparecerían en la base de datos. Y después de todo eso, lo suyo sería implementarlo en SQL y tal...


La potencia de esto se ve realmente cuando insertamos un "CREATE VIEW weekly AS" delante de la consulta del weekly, y así sucesivamente.


20081208

En fins, sé tú mismo dicen por ahí...



INDICATIVO
Presente
Yo me descojorroncio
Tú te descojorroncias
Él se descojorroncia
Nosotros nos descojorronciamos
Vosotros os descojorronciáis
Ellos se descojorroncian

Pretérito imperfecto
Yo me descojorronciaba
Tú te descojorronciabas
Él se descojorronciaba
Nosotros nos descojorronciábamos
Vosotros os descojorronciábais
Ellos se descojorronciaban

Pretérito perfecto simple
Yo me descojorroncié
Tú te descojorronciaste
Él se descojorronció
Nosotros nos descojorronciamos
Vosotros os descojorronciasteis
Ellos se descojorronciaron

Condicional simple
Yo me descojorronciaría
Tú te descojorronciarías
Él se descojorronciaría
Nosotros nos descojorronciaríamos
Vosotros os descojorronciaríais
Ellos se descojorronciarían

Futuro simple
Yo me descojorronciaré
Tú te descojorronciarás
Él se descojorronciará
Nosotros nos descojorronciaremos
Vosotros os descojorronciaréis
Ellos se descojorronciarán

Pretérito perfecto compuesto
Yo me he descojorronciado
Tú te has descojorronciado
Él se ha descojorronciado
Nosotros nos hemos descojorronciado
Vosotros os habéis descojorronciado
Ellos se han descojorronciado

Pretérito pluscuamperfecto
Yo me había descojorronciado
Tú te habías descojorronciado
Él se había descojorronciado
Nosotros nos habíamos descojorronciado
Vosotros os habíais descojorronciado
Ellos se habían descojorronciado

Pretérito anterior
Yo me hube descojorronciado
Tú te hubiste descojorronciado
Él se hubo descojorronciado
Nosotros nos hubimos descojorronciado
Vosotros os hubisteis descojorronciado
Ellos se hubieron descojorronciado

Condicional compuesto
Yo me habría descojorronciado
Tú te habrías descojorronciado
Él se habría descojorronciado
Nosotros nos habríamos descojorronciado
Vosotros os habríais descojorronciado
Ellos se habrían descojorronciado

Futuro compuesto
Yo me habré descojorronciado
Tú te habrás descojorronciado
Él se habrá descojorronciado
Nosotros nos habremos descojorronciado
Vosotros os habréis descojorronciado
Ellos se habrán descojorronciado

SUBJUNTIVO
Presente
Yo me descojorroncie
Tú te descojorroncies
Él se descojorroncie
Nosotros nos descojorronciemos
Vosotros os descojorronciéis
Ellos se descojorroncien

Pretérito imperfecto
Yo me descojorronciara o descojorronciase
Tú te descojorronciaras o descojorronciases
Él se descojorronciara o descojorronciase
Nosotros nos descojorronciáramos o descojorronciásemos
Vosotros os descojorronciárais o descojorronciáseis
Ellos se descojorronciaran o descojorronciasen

Futuro
Yo me descojorronciere
Tú te descojorroncieres
Él se descojorronciere
Nosotros nos descojorronciéremos
Vosotros os descojorronciéreis
Ellos se descojorroncieren

Pretérito perfecto
Yo me haya descojorronciado
Tú te hayas descojorronciado
Él se haya descojorronciado
Nosotros nos hayamos descojorronciado
Vosotros os hayáis descojorronciado
Ellos se hayan descojorronciado

Pretérito pluscuamperfecto
Yo me hubiera o hubiese descojorronciado
Tú te hubieras o hubieses descojorronciado
Él se hubiera o hubiese descojorronciado
Nosotros nos hubiéramos o hubiésemos descojorronciado
Vosotros os hubiérais o hubiéseis descojorronciado
Ellos se hubieran o hubiesen descojorronciado

Futuro perfecto
Yo me hubiere descojorronciado
Tú te hubieres descojorronciado
Él se hubiere descojorronciado
Nosotros nos hubiéremos descojorronciado
Vosotros os hubiéreis descojorronciado
Ellos se hubieren descojorronciado

IMPERATIVO
Descojorrónciate tú (xD)
Descojorronciaos vosotros

FORMAS IMPERSONALES
Infinitivo
Descojorronciar

Gerundio
Descojorronciando

Participio
Descojorronciado

Infinitivo compuesto
Haber descojorronciado

Gerundio compuesto
Habiendo descojorronciado


20081119

Cansadito ya de perder algunos comandos tecleados en bash a causa de que se colgara la máquina y éstos no se guardaran en el .bash_history, he hecho un auto-save patatero:


export PROMPT_COMMAND='if [ 0 -eq $(( $(date +%s) % 10 )) ]; then history -a && echo History updated.; fi'

Lo que hace es que, cada vez que se va a mostrar el prompt, comprueba que el timestamp es divisible por 10; en tal caso hace un history -a y nos avisa. Con mi frecuencia de uso de la shell, el valor de 10 provoca que se guarde unas 3 veces durante una jornada de 8 horas, lo cual de momento voy a considerar como suficiente.


20080319

En cierta ocasión me vi baneado de un foro online y recurrí a una shell externa para seguir accediendo (en lugar de usar un proxy HTTP como la gente normal). En principio, bloqueé el acceso desde mi cacharro al foro, para no entrar por error y que ellos vieran caca en los logs:


# iptables -A OUTPUT -d ip.del.foro -j REJECT

A continuación, configuré que la dirección del foro resolviera a localhost:


# echo '127.0.0.1 foro.example.com' >> /etc/hosts

Y puse en mi router ADSL una reglita para que el tráfico entrante a determinado puerto (llamémosle 12345), me llegara al puerto 22 (ssh) del portátil (como un DNAT, vamos).


Todo esto lo hice una sola vez al principio y ahí se quedó. A continuación, cada vez que quería navegar el foro, realizaba estos pasos:


1.- Abrir un agujerito en el firewall del portátil:


# iptables -A INPUT -p tcp --dport 22 -j ACCEPT

2.- Entrar en la shell remota y levantar un pequeño ssh desde allí. Usamos el puerto 44744 porque somos usuario y no podemos usar el 80. Esto significa "Entrar al 12345 de mi casita (que está redirigido al 22 del portátil gracias al DNAT del ADSL) y levantar un túnel según el cual el puerto 44744 de localhost (en el portátil) va, a traves de este ssh, al 80 del foro". Técnicamente sí podemos hacer 'ssh root@casita' tras cambiar la configuración de ssh, y así haríamos el túnel directamente al 80 en lugar del al 44744, pero no.


remotessh.example.com:~ $ ssh -vp12345 -fNR 44744:foro.example.com:80 hue@adsl.de.mi.casita

3.- Chapar firewall de nuevo, ya no hace falta tenerlo abierto.


# iptables -D INPUT -p tcp --dport 22 -j ACCEPT

4.- A continuación, redirigir el 80 de localhost al 44744.


# iptables -t nat -A OUTPUT -d 127.0.0.1 -p tcp --dport 80 -j REDIRECT --to-ports 44744

5.- Y por último, levantar un navegata diferente al que uso. Con un usuario distinto y todo:


sux - luser iceweasel ## "iceweasel" == "firefox"

Al navegar a foro.example.com, los paquetes van a localhost:80, luego a localhost:44744, luego a remotessh y de ahí ya salen al foro real, que ve como IP origen la de remotessh. Obviamente, tuve que registrarme una cuenta nueva en el foro y todo eso.


Para dejar de navegar, tocaba hacer algo de limpieza:


# iptables -t nat -D OUTPUT -d 127.0.0.1 -p tcp --dport 80 -j REDIRECT --to-ports 44744
remotessh.example.com:~ $ killall ssh

Y luego, cuando perdí interés en el foro y dejé de navegarlo, deshice los pasos preliminares; esto es, quité la entrada en /etc/hosts y borré la regla de firewall que me impedía ir al foro por error.


20070817

Sin dejar de ser una buena idea, pienso que apt-get autoclean borra más cosas de las que debería. Me ha pasado varias veces que al actualizar el sistema (unstable) me aparecía algún paquete roto y, por la ley de Murphy, al ir a buscar la versión anterior en el caché de apt, resulta que ya no estaba allí. Y claro, si no estaba allí es que ya no se puede bajar del repo (precisamente que ya no se pueda bajar es la condición que hace a apt-get borrar el archivo). Es decir, que si ya lo tengo no necesito bajarlo pero si no lo tengo, tampoco puedo. Ilógico, verdad?


Bueno, pues apt-get-autoclean.pl. La función sortable_ver transforma la versión de los paquetes en una cadena que se ordene sola usando cmp. Hay un bug ("1:0.7.3-1.2" aparece antes que "1:0.7.3-1+b1", lo cual debería ser al revés según dpkg --compare-versions), pero lo voy a dejar estar. Ni que decir tiene que hay varias cosas mejorables. Y por supuesto, no warranty bla bla bla.


#!/usr/bin/perl

use strict;
use warnings;

my %pkg;
my $versions_to_keep = 3; ## <-- configure this
my @files_to_delete;

sub sortable_ver {
my $v = shift;
my $pre = "";
## isolate epoch
if ($v =~ /^(\d+)%3a(.*)/) { $pre = sprintf "%02d%%3a", $1; $v = $2; }
$v =~ s/(\d+)/sprintf "%08d", $1/eg;
$v =~ s/\W/_/g;
return $pre.$v; ## restore epoch
}

chdir '/var/cache/apt/archives' or die "chdir: $!";
/([^_]+)_([^_]+)/ and push @{$pkg{$1}}, $2 for <*deb>;
foreach my $p (keys %pkg) {
if ($versions_to_keep >= @{$pkg{$p}}) { delete $pkg{$p}; next; }
push @files_to_delete, <${p}_${_}_*>
foreach (sort {
(sortable_ver $a) cmp (sortable_ver $b)
} @{$pkg{$p}})[0 .. $#{$pkg{$p}}-$versions_to_keep];
}
{
local $" = "\n";
print "About to delete the following files:\n@{[sort @files_to_delete]}\n\n" .
"Type 'yes' if this is correct: ";
}
my $input = <>; chomp $input;
unlink @files_to_delete or die "unlink: $!" if $input =~ /^yes$/i;

20070716

Dicen que más vale tarde que nunca... bueno, acabo de descubrir xcompmgr :^). Este es mi pequeña modificación para dar a las ventanas un valor de transparencia por defecto. Tiene en cuenta el hecho de que la ventana de xscreensaver debería ser siempre opaca ;^). Es para xcompmgr-1.1.3.


--- xcompmgr.c.orig 2007-07-16 11:32:08.000000000 +0200
+++ xcompmgr.c 2007-07-16 11:59:02.000000000 +0200
@@ -39,6 +39,7 @@
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
+#include <X11/Xmu/WinUtil.h>
#include <X11/extensions/Xcomposite.h>
#include <X11/extensions/Xdamage.h>
#include <X11/extensions/Xrender.h>
@@ -186,6 +187,7 @@
double fade_out_step = 0.03;
int fade_delta = 10;
int fade_time = 0;
+double default_opacity = 0.8;
Bool fadeWindows = False;
Bool excludeDockShadows = False;
Bool fadeTrans = False;
@@ -1332,7 +1334,7 @@
{
int mode;
XRenderPictFormat *format;
- unsigned int default_opacity;
+ /*unsigned int default_opacity;*/ /* hue: this is unused so let's comment it just in case */

/* if trans prop == -1 fall back on previous tests*/

@@ -1412,6 +1414,27 @@
return winNormalAtom;
}

+unsigned int
+get_default_opacity (Display *dpy, Window w)
+{
+ double ret = 0;
+
+ Window client = XmuClientWindow (dpy, w);
+ XTextProperty foo;
+ if (XGetWMName (dpy, client, &foo)) {
+ /* hue: override default opacity for specific applications */
+ /* pro[bv]ably better with strncmp() */
+ if (!strcmp (foo.value, "gkrellm")) { ret = 1.0; }
+ if (!strcmp (foo.value, "screensaver")) { ret = 1.0; }
+ if (foo.value) XFree ((char *)foo.value);
+ }
+
+ if (!ret)
+ ret = default_opacity;
+
+ return (unsigned int)(ret * OPAQUE);
+}
+
static void
add_win (Display *dpy, Window id, Window prev)
{
@@ -1462,13 +1485,16 @@
new->shadow_dy = 0;
new->shadow_width = 0;
new->shadow_height = 0;
- new->opacity = OPAQUE;
+ new->opacity = get_default_opacity (dpy, new->id);

new->borderClip = None;
new->prev_trans = 0;

/* moved mode setting to one place */
- new->opacity = get_opacity_prop (dpy, new, OPAQUE);
+ new->opacity = get_opacity_prop (dpy, new, get_default_opacity (dpy, new->id));
+ /* hue: ripped from transset-df-5/transSet.c */
+ XChangeProperty(dpy, new->id, XInternAtom(dpy, OPACITY_PROP, False), XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &new->opacity, 1L);
+ XSync(dpy, False);
new->windowType = determine_wintype (dpy, new->id);
determine_mode (dpy, new);

@@ -1849,6 +1875,7 @@
fprintf (stderr, " -I fade-in-step\n Specifies the opacity change between steps while fading in. (default 0.028)\n");
fprintf (stderr, " -O fade-out-step\n Specifies the opacity change between steps while fading out. (default 0.03)\n");
fprintf (stderr, " -D fade-delta-time\n Specifies the time between steps in a fade in milliseconds. (default 10)\n");
+ fprintf (stderr, " -N default-opacity\n Specifies the default opacity for new windows. (default 0.8)\n");
fprintf (stderr, " -a\n Use automatic server-side compositing. Faster, but no special effects.\n");
fprintf (stderr, " -c\n Draw client-side shadows with fuzzy edges.\n");
fprintf (stderr, " -C\n Avoid drawing shadows on dock/panel windows.\n");
@@ -1896,7 +1923,7 @@
char *display = 0;
int o;

- while ((o = getopt (argc, argv, "D:I:O:d:r:o:l:t:scnfFCaS")) != -1)
+ while ((o = getopt (argc, argv, "N:D:I:O:d:r:o:l:t:scnfFCaS")) != -1)
{
switch (o) {
case 'd':
@@ -1917,6 +1944,11 @@
if (fade_out_step <= 0)
fade_out_step = 0.01;
break;
+ case 'N':
+ default_opacity = atof (optarg);
+ if (default_opacity <= 0)
+ default_opacity = 0.01;
+ break;
case 's':
compMode = CompServerShadows;
break;


20070704

Sigo dándole caña al $PS1. Hace tiempo tenía un hack que averiguaba cuál era el directorio padre del actual, y mostraba en el prompt sólo estos dos (el padre y el actual), no el path entero, lo cual es útil al trabajar en sitios con un nombre muy largo. Eventualmente lo quité y pasó algún tiempo hasta que ayer me puse a reimplementarlo de forma que el número de componentes del directorio actual fuera modificable fácilmente. Este es el archivo donde defino $PS1:



function num_path_components() {
local -a ARRAY
CONCAT="$*"
IFS=/ read -a ARRAY <<< "${CONCAT#/}"
#echo "num_path_components: concat ($CONCAT) array (${ARRAY[*]})" > $(tty)
echo ${#ARRAY[*]}
}

## to control if $PS1 will have the \[ \] sequences
## it seems that they aren't needed if running with a UTF-8 locale
## I'm not bothering detecting that condition here
DELIMIT_NONPRINTABLE=0
if [[ $DELIMIT_NONPRINTABLE -gt 0 ]]; then
export NORMAL=$'\[\x1b[0m\]'
export RED=$'\[\x1b[0;31m\]'
export GREEN=$'\[\x1b[0;32m\]'
else
export NORMAL=$'\x1b[0m'
export RED=$'\x1b[0;31m'
export GREEN=$'\x1b[0;32m'
fi

## several definitions of PS1 follow. The last is the one that remains

export PS1=" (blah blah blah) "

export PS1='$NORMAL\
\u@\h \
e$(
## dont use $() before this one, or the error code will be altered
E=$?
if [ $E -eq 0 ]; then
C=""
N=""
else
C=$RED
N=$NORMAL
fi
echo $C$E$N
) \
m$(
MAILS=0
if [ -f $MAIL ]; then
while read LINE; do
if [[ $LINE =~ "^From " ]]; then
MAILS=$(($MAILS + 1))
fi
done < $MAIL
fi
if [ $MAILS -eq 0 ]; then
C=""
N=""
else
C=$RED
N=$NORMAL
fi
echo $C$MAILS$N
) \
l$(
read one rest < /proc/loadavg
hundred=${one/./}
if [ $hundred -gt 199 ]; then
C=$RED
N=$NORMAL
else
C=""
N=""
fi
echo $C$one$N
) j\j \D{%H%M%S%z} \
$(
if [[ $PWD == / ]]; then ## workaround to avoid empty resulting output
echo $PWD
else
LEN=$(num_path_components $PWD)
LEN_HOME=$(num_path_components $HOME)
STRIPPED_ELEMS=$(( $LEN - $HUE_PATH_ELEMS ))

## if we are under $HOME and the number of stripped elements is
## less than or equal to the size of $HOME, then we are stripping
## part of $HOME, or the whole $HOME but not anything more, so we
## can return a tilde-compressed $PWD in order to obtain a fully
## qualified path. As a bonus, most of the time this will yield a
## shorter result.
##
## BUG: when $HOME == /, the result lacks a slash after the tilde.
## Since users having / as $HOME should not have a fancy $PS1, this
## does not matter much.
if [[ $PWD =~ ^$HOME && $STRIPPED_ELEMS -le $LEN_HOME ]]; then
#echo "len ($LEN) len_home ($LEN_HOME) elems ($HUE_PATH_ELEMS) stripped ($STRIPPED_ELEMS)" > $(tty)
echo ${PWD/#$HOME/\~}
else
RESULT=
IFS=/ read -a ELEMS <<< "${PWD#/}"
#echo "all (${ELEMS[*]})" > $(tty)
#echo "len ($LEN) len_home ($LEN_HOME) elems ($HUE_PATH_ELEMS) stripped ($STRIPPED_ELEMS)" > $(tty)

for ((I=$LEN-1, J=HUE_PATH_ELEMS-1; I>=0 && J>=0; I--, J--)); do
#echo "loop i ($I) j ($J) word (${ELEMS[$I]})" > $(tty)
RESULT="/${ELEMS[$I]}$RESULT"
done

## add leading slash if the resulting path is (almost) fully qualified
[[ $HUE_PATH_ELEMS -lt $LEN ]] && RESULT=${RESULT#/}
echo ${RESULT/#$HOME/\~}
fi
fi
) \
$(
if [ $UID -eq 0 ]; then
C=$RED
else
C=$GREEN
fi
N=$NORMAL
echo $C\$$N
) '

export -n NORMAL RED GREEN


Funciona con una variable de entorno, que no está definida en este mismo archivo. He aquí algunos ejemplillos, tanto de esto como de lo que tenía también hasta ahora. Se va a salir de la pantalla en la mayoría de los casos pero bueno...



hue@hue e0 m0 l0.01 j1 102848+0100 ~ $ jobs
[1]+ Stopped vim -X -o
hue@hue e0 m0 l0.00 j1 102917+0100 ~ $ echo "From foo" > $MAIL
You have new mail in /var/mail/hue
hue@hue e0 m1 l0.00 j1 102943+0100 ~ $ : > $MAIL
hue@hue e0 m0 l0.00 j1 102958+0100 ~ $ cat > busy-wait.c
int main(void) { while (1); return 0; }
hue@hue e0 m0 l0.07 j1 103015+0100 ~ $ make busy-wait
cc -mfpmath=sse -msse2 -mmmx busy-wait.c -o busy-wait
hue@hue e0 m0 l0.07 j1 103019+0100 ~ $ ./busy-wait &
[2] 8626
hue@hue e0 m0 l0.06 j2 103026+0100 ~ $ ./busy-wait &
[3] 8634
hue@hue e0 m0 l0.14 j3 103027+0100 ~ $ ./busy-wait &
[4] 8642
hue@hue e0 m0 l0.14 j4 103029+0100 ~ $ sleep 30
hue@hue e0 m0 l1.40 j4 103105+0100 ~ $ sleep 30
hue@hue e0 m0 l2.11 j4 103140+0100 ~ $ killall busy-wait; false
[3] Terminated ./busy-wait
[4]- Terminated ./busy-wait
[2]- Terminated ./busy-wait
hue@hue e1 m0 l2.18 j1 103146+0100 ~ $

hue@hue e0 m0 l0.01 j1 105255+0100 ~ $ echo $HUE_PATH_ELEMS $HOME $PWD
3 /home/hue /home/hue
hue@hue e0 m0 l0.01 j1 105259+0100 ~ $ cd ..
hue@hue e0 m0 l0.01 j1 105303+0100 /home $ cd hue/tmp/this/is/a/deep/dir
hue@hue e0 m0 l0.01 j1 105306+0100 a/deep/dir $ cd ..
hue@hue e0 m0 l0.00 j1 105310+0100 is/a/deep $ HUE_PATH_ELEMS=4
hue@hue e0 m0 l0.00 j1 105313+0100 this/is/a/deep $ HUE_PATH_ELEMS=5
hue@hue e0 m0 l0.00 j1 105315+0100 ~/tmp/this/is/a/deep $ HUE_PATH_ELEMS=6
hue@hue e0 m0 l0.00 j1 105318+0100 ~/tmp/this/is/a/deep $ cd /media/xp/Documents\ and\ Settings/All\ Users/Start\ Menu/Programs
hue@hue e0 m0 l0.00 j1 105330+0100 /media/xp/Documents and Settings/All Users/Start Menu/Programs $ cd Launch\ Manager
hue@hue e0 m0 l0.07 j1 105355+0100 xp/Documents and Settings/All Users/Start Menu/Programs/Launch Manager $ HUE_PATH_ELEMS=1
hue@hue e0 m0 l0.07 j1 105401+0100 Launch Manager $ HUE_PATH_ELEMS=2
hue@hue e0 m0 l0.06 j1 105403+0100 Programs/Launch Manager $ HUE_PATH_ELEMS=3
hue@hue e0 m0 l0.06 j1 105409+0100 Start Menu/Programs/Launch Manager $



20070616

El /etc/sudoers es otra de esas cosas que tampoco me he aprendido de memoria, así que he aquí una mini referencia para cuando tenga que configurarlo y no pueda copy pastear de ningún sitio:


Host_Alias H1 = hostname, 172.16.16.16, *.net
Host_Alias H2 = 10.0.0.0/16, !10.0.10.10

User_Alias U1 = %lusers
User_Alias U2 = %lusers, !someone

Cmnd_Alias C1 = /path/to/foo --param1, /path/to/bar
Cmnd_Alias C2 = /path/to/baz --param2 *

Defaults mail_badpass, mail_no_host, mail_no_perms, tty_tickets, \
requiretty, !env_editor, env_check="FOO BAR", env_reset, \
passwd_tries=2, timestamp_timeout=5, passwd_timeout=1, !umask, \
editor=/usr/bin/foo:/usr/bin/bar, !rootpw, !runaspw, !targetpw, \
!noexec, logfile=/path/to/baz.log
Defaults@host param+=value
Defaults:user param-=value
Defaults>runas !param

## esto va después de los Defaults, ya que runas_default debe
## configurarse antes de los Runas_Alias
Runas_Alias R1 = user
Runas_Alias R2 = %lusers, !#1000

U1 H1 = (R1) NOPASSWD: C1, (R2) PASSWD: C2 : H2 = (R2) NOPASSWD: NOEXEC: C2

20070602

$ ssh root@192.168.1.19
Password:

BusyBox v1.1.3 (Debian 3:1.1.3-3.osso17) Built-in shell (ash)
Enter 'help' for a list of built-in commands.

# uname -a
Linux Nokia-N800-10 2.6.18-omap1 #2 Wed Mar 7 15:36:09 EET 2007 armv6l unknown

# cat /proc/cpuinfo
Processor : Some Random V6 Processor rev 2 (v6l)
BogoMIPS : 320.37
Features : swp half thumb fastmult vfp edsp java
CPU implementer : 0x41
CPU architecture: 6TEJ
CPU variant : 0x0
CPU part : 0xb36
CPU revision : 2
Cache type : write-back
Cache clean : cp15 c7 ops
Cache lockdown : format C
Cache format : Harvard
I size : 32768
I assoc : 4
I line length : 32
I sets : 256
D size : 32768
D assoc : 4
D line length : 32
D sets : 256

Hardware : Nokia N800
Revision : 24202524
Serial : 0000000000000000

# free
total used free shared buffers
Mem: 127252 96628 30624 0 756
Swap: 131064 0 131064
Total: 258316 96628 161688

# mount
/dev/root on /mnt/initfs type jffs2 (rw)
none on /mnt/initfs/proc type proc (rw)
none on /mnt/initfs/sys type sysfs (rw)
none on /mnt/initfs/tmp type tmpfs (rw)
/dev/mtdblock4 on / type jffs2 (rw,rpsize=1024,rpuid=0,rpuid=30000)
none on /tmp type tmpfs (rw)
proc on /proc type proc (rw)
sysfs on /sys type sysfs (rw)
none on /dev type tmpfs (rw)
devpts on /dev/pts type devpts (rw)
/dev/mmcblk1p1 on /media/mmc1 type vfat (rw,noauto,nodev,noexec,nosuid,utf8,uid=29999, shortname=mixed,ro,nosuid,nodev,noexec,sync,noatime,nodiratime)
/dev/mmcblk0p1 on /media/mmc2 type vfat (rw,noauto,nodev,noexec,nosuid,utf8,uid=29999, shortname=mixed,ro,nosuid,nodev,noexec,sync,noatime,nodiratime)

# df
Filesystem 1k-blocks Used Available Use% Mounted on
/dev/mtdblock4 2048 2048 0 100% /mnt/initfs
none 512 80 432 16% /mnt/initfs/tmp
/dev/mtdblock4 257536 167452 90084 65% /
none 512 80 432 16% /tmp
none 1024 64 960 6% /dev
/dev/mmcblk1p1 1984736 298240 1686496 15% /media/mmc1
/dev/mmcblk0p1 500748 153312 347436 31% /media/mmc2

# ifconfig -a
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:178 errors:0 dropped:0 overruns:0 frame:0
TX packets:178 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:112435 (109.7 KiB) TX bytes:112435 (109.7 KiB)

wlan0 Link encap:Ethernet HWaddr 00:19:4F:9E:9A:29
inet addr:192.168.1.19 Bcast:192.168.1.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:11538 errors:0 dropped:0 overruns:0 frame:0
TX packets:8012 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:1944975 (1.8 MiB) TX bytes:1559233 (1.4 MiB)

# hciconfig
hci0: Type: UART
BD Address: 00:19:4F:A4:B4:A9 ACL MTU: 384:4 SCO MTU: 64:8
UP RUNNING PSCAN ISCAN
RX bytes:894 acl:0 sco:0 events:16 errors:0
TX bytes:1114 acl:0 sco:0 commands:16 errors:0

# iwconfig
lo no wireless extensions.

wlan0 IEEE 802.11b/g ESSID:"ESSID"
Mode:Managed Frequency:2.437 GHz Access Point: ff:ff:ff:ff:ff:ff
Bit Rate=54 Mb/s Tx-Power=19 dBm Sensitivity=0/200
RTS thr=2347 B Fragment thr=2346 B
Encryption key:ffff-ffff-ffff-ffff-ffff-ffff-ff Security mode:restricted
Power Management:on
Link Quality:61/0 Signal level:-31 dBm Noise level:-92 dBm
Rx invalid nwid:0 Rx invalid crypt:0 Rx invalid frag:0
Tx excessive retries:0 Invalid misc:0 Missed beacon:0

# less /var/log/dmesg ## hubo que tocar bajo /etc/init.d, puesto que no existe por defecto
Linux version 2.6.18-omap1 (root@bifh.research.nokia.com) (gcc version 3.4.4 (release) (CodeSourcery
ARM 2005q 3-2)) #2 Wed Mar 7 15:36:09 EET 2007
CPU: Some Random V6 Processor [4107b362] revision 2 (ARMv6TEJ), cr=00c5387f
Machine: Nokia N800
Memory policy: ECC disabled, Data cache writeback
On node 0 totalpages: 32768
DMA zone: 32768 pages, LIFO batch:7
OMAP24205
Reserving 462848 bytes SRAM for frame buffer
SRAM: Mapped pa 0x40200000 to va 0xd0000000 size: 0x100000
Reserving 1540096 bytes SDRAM for frame buffer
CPU0: D VIPT write-back cache
CPU0: I cache: 32768 bytes, associativity 4, 32 byte lines, 256 sets
CPU0: D cache: 32768 bytes, associativity 4, 32 byte lines, 256 sets
Built 1 zonelists. Total pages: 32768
Kernel command line: root=1f03 rootfstype=jffs2
Clocking rate (Crystal/DPLL/MPU): 19.2/658/329 MHz
clock.c: Enable for dpll_ck without enable code
GPMC revision 2.0
IRQ: Found an INTC at 0xd80fe000 (revision 2.0) with 96 interrupts
Total of 96 interrupts on 1 active controller
OMAP24xx GPIO hardware version 1.8
PID hash table entries: 1024 (order: 10, 4096 bytes)
Console: colour dummy device 80x30
Dentry cache hash table entries: 16384 (order: 4, 65536 bytes)
Inode-cache hash table entries: 8192 (order: 3, 32768 bytes)
Memory: 64MB 64MB = 128MB total
Memory: 127104KB available (2177K code, 460K data, 108K init)
Calibrating delay loop... 320.37 BogoMIPS (lpj=1253376)
Security Framework v1.0.0 initialized
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
NET: Registered protocol family 16
TUSB 6010
OMAP DMA hardware revision 2.0
omap_dsp_init() done
USB: No board-specific platform config found
OMAP STI support loaded (HW v1.0)
[ 5727.591552] i2c_omap i2c_omap.2: bus 1 rev3.4 at 100 kHz
[ 5727.592224] i2c_omap i2c_omap.1: bus 0 rev3.4 at 100 kHz
[ 5727.592864] Tahvo/Betty driver initialising
[ 5727.593780] Betty v2.1 found
[ 5727.594299] Retu/Vilma driver initialising
[ 5727.595184] Vilma v1.5 found
[ 5727.596954] SCSI subsystem initialized
[ 5727.597167] OMAP24xx McSPI driver initializing
[ 5727.599822] musb_hdrc: version 2.2a/db-0.5.1/dbg, tusb-omap-dma, peripheral, debug=1
[ 5727.611206] tusb: Revisions: prcm2.0 int2.0 gpio2.0 dma2.0
[ 5727.611328] drivers/usb/musb/tusb6010.c musb_platform_disable: dma still active
[ 5727.611419] musb_hdrc: ConfigData=0x06 (UTMI-8, dyn FIFOs, SoftConn)
[ 5727.611450] musb_hdrc: MHDRC RTL version 1.400
[ 5727.611480] musb_hdrc: setup fifo_mode 3
[ 5727.611541] musb_hdrc: 7/31 max ep, 3648/16384 memory
[ 5727.611572] musb_hdrc: hw_ep 0shared, max 64
[ 5727.611602] musb_hdrc: hw_ep 1tx, doublebuffer, max 512
[ 5727.611633] musb_hdrc: hw_ep 1rx, doublebuffer, max 512
[ 5727.611694] musb_hdrc: hw_ep 2tx, max 512
[ 5727.611724] musb_hdrc: hw_ep 2rx, max 512
[ 5727.611755] musb_hdrc: hw_ep 3shared, max 256
[ 5727.611785] musb_hdrc: hw_ep 4shared, max 256
[ 5727.611846] musb_hdrc: USB Peripheral mode controller at c8812000 using DMA, IRQ 218
[ 5727.612030] musb_init_controller 1797: PERIPHERAL mode, status 0, dev80
[ 5727.612091] Registered /proc/driver/musb_hdrc
[ 5727.612487] Bluetooth: Core ver 2.10
[ 5727.613220] NET: Registered protocol family 31
[ 5727.613281] Bluetooth: HCI device and connection manager initialized
[ 5727.613342] Bluetooth: HCI socket layer initialized
[ 5727.616394] NET: Registered protocol family 2
[ 5727.681793] IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
[ 5727.682495] TCP established hash table entries: 4096 (order: 2, 16384 bytes)
[ 5727.682739] TCP bind hash table entries: 2048 (order: 1, 8192 bytes)
[ 5727.682891] TCP: Hash tables configured (established 4096 bind 2048)
[ 5727.682952] TCP reno registered
[ 5727.684143] NetWinder Floating Point Emulator V0.97 (double precision)
[ 5727.684661] dsp dsp: OMAP DSP driver initialization
[ 5727.699554] JFFS2 version 2.2. (NAND) (SUMMARY) (C) 2001-2006 Red Hat, Inc.
[ 5727.700714] lowmem: Module initialized.
[ 5727.700805] io scheduler noop registered (default)
[ 5727.701812] omapfb: ls041y3 rev 8f LCD detected
[ 5727.702178] omapfb: configured for panel ls041y3
[ 5727.713500] omapfb: DISPC version 2.0 initialized
[ 5727.713684] omapfb: RFBI version 1.0 initialized
[ 5727.736328] omapfb: s1d13745 LCD controller rev 1 initialized (CNF pins 3)
[ 5727.736511] omapfb omapfb: s1d1374x: setting update mode to manual
[ 5727.738037] omapfb: Framebuffer initialized. Total vram 2002944 planes 3
[ 5727.738128] omapfb: Pixclock 21940 kHz hfreq 24.9 kHz vfreq 51.0 Hz
[ 5727.762359] OMAP Watchdog Timer: initial timeout 60 sec
[ 5727.769012] RAMDISK driver initialized: 16 RAM disks of 4096K size 1024 blocksize
[ 5727.772155] loop: loaded (max 8 devices)
[ 5727.773132] PPP generic driver version 2.4.2
[ 5727.773681] PPP Deflate Compression module registered
[ 5727.773742] PPP BSD Compression module registered
[ 5727.773803] tun: Universal TUN/TAP device driver, 1.6
[ 5727.773864] tun: (C) 1999-2004 Max Krasnyansky
[ 5727.774291] Linux video capture interface: v2.00
[ 5727.786376] FCLK = 96000000 [96000000], usecount = 1
[ 5727.786926] omap24xxcam: registered device video0 [v4l2]
[ 5727.792022] tea5761 0-0010: tea5761 (version 7) detected at 0-0010
[ 5727.795440] Menelaus rev 2.2
[ 5727.795928] menelaus: Setting VCORE FLOOR to 1050 mV and ROOF to 1400 mV
[ 5727.806793] menelaus: regulator sleep configuration: ff
[ 5727.807586] Retu power button driver initialized
[ 5727.807647] retu: Registering interrupt 0 for device PwrOnX
[ 5727.808410] input: retu-pwrbutton as /class/input/input0
[ 5727.809417] retu: Registering interrupt 2 for device RTCS
[ 5727.809631] retu: Registering interrupt 5 for device RTCA
[ 5727.810729] Retu watchdog driver initialized
[ 5727.810821] Retu/Vilma headset driver initializing
[ 5727.811737] input: retu-headset as /class/input/input1
[ 5727.811889] retu: Registering interrupt 6 for device hookdet
[ 5727.812866] OMAP2 OneNAND driver initializing
[ 5727.813537] omap2-onenand omap2-onenand: initializing on CS0, phys base 0x04000000, virtual base c8880000
[ 5727.813659] OneNAND Manufacturer: Samsung (0xec)
[ 5727.813690] Muxed OneNAND(DDP) 256MB 1.8V 16-bit (0x48)
[ 5727.813751] OneNAND version = 0x0011
[ 5727.832885] Scanning device for bad blocks
[ 5727.865814] onenand_wait: controller error = 0x2400
[ 5727.865875] onenand_read_oob: read failed = 0x2400
[ 5727.865905] Bad eraseblock 1257 at 0x09d20000
[ 5727.886077] Creating 5 MTD partitions on "omap2-onenand":
[ 5727.886138] 0x00000000-0x00020000 : "bootloader"
[ 5727.887420] 0x00020000-0x00080000 : "config"
[ 5727.888610] 0x00080000-0x00280000 : "kernel"
[ 5727.889739] 0x00280000-0x00480000 : "initfs"
[ 5727.890960] 0x00480000-0x10000000 : "rootfs"
[ 5727.893463] TSC2301 driver initializing
[ 5727.909057] input: TSC2301 keypad as /class/input/input2
[ 5727.909881] input: TSC2301 touchscreen as /class/input/input3
[ 5727.910827] mice: PS/2 mouse device common for all mice
[ 5727.912353] tmp105: initializing
[ 5727.913208] menelaus: Setting voltage 'VAUX' to 2800 mV (reg 0x0a, val 0xb8)
[ 5727.924041] tmp105: found at address 0x48
[ 5727.963867] hci_h4p hci_h4p: Registering HCI H4P device
[ 5728.192718] menelaus: Setting voltage 'VMMC' to 3100 mV (reg 0x0a, val 0xf8)
[ 5728.205963] mmci-omap mmci-omap.1: cover is now closed
[ 5728.206298] omap_pwm_led omap_pwm_led: OMAP PWM LED (keypad) at GP timer 10/9
[ 5728.206726] Registered led device: keypad
[ 5728.221069] Advanced Linux Sound Architecture Driver Version 1.0.12rc1 (Thu Jun 22 13:55:50 2006 UTC).
[ 5728.221740] omap24xx-eac omap24xx-eac: EAC version: 1.0
[ 5728.224914] ALSA device list:
[ 5728.224975] #0: OMAP24xx EAC with codec TSC2301
[ 5728.225036] Netfilter messages via NETLINK v0.30.
[ 5728.225158] ip_tables: (C) 2000-2006 Netfilter Core Team
[ 5728.286437] menelaus: Setting voltage 'VMMC' to 2800 mV (reg 0x0a, val 0x78)
[ 5728.299102] TCP bic registered
[ 5728.299285] NET: Registered protocol family 1
[ 5728.299346] NET: Registered protocol family 17
[ 5728.299438] Bluetooth: L2CAP ver 2.8
[ 5728.299468] Bluetooth: L2CAP socket layer initialized
[ 5728.299530] Bluetooth: SCO (Voice Link) ver 0.5
[ 5728.299560] Bluetooth: SCO socket layer initialized
[ 5728.299682] Bluetooth: RFCOMM socket layer initialized
[ 5728.299804] Bluetooth: RFCOMM TTY layer initialized
[ 5728.299865] Bluetooth: RFCOMM ver 1.8
[ 5728.299926] Bluetooth: BNEP (Ethernet Emulation) ver 1.2
[ 5728.299957] Bluetooth: HIDP (Human Interface Emulation) ver 1.1-mh1
[ 5728.300018] Power Management for OMAP2 initializing
[ 5728.300079] PRCM revision 1.0
[ 5728.300201] VFP support v0.3: implementor 41 architecture 1 part 20 variant b rev 2
[ 5728.300323] Disabling unused clock "uart3_fck"
[ 5728.300384] Disabling unused clock "uart3_ick"
[ 5728.300415] Disabling unused clock "uart2_fck"
[ 5728.300445] Disabling unused clock "uart2_ick"
[ 5728.300506] Disabling unused clock "gpt12_fck"
[ 5728.300537] Disabling unused clock "gpt12_ick"
[ 5728.300598] Disabling unused clock "gpt11_fck"
[ 5728.300628] Disabling unused clock "gpt11_ick"
[ 5728.300689] Disabling unused clock "gpt8_fck"
[ 5728.300720] Disabling unused clock "gpt8_ick"
[ 5728.300781] Disabling unused clock "gpt7_fck"
[ 5728.300811] Disabling unused clock "gpt7_ick"
[ 5728.300842] Disabling unused clock "gpt6_fck"
[ 5728.300903] Disabling unused clock "gpt6_ick"
[ 5728.300933] Disabling unused clock "gpt5_fck"
[ 5728.300994] Disabling unused clock "gpt5_ick"
[ 5728.301025] Disabling unused clock "gpt4_fck"
[ 5728.301086] Disabling unused clock "gpt4_ick"
[ 5728.301116] Disabling unused clock "gpt3_fck"
[ 5728.301147] Disabling unused clock "gpt3_ick"
[ 5728.301208] Disabling unused clock "gpt2_fck"
[ 5728.301239] Disabling unused clock "gpt2_ick"
[ 5728.301300] Disabling unused clock "dss2_fck"
[ 5728.301971] Bootup reason: sw_rst
[ 5728.302093] OMAP GPIO switch handler initializing
[ 5728.304931] headphone (GPIO 107) is now disconnected
[ 5728.305023] cam_turn (GPIO 12) is now inactive
[ 5728.305053] cam_act (GPIO 95) is now inactive
[ 5728.305114] bat_cover (GPIO 110) is now closed
[ 5728.305358] OMAP Random Number Generator ver. 40
[ 5728.305664] 128 words of entropy generated
[ 5728.305725] FCLK = 96000000 [96000000], usecount = 1
[ 5728.305908] mmci-omap mmci-omap.1: cover is now closed
[ 5728.306274] menelaus: Setting voltage 'VMEM' to 1500 mV (reg 0x0a, val 0x78)
[ 5728.338134] menelaus: Setting voltage 'VIO' to 2500 mV (reg 0x0a, val 0x78)
[ 5728.375030] mmcblk0: mmc0:0001 AF HMP 501760KiB
[ 5728.375366] mmcblk0: p1
[ 5728.379119] menelaus: Setting voltage 'VDCDC3' to 3300 mV (reg 0x07, val 0x39)
[ 5728.471557] menelaus: Setting voltage 'VDCDC3' to 2800 mV (reg 0x07, val 0x29)
[ 5728.479614] tcm825x_find_size(): size 3
[ 5728.479644] tcm825xsensor_try_format(): isize = 3 num_capture = 2
[ 5728.479675] tcm825xsensor_try_format(): format = 0x50424752
[ 5728.479705] Sensor is TCM825x
[ 5728.510009] menelaus: Setting voltage 'VIO' to 0 mV (reg 0x0a, val 0x70)
[ 5728.541259] menelaus: Setting voltage 'VMEM' to 0 mV (reg 0x0a, val 0x70)
[ 5728.874206] VFS: Mounted root (jffs2 filesystem).
[ 5728.874572] Freeing init memory: 108K
[ 5728.933990] mmcblk1: mmc1:8001 SD02G 1985024KiB
[ 5728.934326] mmcblk1: p1
[ 5729.204956] mmci-omap mmci-omap.1: card status error (CMD13)
[ 5730.014923] umac: module license 'Proprietary' taints kernel.
[ 5730.167388] CX3110x chip variant: STLC4550
[ 5730.248077] CX3110x: firmware version: 2.13.0.0.a.22.4
[ 5730.263854] Loaded CX3110x driver, version 0.8
[ 5734.372070] tahvo: Registering interrupt 7 for device
[ 5734.372558] retu: Registering interrupt 8 for device
[ 5734.373382] retu: Registering interrupt 1 for device
[ 5734.373779] tahvo: Registering interrupt 1 for device

# cat /etc/debian_version
testing/unstable

# dpkg -l | wc -l
1489

# cat sources.list
#maemo:name Nokia Catalogue
#maemo:essential
deb http://catalogue.tableteer.nokia.com/certified/ bora user
#maemo:name Nokia Catalogue (3rd party software)
deb http://catalogue.tableteer.nokia.com/non-certified/ bora user
#maemo:name Maemo Repository
deb http://repository.maemo.org bora free non-free extras
#maemo:name Maemo extras
deb http://repository.maemo.org/extras bora free non-free
#maemo:name kernel concepts
deb http://downloads.kernelconcepts.de/maemo3 bora free
#maemo:name Mulliner.org
deb http://www.mulliner.org/nokia770/repository/ bora free
#maemo:name repository.maemo.org
deb http://repository.maemo.org/ bora free non-free
#maemo:name Maemo hackers
deb http://maemo-hackers.org/apt bora main
#maemo:name eko one
deb http://eko.one.pl/maemo/ bora user
#maemo:name OpenedHand Maemo Software
deb http://maemo.o-hand.com/packages/ bora/
#maemo:name INdT Games
deb http://openbossa.indt.org.br/games bora games
#maemo:name mg
deb http://mg.pov.lt/770 bora user other
#maemo:name scriptkiller.de (vpnc and more)
deb http://scriptkiller.de/apt/ mistral main
#maemo:name maemo.org.br
deb http://www.maemo.org.br/platform/apt/ mistral user
#maemo:name Claws-mail
deb http://www.claws-mail.org/maemo bora user

# perl
-sh: perl: not found

# nmap --version

Nmap version 3.95 ( http://www.insecure.org/nmap/ )

# mplayer -h
MPlayer 1.0rc1-maemo.16.n800 (C) 2000-2006 MPlayer Team
CPU: ARM
Usage: mplayer [options] [url|path/]filename
[...]

# php --version
PHP 5.2.1 (cgi-fcgi) (built: Feb 27 2007 11:44:47)
Copyright (c) 1997-2007 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2007 Zend Technologies

Que conste que el juguete no es mío...


20070518

Durante unos días sin conexión a internet en casa, tuve tiempo de aburrirme lo suficiente como para reimplementar en Perl aquel programita de los monos y el soneto de Shakespeare. Ahora va algo más rápido, hasta aparecen palabras de 7 letras :^).


#!/usr/bin/perl

use warnings;
use strict;

my %dict;
open my $dict, '<', '/usr/share/dict/words' or die "open: $!";
chomp, $dict{$_} = undef while <$dict>;
close $dict;

sub hash2 {
open my $src, 'strings -eS /dev/urandom | tr -dc "a-zA-ZáéíóúüñÁÉÍÓÚÜÑ\n" |' or die "open: $!";
my $count = 0;
while (my $pw = <$src>) { ## potential word
chomp $pw;
next if length $pw < 4;
$pw =~ tr/A-ZÁÉÍÓÚÜÑ/a-záéíóúüñ/;

print $pw,v10 if exists $dict{$pw};
}
}

hash2;

El nombre de la función se debe a que hice un Benchmark con varias pruebas, y esta resultó ser la más rápida. Almacenar todo el diccionario en un hash tiene su precio: ocupa 8 Mb de RAM :^).


20070420

El super vi de solaris no se traga terminales de más de 163 caracteres, por lo que todos los días me encuentro con la misma secuencia: vi , mensajito de turno, q, <enter>, q, <enter>, !stty, !vi. Supongo que eso de q, <enter>, q, <enter> se puede hacer de alguna otra manera pero así es como lo hago yo. Parece que hoy no le di bien a la primera "q", de forma que la secuencia quedó cambiada y, donde normalmente le pongo la segunda "q", hoy le puse "!stty". Y claro, el señorito vi de solaris, que es muy pijo, se molestó un poco... ni que decir tiene que soy el único usuario de stty en esta máquina, por lo que "!stty" se refiere siempre a mi "stty cols 163" del día anterior.


$ vi Defaults
Terminal too wide
:
At EOF
:q
1 more file to edit:!stty
speed 38400 baud; -parity
rows = 69; columns = 180; ypixels = 0; xpixels = 0;
eol = -^?; eol2 = -^?; swtch = ;
brkint -inpck -istrip icrnl -ixany imaxbel onlcr tab3
echo echoe echok echoctl echoke iexten
!
Segmentation Fault (core dumped)
$ file core
core: ELF 32-bit MSB core file SPARC Version 1, from 'vi'
$ _

Además esto es global, vamos. Lo del cat del otro día me pasó cuando estuve en Sudáfrica, y ahora estoy en Inglaterra...


Update: El de HP/UX 11.00 es un poquito mejor, funciona con terminales de 164 caracteres :^D.


20070417

# grep win32 /usr/share/snmp/mibs/UCD-SNMP-MIB.txt
win32 OBJECT IDENTIFIER ::= { ucdSnmpAgent 13 } -- unlucky

Mecachis en la mar... qué mala suerte ha tenido el pobre güindons, que le han puesto en el 13... :^D.


20070403

# ls -l lastlog
-r-------- 1 root root 1254130450140 Apr 2 12:49 lastlog
# stat --format "%b * %B" lastlog | bc
61440


Un archivo de 1 Tb impresiona un poco a primera vista, al menos en 2007, y por eso creo que se ha merecido el esfuerzo adicional de comprobar si las cosas eran como aparentaban... La pregunta es: ¿hubiera detectado esto con 'ls -h'? Lo digo por la manía (a mi juicio) que tienen algunos de usarlo ;^). Humanos...

20070321

$ wget http://cronolog.org/patches/cronolog-1.7.0-beta.tar.gz
$ tar zxf cronolog-1.7.0-beta.tar.gz
$ cd cronolog-1.7.0
$ ./configure
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
/home/hue/tmp/cronolog-1.7.0/missing: Unknown `--run' option
Try `/home/hue/tmp/cronolog-1.7.0/missing --help' for more information
configure: WARNING: `missing' script is too old or missing
checking for gawk... no
[...]

Pues anda que no tiene gracia eso de "Missing script is missing"...


20070316

Como estoy viendo que no voy a memorizar esto en la vida, me lo apunto por aquí y así luego no tengo más que copy-pastear:


# apt-get update
[blah]
W: GPG error: http://foo.bar.tld unstable Release: The following
signatures couldn't be verified because the public key is not
available: NO_PUBKEY DE7E57AB1EC0FFEE
# gpg --keyserver hkp://wwwkeys.eu.pgp.net --recv-keys 1EC0FFEE
# gpg --armor --export 1EC0FFEE | apt-key add -

20070228

Más todavía, uf... Esto es un strace de la ejecución de jboss. Muchos megas y varios archivos pero lo que cuenta es:


$ grep ECONNREFUSED abc* | wc -l
1

Un errorcillo sin importancia, y de fácil resolución. Bien, veamos la salida por consola de jboss...


$ ls -l j-exception-econnrefused
-rw-r--r-- 1 hue hue 149540 20070213:093915+0100 j-exception-econnrefused
$ wc -l j-exception-econnrefused
2107 j-exception-econnrefused

¡150 Kb! ¡2000 líneas! O_o


$ grep "Connection refused" j-exception-econnrefused
MESSAGE: java.net.ConnectException: Connection refused
java.net.SocketException: java.net.ConnectException: Connection refused
MESSAGE: java.net.ConnectException: Connection refused
java.net.SocketException: java.net.ConnectException: Connection refused
MESSAGE: java.net.ConnectException: Connection refused
java.net.SocketException: java.net.ConnectException: Connection refused
MESSAGE: java.net.ConnectException: Connection refused
java.net.SocketException: java.net.ConnectException: Connection refused
MESSAGE: java.net.ConnectException: Connection refused
java.net.SocketException: java.net.ConnectException: Connection refused
MESSAGE: java.net.ConnectException: Connection refused
java.net.SocketException: java.net.ConnectException: Connection refused
MESSAGE: java.net.ConnectException: Connection refused
java.net.SocketException: java.net.ConnectException: Connection refused
MESSAGE: java.net.ConnectException: Connection refused
java.net.SocketException: java.net.ConnectException: Connection refused
MESSAGE: java.net.ConnectException: Connection refused
java.net.SocketException: java.net.ConnectException: Connection refused
MESSAGE: java.net.ConnectException: Connection refused
java.net.SocketException: java.net.ConnectException: Connection refused
MESSAGE: java.net.ConnectException: Connection refused
java.net.SocketException: java.net.ConnectException: Connection refused
MESSAGE: java.net.ConnectException: Connection refused
java.net.SocketException: java.net.ConnectException: Connection refused
$ grep -c "Connection refused" j-exception-econnrefused
24

Pero... ¿¿por qué 12 veces?? ¿Por qué 12 volcados de pila? ¿No bastaba con uno, como hace el resto del mundo? (Y no, no son reintentos porque entonces habría más resultados en el strace).


ARF!


20070218

Los chicos de Sun son todos unos artistas. No hay ni que referirse a la vulnerabilidad de telnet recientemente descubierta para encontrar que la calidad de su software está por todo lo alto:


$ cat >> file
H=$(hostname)
if echo $H | grep '_p$'; then
^\Quit (core dumped)
$ file core
core: ELF 32-bit MSB core file SPARC Version 1, from 'cat'
$ uname -sr
SunOS 5.9
$ _

Alguna tecla chunga habré pulsado, la verdad es que no sé cuál, de esto que le das sin querer. Pero en cualquier caso, no debería haber pasado *eso*.


20070130

Este mes me he tenido que pelear para intentar levantar un programita. En una semana me he tenido que comer todos estos acrónimos y conceptos (por orden alfabético):



No sé si se aprecia alguna constante en ellos :^P. La verdad, me he quedado con la idea de que alguna jente tiene deficiencias neuronales. O quizá el problema soy yo... ya se sabe, tantos millones de moscas no pueden estar equivocados así que vamos todos a comer mierda.


Afortunadamente ya me he vuelto a despertar, un poco mareado pero bien. Y además tengo ganas de ir al trabajo!


20070127

Pues ya ralla esto del mono:


$ chmod 755 lphantCmdLine.exe
$ ./lphantCmdLine.exe
Starting lphant!
_____________________________________________

To control lphant [bla bla bla]

20061205

Hoy toca un poco de Banda Sonora Original, bso.sh:


S=(/media/xp/windows/Media/{chord,Windows\ XP\ {Critical\ Stop,Error,Exclamation}}.wav)
while sleep $(( $RANDOM % 60 )); do
bplay "${S[ $(( $RANDOM % ${#S[*]} )) ]}" >&/dev/null;
done &

Lleva un rato funcionando aquí, y no noto ninguna diferencia con el original...


20061202

Este es un trozo de mi .bash_history, sin modificaciones:


perl -e'for my $i in (9759 25155 31755 31896 31976 32059); do printf "%x\n", $i; done'
perl -e'for my $i in (9759 25155 31755 31896 31976 32059) { printf "%x\n", $i; done }' ## xD
perl -e'for my $i (9759 25155 31755 31896 31976 32059) { printf "%x\n", $i; done }' ## xD
perl -e'for my $i (9759, 25155, 31755, 31896, 31976, 32059) { printf "%x\n", $i; done }' ## xDD
perl -e'for my $i (9759, 25155, 31755, 31896, 31976, 32059) { printf "%x\n", $i }' ## xDD
## qué fuerte
## pero si era mas bash que perl :^D
for i in 9759 25155 31755 31896 31976 32059; do printf "%x\n" $i; done

¿Quién quiere humanos, pudiéndoselo pasar tan bien con una simple shell?


20060905

# uptime
10:47:52 up 2:42, 1 user, load average: 160.19, 160.97, 160.17
# ps -e f | grep -c "apache$"
151

Problemilla del disco duro, parece...


Update: En el análisis post-mortem aparecieron varias sesiones de apache:


$ ls -ld tmp
drwxrwxrwt 2 root root 62668800 Sep 12 06:15 tmp
$ ls -U tmp | wc -l
1300432

20060820

$ mpg321 file.mp3
[...]
ALSA lib confmisc.c:672:(snd_func_card_driver) cannot find card '0'
ALSA lib conf.c:3493:(_snd_config_evaluate) function snd_func_card_driver returned error: No such device
ALSA lib confmisc.c:392:(snd_func_concat) error evaluating strings
ALSA lib conf.c:3493:(_snd_config_evaluate) function snd_func_concat returned error: No such device
ALSA lib confmisc.c:1072:(snd_func_refer) error evaluating name
ALSA lib conf.c:3493:(_snd_config_evaluate) function snd_func_refer returned error: No such device
ALSA lib conf.c:3962:(snd_config_expand) Evaluate error: No such device
ALSA lib pcm.c:2099:(snd_pcm_open_noupdate) Unknown PCM default
ALSA snd_pcm_open error: No such device

Funcionaba a pesar de esto porque tengo compilada la emulación OSS. Hoy me puse con ello y resultó que no había /dev/snd en esta máquina. Crearlo no fue difícil:


# mkdir /dev/snd
# chmod 755 /dev/snd
# cd /dev/snd
# cat /proc/asound/devices
1: : sequencer
8: [0- 0]: raw midi
17: [0- 1]: digital audio playback
16: [0- 0]: digital audio playback
24: [0- 0]: digital audio capture
0: [0- 0]: ctl
33: : timer
# mknod controlC0 c 116 0
# mknod seq c 116 1
# mknod midiC0D0 c 116 8
# mknod pcmC0D0p c 116 16
# mknod pcmC0D1p c 116 17
# mknod pcmC0D0c c 116 24
# mknod timer c 116 33
# chgrp audio *
# chmod 660 *

20060727

# file: 04.data 
42
33
1
-5
5.7

No me he matado a comprobar errores:


/* C */
#include <stdio.h>
#include <stdlib.h>
int main (void) {
FILE *fd;
char linea[16];
float tot = 0;

fd = fopen ("04.data", "r");
while (fgets (linea, 16, fd)) {
tot += atof (linea);
}
close (fd);
printf ("tot %.1f\n", tot); /* bad: ".1" hardcoded */
}

# Perl 5.8.8
my $tot;
open my $fd, '<', '04.data';
$tot += $_ while <$fd>;
close $fd;
print "tot $tot\n";

# Perl 6 (pugs 6.2.10)
my $tot = [+] '04.data'.slurp;
"tot $tot".say;

Update: s/sum/tot/g/; en el ejemplo de Perl 6


20060501

-----BEGIN PERL GEEK CODE BLOCK-----
Version: 0.01
P++$c--P6-R++M+O++MA++E+PU BD C--D S
X+WP+MO---PP n
CO!PO!o+++G+A-OLC--OLCC---OLJ---OLP-OLC
O---Ee---Ev Eon uL+++uB+w!m!
------END PERL GEEK CODE BLOCK------

Update 20060930:


-----BEGIN PERL GEEK CODE BLOCK-----
Version: 0.01
P++>+++c--P6 R+++M+>+++O++>+++MA++E+PU
>++(+)BD C+>++D >++S X+>++WP+>+++MO--->+PP
>++n-( )CO!>-(--)PO-->
o+++G+>++A+>+++OLC-->-OLP >++OLL >+Ee---
>?Ev+>++Eon+uL++>+++uB+>+w!m!>+
------END PERL GEEK CODE BLOCK------

Decode

20060401

IPSEC: tan pronto ciframos todo el tráfico, NFS se rompe, lo cual es bastante lógico :^):


System Clock set. Local time: Tue Nov 22 20:30:02 UTC 2005
Loading device-mapper support.
Checking all file systems....
Setting kernel variables ...
... done.
Mounting local filesystems... failed!
Loading IPsec SA/SP database from /etc/ipsec-tools.conf: done.
RPC: sendmsg returned error 3
nfs: RPC call returned error 3
RPC: sendmsg returned error 3
nfs: RPC call returned error 3
RPC: sendmsg returned error 3
nfs: RPC call returned error 3
/etc/init.d/rc: line 159: /bin/sed: No such process
RPC: sendmsg returned error 3
nfs: RPC call returned error 3
RPC: sendmsg returned error 3
nfs: RPC call returned error 3

20060324

Me ha vuelto a dar la venada de la bolsa, que tenía abandonada desde el 2003 o por ahí. Acabo de "acabar" un scriptito para calcular rápidamente las ganancias porcentuales:


$ perl -T earnings.pl 
in: 2345.67 <-- importe por el cual hemos comprado cosas
out: 2468.02 <-- idem vendido
comm: 13.96 + 13.99 = 27.95
comm[27.95]:
(using default comm value)
without comm, you gain/lose 5.22%
with comm, you gain/lose 4.02%
$ perl -T earnings.pl r4
in: 12345.67
out: 12468.02
comm: 24.65 + 24.85 = 49.5
comm[49.5]: 50
without comm, you gain/lose 0.99%
with comm, you gain/lose 0.59%
$ _

Está en fase beta.


#!/usr/bin/perl -T

use strict;
use warnings;

@ENV{'PATH','CDPATH'} = ('')x2;

my $broker;
my %canon = ( ## value, minimum
0 => [ '0.10 + 0%', 0 ],
30 => [ '1.10 + 0%', 0 ],
300.01 => [ '2.45 + 0.024%', 0 ],
3000.01 => [ '4.65 + 0.012%', 0 ],
35000.01 => [ '6.40 + 0.007%', 0 ],
70000.01 => [ '9.20 + 0.003%', 0 ],
140000.01 => [ '13.40 + 0%', 0 ],
);
my %commissions = (
selftrade => { ## value, minimum
0 => [ 4.95, 0 ],
1500 => [ '4.95 + 0.12%', 10.95 ],
},
r4 => {
0 => [ 3, 0 ],
2000 => [ '0.15%', 0 ],
15000 => [ '3 + 0.1%', 0 ],
},
## TODO: add more
);

sub calc_comm {
my $amount = shift;
my $comm = 0;

foreach my $hash (\%canon, $commissions{$broker}) {
## traverse sorted hash keys until needed
foreach (sort {$b <=> $a} keys %$hash) {
if ($amount > $_) {
my $val = $hash->{$_}[0];
my $min = $hash->{$_}[1];

## manage pct values
$val =~ s{(\S+)%}{$amount * $1/100}ge;

## -T forces us to untaint $val (even when it's
## something derived from untainted user input)
$val = $val =~ /^([\d\s.+-]+)$/ ? $1 : die "\$val tainted";

$val = eval $val; ## perform math
$val = $min if $val < $min;
$comm += $val;
last;
}
}
}
return sprintf "%.2f", $comm; ## trim and round
}

$broker = shift;
$broker = 'selftrade' unless defined $broker; ## default val
die <<"EOF" unless grep /$broker/, keys %commissions;
broker unsupported
supported: @{[ sort keys %commissions ]}
EOF

## get data
print "in: "; chomp (my $in = <STDIN>);
print "out: "; chomp (my $out = <STDIN>);
## untaint input
$in = $in =~ /^\D*(\d+\.?\d*).*$/ ? $1 : '';
$out = $out =~ /^\D*(\d+\.?\d*).*$/ ? $1 : '';
die "invalid input\n" unless length $in && length $out;

## calculate commision
my $comm_in = calc_comm $in;
my $comm_out = calc_comm $out;
my $calc_comm = $comm_in + $comm_out;
print "comm: $comm_in + $comm_out = $calc_comm\n";
## ask for commission (just in case), suggesting calculated value
print "comm[$calc_comm]: "; chomp (my $comm = <STDIN>);
## untaint input
$comm = $comm =~ /^\D*(\d+\.?\d*).*$/ ? $1 : ''; ## dup code :^/
unless (length $comm) {
warn "(input null or invalid, using default comm value)\n";
$comm = $calc_comm;
}

## calc pct earnings
my $without_comm = ($out - $in ) / $in * 100;
my $with_comm = ($out - $in - $comm) / $in * 100;

printf <<"EOF", $without_comm, $with_comm;
without comm, you gain/lose %.2f%%
with comm, you gain/lose %.2f%%
EOF

UPDATE: s/</&lt;/; s/>/&gt;/; Fix typo.


20060316

# reboot
[bla bla]
# ps faxu|tail -n2
root 21436 0.0 0.5 5076 2420 ? Ss 16:51 0:00 /bin/sh /etc/init.d/rc 6
root 689 0.0 0.4 5052 2300 ? S 16:51 0:00 \_ /bin/bash /etc/rc6.d/K01beepz stop
# strace -p 689 -tt
Process 689 attached - interrupt to quit
17:17:43.736955 write(1, "Usage: /etc/init.d/beepz star\n", 30 <unfinished ...>
Process 689 detached
# _

20060308

Una vez estaba jugando con un amiguete a intentar copiar un archivo usando únicamente la redirección de bash. Cuando nos cansamos (sin conseguirlo) seguimos con lo nuestro pero al rato vi algo extraño...


~ # ps faxu    ## recortado
USER PID TIME COMMAND
#0 1 0:13 init [2]
#0 17296 0:00 /bin/sh /usr/bin/mysqld_safe
#106 13097 0:00 \_ /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql --user=m
#106 14772 0:09 | \_ /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql --us
#106 7272 0:00 | \_ /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql
#106 7600 0:00 | \_ /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql
#106 9146 0:00 | \_ /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql
#0 22826 0:00 \_ logger -p daemon.err -t mysqld_safe -i -t mysqld
#0 10525 0:00 /usr/lib/postfix/master
#102 2073 0:00 \_ qmgr -l -t fifo -u -c
#102 24442 0:00 \_ pickup -l -t fifo -u -c
#103 32548 0:08 /usr/sbin/snort -m 027 -D -l /var/log/snort -d -u snort -g snort -c /
#0 4353 0:10 /usr/sbin/apache
#33 31134 0:00 \_ /usr/sbin/apache
#33 17713 0:00 \_ /usr/sbin/apache
#33 17142 0:00 \_ /usr/sbin/apache
#33 31469 0:00 \_ /usr/sbin/apache
#33 14616 0:00 \_ /usr/sbin/apache
#1001 11146 0:00 -bash
#1000 22009 0:00 -bash
~ # _

Mi primera sospecha se vio desgraciadamente confirmada:


~ # cat /etc/passwd
~ # _

Claro, sólo a nosotros se nos ocurre jugar como root y además usando precisamente *ese* archivo :^D. Buscamos el culpable y resultó ser:


~ # ll /etc/passwd
-rw-r--r-- 1 root root 1264 Oct 29 17:53 /etc/passwd
~ # < /etc/passwd > /proc/$$/fd/0
~ # ll /etc/passwd
-rw-r--r-- 1 0 root 0 Oct 29 17:54 /etc/passwd
~ # _

20060302

Receta rápida para que Portage vaya (mucho) más lento:


$ wget http://dev.gentoo.org/~carpaski/gpg/{README,gentoo.gpg{,.asc}}
$ less README
$ su
# umask 077
# QQDIR=/etc/portage/gpg
# mkdir $QQDIR
# mv -f gentoo.gpg{,.asc} !$
# chown 0.0 !$/gentoo.gpg{,.asc}
# ^own 0.^mod 60^
# chattr +A !$/gentoo.gpg
# sh /usr/lib/portage/bin/portage_gpg_update.sh
# mv -f /usr/portage/metadata/gentoo.gpg $QQDIR/pubring.gpg
# rm -f /usr/portage/metadata/gentoo.gpg~
# echo PORTAGE_GPG_DIR=\"$QQDIR\" >> /etc/make.conf
# sed -i -e 's/\(FEATURES="\)/\1gpg /' !$
# emerge -p portage ## test
# exit
$ rm -f README

El chattr está por una razón bastante curiosa. Me pasó que al probar a hacer un emerge me salía un mensaje tal que "The keyring has changed". Tras un rato de depuración, vi que se hacía un checksum del archivo a partir de la información del inodo. Más tarde se hacía otro checksum, que daba un resultado distinto porque había cambiado el atime del archivo (es decir, alguien había accedido al archivo entre los dos checksums). Con el chattr hacemos que no se actualice el atime, con lo que el síntoma desaparece. Y así lo he dejado.


20060226

$ perl -e'printf "0x%x %s\n", time, scalar localtime and sleep 1 while 1'
0x43fffff7 Sat Feb 25 07:57:59 2006
0x43fffff8 Sat Feb 25 07:58:00 2006
0x43fffff9 Sat Feb 25 07:58:01 2006
0x43fffffa Sat Feb 25 07:58:02 2006
0x43fffffb Sat Feb 25 07:58:03 2006
0x43fffffc Sat Feb 25 07:58:04 2006
0x43fffffd Sat Feb 25 07:58:05 2006
0x43fffffe Sat Feb 25 07:58:06 2006
0x43ffffff Sat Feb 25 07:58:07 2006
0x44000000 Sat Feb 25 07:58:08 2006
0x44000001 Sat Feb 25 07:58:09 2006
0x44000002 Sat Feb 25 07:58:10 2006
0x44000003 Sat Feb 25 07:58:11 2006
0x44000004 Sat Feb 25 07:58:12 2006
0x44000005 Sat Feb 25 07:58:13 2006
0x44000006 Sat Feb 25 07:58:14 2006

Sí, ya sé que es una revancha muy patatera pero bueno :^P. La zona horaria, por cierto, es CET.


20060219

Hace poco me topé con un comportamiento extraño de lsof. En principio lo consideré un bug pero al ir a mirar el fuente, me encontré con que ese caso había sido tenido en cuenta. Como los autores de lsof saben mucho más que yo, decidí dejarlo estar y dado que ahora para mí ya no tiene ninguna relevancia, lo pongo por aquí. Se trata de hacer algo tan sencillo como:


$ cp /bin/sleep $'abc\x0aabc'
$ './abc^Jabc' 60 &

Y a continuación usar lsof para buscar el proceso. Yo probé lo siguiente:


lsof -n|grep abc
lsof -n|grep <pid>
lsof -n -c abc
lsof -n -p <pid>
lsof -n +w -p <pid>

Pero no apareció en ninguno de los casos.


20060216

Esta máquina estaba un poco saturadilla:


10:07:16.360483 write(1, "standa"..., 4096) = 4096
10:07:16.460891 write(1, "los/p"..., 4096) = 4096
10:07:18.816420 write(1, ".py\na"..., 4096) = 4096
10:07:23.750215 write(1, "\nadde"..., 4096) = 4096
10:07:23.751693 write(1, "templa"..., 4096) = 4096
10:07:25.833796 write(1, "smart"..., 4096) = 4096
10:07:59.514171 write(1, "ython"..., 4096) = 4096
10:07:59.822834 write(1, "net/tu"..., 4096) = 4096
10:07:59.847215 write(1, "usr/s"..., 4096) = 4096
10:08:09.369819 write(1, "o\nadd"..., 4096) = 4096
10:08:11.707664 write(1, "/napi."..., 4096) = 4096

20060130

UNIX realmente tiene cosas curiosas, parte III:


# ls -li /var/chroot/apache2/var/run/mysqld/mysqld.sock /var/chroot/mysql/var/run/mysqld/mysqld.sock mysqld.sock
10780999 srwxrwxrwx 2 mysql mysql 0 2005-05-13 12:28 mysqld.sock
10780999 srwxrwxrwx 2 mysql mysql 0 2005-05-13 12:28 /var/chroot/apache2/var/run/mysqld/mysqld.sock
10780999 srwxrwxrwx 2 mysql mysql 0 2005-05-13 12:28 /var/chroot/mysql/var/run/mysqld/mysqld.sock
# _

3 entradas con el mismo inodo, pero la información de los inodos dice que sólo hay 2...


[Meses más tarde]


# ls -li /var/run/mysqld/mysqld.sock /chroot/apache/var/run/mysqld/mysqld.sock /chroot/mysql/var/run/mysqld/mysqld.sock
1606485 srwxrwxrwx 1 mysql mysql 0 Jan 30 11:24 /chroot/apache/var/run/mysqld/mysqld.sock
1606485 srwxrwxrwx 1 mysql mysql 0 Jan 30 11:24 /chroot/mysql/var/run/mysqld/mysqld.sock
1606485 srwxrwxrwx 1 mysql mysql 0 Jan 30 11:24 /var/run/mysqld/mysqld.sock
$ _

Hmm, ahora pone 1...


<EOF>

This page is powered by Blogger. Isn't yours?