Archivo

Archivo para la categoría ‘Bash’

Creando un menú selector de frecuencia de nuestra CPU

Lunes, 9 de Enero de 2012 Gaspar Fernández 2 comentarios

screenshot-05-01-2012-220103

A mí me gusta tener el control sobre la frecuencia de la CPU, ya sea porque muchas veces no estoy haciendo nada y lo quiero dejar al mínimo de velocidad para que se caliente menos, o porque algunas veces necesito un poco más de potencia, y otras veces lo dejo a su aire para que cambie de frecuencia solo.

El script se basa en llamadas a cpufreq-set de cpufrequtils, aunque la llamada tiene que ser con permisos de root, por lo que conviene ver antes este artículo, de todas formas, todo esto se hará paso a paso.

Requisitos

  • CPU soportada por cpufreq
  • Sudo / Gksudo
  • Cpufrequtils
  • Zenity
  • Xosd

Editando sudoers

Este script lo ejecutaremos desde nuestro usuario, pero la llamada a cpufreq-set necesita permisos especiales, por lo tanto, lo haremos con sudo. Si saltamos este paso, nos preguntará la contraseña para ejecutar los comandos, pero si no queremos que nos pregunte, debemos hacer esto.

Lo primero es ejecutar:

$ sudo visudo

Y en el archivo, debajo de la última línea sin comentario, escribimos:

mi_usuario   ALL= NOPASSWD : /usr/bin/cpufreq-set

Sustituyendo mi_usuario por el usuario que va a ejecutar el script. Si tenéis varios usuarios podéis añadirlos uno por línea, o ver el artículo mencionado antes para más opciones.

El script

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#!/bin/bash

DIALOG=zenity
CPUFREQSET=`which cpufreq-set`
OSDCAT=`which osd_cat`

XOSD_FONT="-*-luxisans-bold-*-*-*-47-*-*-*-*-*-*-*"
XOSD_OPTIONS="--pos=bottom -o -210 -A center -c green -s 2 -d 2 -f "$XOSD_FONT;
tempfile=`tempfile 2>/dev/null` || tempfile=/tmp/test$$
trap "rm -f $tempfile" 0 1 2 5 15

if [ -z $CPUFREQSET ]
then
    echo "cpufrequtils no está instalado"
    exit
fi

if [ -z $OSDCAT ]
then
    echo "xosd no está instalado"
    exit
fi

if [ -e "/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies" ]
then
    actual=`cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq`
    cnt=0
    for i in `cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies`
    do
    if [[ $i != $actual ]]; then
        cnt=`expr $cnt + 1`
    fi
    done
else
    echo "CPUfreq no está disponible"
    exit    
fi

simple_math()
{
    echo "scale=2; $1" | bc;
}

saca_freq()
{
    cnt=0
    for i in `cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies`
      do
      if [[ $cnt == $1 ]]; then
      frq=$i
      break
      fi
      cnt=`expr $cnt + 1`
    done
    echo $frq
}

pone_freqs()
{
    cnt=0
    for j in `cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies`
      do
      if [[ $j != $actual ]]; then
      frq=$frq":Cpufreq "$cnt":"`simple_math $j/1000000`" Ghz"
      fi
      cnt=`expr $cnt + 1`
    done
    echo $frq
}

pone_governors()
{
    possible_governors=([0]=powersave [1]=conservative [2]=ondemand [3]=performance)
    governor_command=([0]=Powersave [1]=Conservative [2]=Ondemand [3]=Performance)
    governor_text=([0]="Ahorro de energía" [1]="Modo conservador" [2]="Modo Bajo demanda" [3]="Modo rendimiento")
    available_governors=`cpufreq-info -g`

    for (( g=0; g<${#possible_governors[*]}; g++ ))
    do
    # echo $g
    # echo ${possible_governors[$g]}
    gov=${possible_governors[$g]}
    if [ -n "`echo $available_governors | grep $gov`" ]
    then
        frq=$frq":"${governor_command[$g]}":"${governor_text[$g]}
    fi
    done
   
    echo $frq
}

freqs="Exit:No hacer nada"
freqs=$freqs`pone_freqs`
freqs=$freqs`pone_governors`

OLD_IFS=$IFS
IFS=":"


$DIALOG --width=240 --height=250 --title="Selector de frecuencia" --list --column "ID" --column "Frecuencia" --hide-column 1 --text "Elige una opcion" $freqs > $tempfile

retval=$?
IFS="${OLD_IFS}"

choice=`cat $tempfile`

comando=`echo $choice | cut --delimiter " " --fields 1`
modif=`echo $choice | cut --delimiter " " --fields 2`

case $retval in
  0)
    case $comando in
        "Exit")
        echo "Salir" | osd_cat $XOSD_OPTIONS
        ;;
        "Cpufreq")
        freqdef=`saca_freq $modif`
        gksudo "$CPUFREQSET -g userspace"
        gksudo "$CPUFREQSET -f $freqdef"
        echo "Velocidad actual "`simple_math $freqdef/1000000`"Ghz" | $OSDCAT $XOSD_OPTIONS
        ;;
        "Powersave")
        gksudo "/usr/bin/cpufreq-set -g powersave"
        echo "Modo ahorro de energía" | $OSDCAT $XOSD_OPTIONS
        ;;
        "Conservative")
        gksudo "/usr/bin/cpufreq-set -g conservative"
        echo "Modo conservador" | $OSDCAT $XOSD_OPTIONS
        ;;
        "Ondemand")
        gksudo "/usr/bin/cpufreq-set -g ondemand"
        echo "Modo bajo demanda" | $OSDCAT $XOSD_OPTIONS
        ;;
        "Performance")
        gksudo "/usr/bin/cpufreq-set -g performance"
        echo "Modo rendimiento" | $OSDCAT $XOSD_OPTIONS
        ;;     
    esac;;
  1)
    echo "Cancelado";;
  255)
    echo "Escape";;
esac

Notas del script

  • He optado por filtrar el resultado de cpufreq-info -g y cambiar las palabras, me gusta filtrar todos los datos que me llegan.
  • Añadí la primera opción para no hacer nada, porque me resultó más cómoda cuando quiero cancelar el menú
  • zenity nos devuelve dos cosas: El resultado de la ejecución y el valor elegido, por tanto el primer valor lo podemos averiguar del script, el segundo lo devuelve como texto, por eso lo almacenamos en un archivo temporal
  • Para cambiar el tipo de letra, tenemos que ejecutar xfontsel, desde ese programa, elegir el tipo de letra y copiar el texto que nos devuelve a la variable XOSD_FONT
    • Por último…

      Para disfrutar de este script, lo bueno es asociarlo a una tecla, por ejemplo yo lo tengo en Meta+F3 y con ello se puede cambiar la frecuencia rápidamente.

Ejecutando programas como root sin contraseña (Paso a paso)

Jueves, 5 de Enero de 2012 Gaspar Fernández Sin comentarios

sandwich

Cuando estamos utilizando la terminal y queremos ejecutar comandos con privilegios de superusuario (root), los usuarios de Ubuntu o Mint entre otras estarán acostumbrados a pedir las cosas con sudo.

Cuando estamos delante, es muy cómodo hacerlo, aunque tengamos que introducir la contraseña nada más ejecutar el comando (en muchos sistemas, cuando la has introducido una vez, te deja ejecutar comandos como root durante un rato sin introducir contraseña).

El problema está cuando creamos scripts y automatizamos tareas que requieren en una pequeña parte privilegios de root. Por un lado, podemos ejecutar los scripts como root y olvidarnos, pero es algo muy inseguro, lo suyo es que ejecutemos el comando con sudo y no nos pregunte por contraseña.

Tenemos que tener cuidado con esto, ya que se permitirán algunos comandos de root sin contraseña, y puede que muchos de ellos sean dañinos para el sistema, eso es nuestra responsabilidad.

Un comando, para un sólo usuario

Para los ejemplos, vamos a ejecutar como root el comando service (para arrancar o parar servicios de sistema). De este modo no tendremos que introducir la contraseña cuando queramos hacerlo.

Para ello vamos a editar el archivo sudoers. Y con ese fin debemos ejecutar el comando visudo como root:

$ sudo visudo

Se abrirá un editor (vi, por ejemplo) con el que podremos editar los contenidos de ese fichero de forma segura. Allí debemos añadir la siguiente línea:

1
usuario   ALL= NOPASSWD : /usr/sbin/service

Si os fijáis, es la palabra clave NOPASSWD la que provoca que no se pregunte contraseña cuando se invoca el comando.

Podemos hacerlo al final del fichero. En este caso daremos permiso a usuario para que ejecute:

$ sudo service xxxxx xxxxxx

por ejemplo:

$ sudo service apache restart

las veces que quiera sin pedir contraseña.

Un comando, un grupo

Una opción, es que si el ordenador lo utilizan varios usuarios, es permitir a un grupo entero la ejecución de comandos de esta forma, para ello, primero creamos el grupo (el grupo se llamará administradores)

$ sudo groupadd administradores

Ahora introucimos usuarios en el grupo:

$ sudo gpasswd -a usuario1 administradores
$ sudo gpasswd -a usuario2 administradores
$ sudo gpasswd -a usuario3 administradores

o también

$ sudo gpasswd -M usuario1,usuario2,usuario3 administradores

Ahora introducimos lo siguiente en sudoers (con el comando visudo, como antes):

1
%administradores   ALL= NOPASSWD : /usr/sbin/service

Muchos comandos, muchos usuarios

También puede ser que tengamos muchos comandos para permitir a muchos usuarios y, aunque podemos introducir 200 líneas en sudoers, a lo mejor es algo complicado de administrar en el caso de que queramos quitar un comando, ya que tendremos que modificar varias líneaas, o queramos quitar a un usuario. Para eso utilizaremos los alias de sudoers.

Podemos utilizr comandos especiales dentro de sudoers que nos permitirán crear un Alias donde introducir una enumeración de datos (por ejemplo usuarios y comandos):

  • User_Alias NOMBRE_DE_LA_COLECCION = usuario1, usuario2, usuario3, etc : Configurará una colección de usuarios llamada NOMBRE_DE_LA_COLECCION
  • Cmnd_Alias COLECCION_COMANDOS = comando1, comando2, comando3, etc : Configura una colección de comandos llamada COLECCION_COMANDOS

Luego estos alias podemos utilizarlos en la línea de sudoers que activa la utilización sin contraseña:

1
ADMINISTRADORES   ALL= NOPASSWD : COMANDOS

Algo que me dejé en el tintero

En esta guía no quise introducir el host (es ese ALL) que nos queda colgado, y es que podemos limitar el uso de sudo a un host determinado. Por ejemplo, permitir esa ejecución cuando se ejecuten en modo local o desde un determinado nodo remoto (para que no desde todos lados se pueda hacer). Aquí podemos especificar tanto nombres de host como direcciones IP.

Foto: xkcd

Buscando un proceso en C

Martes, 4 de Octubre de 2011 Gaspar Fernández 2 comentarios

Comando topEn ocasiones, nuestros programas requieren que un servicio o un programa esté en ejecución. Algunos servicios los podemos ubicar fácilmente, ya que /var/run ,  /dev/shm u otra ruta contienen un archivo con su PID (Identificador de proceso), otras servicios no figuran en ningún lado. También puede ser que estemos esperando que otro proceso termine y necesitamos averiguar su PID.

Para todo ello, debemos echar un ojo al contenido de /proc/, ahí encontramos, entre otras cosas, información sobre los procesos en ejecución del sistema. En principio lo que nos interesa es el nombre del ejecutable (es lo que estamos buscando), para ello, vamos a buscar dentro del directorio /proc/ todos los directorios que sean numéricos (esos que contendrán un PID), y leeremos el fichero /proc/[pid]/comm, que contiene la información del nombre del ejecutable. Eso sí, ese nombre tendrá una longitud limitada (marcada por la constante del kernel TASK_COMM_LEN, que suele valer 16 (con lo que los nombres tendrán como máximo 15 caracteres):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <ctype.h>

void tareaProceso(char *nombre, int pid);

void buscaProceso(char *nombre);

void error(char *error);

/* Una función lo más general posible */
void getProcName(char *dest, int pid);

int main(int argc, char *argv[])
{
  buscaProceso("firefox-bin");
  return EXIT_SUCCESS;
}

void tareaProceso(char *nombre, int pid)
{
  printf("Encontrado proceso %-16s con PID: %d\n", nombre, pid);
  /* Aquí ya puedo matarlo, mandarle señales o hacer lo que quiera */
  /* con el proceso en cuestión */
}

void buscaProceso(char *nombre)
{
  DIR *proc;
  struct dirent *proceso;
  char procname[16];        /* Nombre del proceso */
  int pid;

  proc=opendir("/proc");

  if (proc==NULL)
    error("No puedo acceder al directorio /proc");

  while ((proceso=readdir(proc)) != NULL)
    {
      /* En /proc hay más cosas además de los PIDs, debemos asegurarnos de que */
      /* lo que hemos visto es un ID de proceso, lo demás no nos interesa */
      if ( (*proceso->d_name>'0') && (*proceso->d_name<='9') )
    {
      /* Convertimos el PID a número para la llamada a la función */
      pid=strtol(proceso->d_name, NULL, 10);
      getProcName(procname, pid);
      if (strncmp(nombre,procname,15)==0)
        tareaProceso(procname, pid);
    }
    }
}

void error(char *error)
{
  fprintf(stderr, "Error: %s (%d, %s)\n", error, errno, strerror(errno));
  exit(EXIT_FAILURE);
}

void getProcName(char *dest, int pid)
{
  FILE *fcomm;
  char filename[20];        /* /proc/[PID] (5 chars)/comm : total 16 chars */

  sprintf(filename,"/proc/%d/comm", pid);

  fcomm=fopen(filename, "r");
  if (!fcomm)
    error("No existe el fichero");
  /* A veces fgets() coge un salto de línea extra */
  /* fgets(dest, 16, fcomm); */
  fscanf(fcomm, "%s", dest);
  close(fcomm);
}

En este ejemplo si comentamos la línea 52 y en la línea 53 ponemos:

1
tareaProceso(nombre, pid);

podemos obtener un listado completo de las tareas en ejecución (sólo por curiosear un poco). Aunque en este ejemplo tenemos un problema, mencionado antes, el número de caracteres del ejecutable, es decir, hay ejecutables con más de 15 caracteres, y tal vez queramos buscarlos. Con la solución actual estamos cortando los nombres (con strncmp()), es decir, sería lo mismo aplicacionconnombrelargo que aplicacionconnombrecorto, ya que sólo tenemos en cuenta los primeros 15 caracteres. Tiene que haber otra forma de sacar el nombre completo, y es a través del archivo /proc/[PID]/cmdline, es más, desde aquí podemos sacar la ruta del ejecutable y los parámetros con los que se llamó, tal y como vemos cuando ejecutamos:

$ ps x

Vamos a ver cómo podemos adaptar el código de antes para poder sacar toda esa información.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <libgen.h>     /* basename */

enum pnametype
  {
    SHORT,
    LONG,
    WPATH
  };

/* Realiza una tarea con el proceso encontrado */
void tareaProceso(char *nombre, int pid);

/* Busca un proceso determinado */
void buscaProceso(char *nombre);

/* Sale del programa emitiendo un error */
void error(char *error);

/* Obtiene el nombre de un proceso */
void getProcName(char *dest, int pid, enum pnametype outtype);

/* Lee los contenidos de un archivo */
int getFileContents(char *dest, char *fname);

int main(int argc, char *argv[])
{
  buscaProceso("plugin-container");
  return EXIT_SUCCESS;
}

void tareaProceso(char *nombre, int pid)
{
  printf("Encontrado proceso %-16s con PID: %d\n", nombre, pid);
  /* Aquí ya puedo matarlo, mandarle señales o hacer lo que quiera */
  /* con el proceso en cuestión */
}

void buscaProceso(char *nombre)
{
  DIR *proc;
  struct dirent *proceso;
  char procname[255];       /* Como getProcName necesita una variable grande, se la damos */
  int pid;

  proc=opendir("/proc");

  if (proc==NULL)
    error("No puedo acceder al directorio /proc");

  while ((proceso=readdir(proc)) != NULL)
    {
      /* En /proc hay más cosas además de los PIDs, debemos asegurarnos de que */
      /* lo que hemos visto es un ID de proceso, lo demás no nos interesa */
      if ( (*proceso->d_name>'0') && (*proceso->d_name<='9') )
    {
      /* Convertimos el PID a número para la llamada a la función */
      pid=strtol(proceso->d_name, NULL, 10);
      getProcName(procname, pid, LONG);
      if (strcmp(nombre,procname)==0)
        tareaProceso(procname, pid);
    }
    }
}

void error(char *error)
{
  fprintf(stderr, "Error: %s (%d, %s)\n", error, errno, strerror(errno));
  exit(EXIT_FAILURE);
}

int getFileContents(char *dest, char *fname)
{
  FILE *fdata;
  int res;

  fdata=fopen(fname, "r");
  if (!fdata)
    error("No existe el fichero");
 
  res=fscanf(fdata, "%s", dest);
  if (res==EOF)         /* Si no hemos leído nada,  */
    *dest='\0';         /* nos aseguramos de vaciar la cadena */

  fclose(fdata);

  /* Devolvemos un error si, por ejemplo el fichero está vacío */
  return (res!=EOF);
}
/* dest tiene que ser grande, en un proyecto real, reservamos memoria desde */
/* getProcName, no nos arriesgamos a que falle algo de fuera */
void getProcName(char *dest, int pid, enum pnametype outtype)
{
  char filename[20];        /* /proc/[PID] (5 chars)/cmdline : total 19 chars */
  char *tmp;
  char *newfile;
  if (outtype==SHORT)
    sprintf(filename,"/proc/%d/comm", pid);
  else
    sprintf(filename,"/proc/%d/cmdline", pid);

  if (!getFileContents(dest, filename))
    {
      /* Si no hemos podido obtener nada */
      if (outtype!=SHORT)
    {
      /* probamos desde comm */
      sprintf(filename,"/proc/%d/comm", pid);
      getFileContents(dest, filename);
    }
    }

  if (outtype!=SHORT)
    {
      /* Si queremos un tipo de salida que no sea el corto, tendremos que transformar esta cadena */
      tmp=dest;
      while ((*tmp!=' ') && (*tmp!='\0')) ++tmp;
      tmp='\0';
      if (outtype==LONG)
    {
      tmp=basename(dest);
      strcpy(dest, tmp);
    }
    }
}

Ahora, obtenemos la información dependiendo del tipo especificado por outtype de tipo enum pnametype, e incluso si especificamos LONG, este tipo extraerá el nombre del archivo ejecutable despreciando la ruta del mismo. Para descargar los archivos de código, click aquí (2.3Kb)

Solución temporal al problema con udev 171

Jueves, 8 de Septiembre de 2011 Gaspar Fernández Sin comentarios

Desde Mayo de 2011 tenemos a nuestra disposición una de las versiones con más bugs de udev, este gestor de dispositivos de Linux. En concreto, el bug del que hablo está apareciendo desde Julio/Agosto de este año. La forma de reproducirlo es muy fácil, tenemos que tener el servidor X con la configuración automática (en muchas distribuciones) o utilizando dispositivos de eventos, desde el arranque, ni el teclado ni el ratón funcionan.

tecladosLa primera vez que me pasó pensé en el servidor X, de hecho, como no funcionaba el teclado, no se podía cambiar a consola con Ctrl+Alt+Fn (n=1,2,3,4,….) ; por lo que fue necesario pulsar Alt+Sysrq+R antes de poder cambiar a la consola con Alt+Fn.

Dicho esto, había que trastear un poco, y es que la culpa no es de las X, éstas estaban bien configuradas, aprovechando que utilizo una de las últimas versiones, está configurada para no utilizar HAL a la hora de detectar dispositivos de entrada, y apoyarse directamente en lo que udev le dice.

Si el sistema está recién instalado, podemos ver que la configuración sí que funcionaba perfectamente nada más arrancar, es a la segunda vez cuando ya no hace las cosas bien, esto nos da una pista de que puede haber algún archivo que se escribe y puede estar metiendo la pata… ¡ lo borramos y ya está ! Aunque tendremos que hacerlo cada vez que arrancamos el ordenador. Por otra parte, si enchufamos el teclado o ratón de nuevas, el sistema hace las cosas bien, es decir, podemos desenchufar y enchufar el ratón y no pasaría nada (sería un “problema menor” aunque incómodo), lo malo es si trabajamos desde un portátil.

Dado que la versión 171 de udev es una de las más actuales, y que para la 172 (aún experimental) hay que instalar muchos otros componentes también experimentales, no estaría mal aplicar un pequeño parche antes de actualizar nuestro sistema con componentes que a lo mejor luego nos dan algún problema, además de que para muchas distribuciones aún no están disponibles los paquetes.

Podemos optar por varias soluciones:

Eliminar archivos al apagar el ordenador automáticamente

Consiste en hacer rm -rf /var/run/udev al apagar el ordenador (más adelante pondré un ejemplo parecido, junto con otra solución).

Configurar el servidor X a la antigua usanza

Es decir, configurarlo con la ubicación exacta de los dispositivo. En un portátil no pasa nada, casi siempre vamos a tener los dispositivos en el mismo orden (el teclado, el touchpad, etc), aunque no seremos tan “modernos”, y puede que alguna vez sí que tengamos algún problema si se nos ocurre enchufar un teclado externo o varios dispositivos apuntadores o algo así, de esas veces que a udev se le ocurre asignar nombres diferentes a los dispositivos (eso, cuando todo funciona, no es un problema.

La forma de configurar los dispositivos a la antigua usanza es la siguiente (modificanfo /etc/X11/xorg.conf):

Section "InputDevice"
    Identifier     "Configured Mouse"
    Driver         "evdev"
    Option         "CorePointer"
    Option         "Device" "/dev/input/event1"
EndSection

Section "InputDevice"
    Identifier     "Configured Keyboard"
    Driver         "evdev"
    Option         "CoreKeyboard"
    Option         "Device" "/dev/input/event0"
EndSection

Suponiendo que el teclado está en /dev/input/event0 y el ratón (o touchpad) en /dev/input/event1 . Una forma de averiguarlo rápida y sencilla (ya que evdev no funciona bien) es hacer un cat…

$ ls /dev/input/
by-id  by-path  event0  event1  event2  event3  event4  mice  mouse0
$ cat /dev/input/event0

# Tocar las teclas Control, Mayúscula, Alt y alguna de esas que no imprimen caracteres y ver si sale algo por pantalla. Si vemos que sí, ese dispositivo será nuestro teclado. Si movemos el ratón y sale algo, ese dispositivo será el ratón.

# Control +C para salir, puede que cuando terminemos tengamos que hacer reset en la terminal.

$ cat /dev/input/event1

$ reset

Para saber más acerca de configurar los dispositivos para Xorg de esta forma, se pueden visitar las wikis de Gentoo o de Arch Linux, por poner dos ejemplos.

Desactivar AutoAddDevices en Xorg

Lo podemos hacer añadiendo en /etc/X11/xorg.conf las siguentes líneas:

Section "ServerFlags"
   Option "AutoAddDevices" "false"
EndSection

Esto hará que no se usen los drivers de dispositivos de eventos, sino los tradicionales “kbd” y “mouse”, y en algunas distribuciones tendremos que instalarlos a mano, ya que no vienen.

Hacer como que desenchufamos y enchufamos los dispositivos

Y es que en Linux podemos hacerlo de forma muy sencilla, sólo tenemos que descargar un módulo y cargarlo de nuevo. No me extenderé mucho en la explicación, ya que ésta llegará pronto a este blog, e incluso algo más extendida.

Lo malo es que este método está particularizado para los Debian-like (Debian/*Ubuntu/Linux Mint y otros 1000 más, aunque casi casi al 100% funcionarán en otras distribuciones.

Lo primero que tenemos que hacer es añadir el módulo del kernel evdev (sí, al menos tenemos que tenerlo como módulo, si no, debemos elegir una de las otras formas), para ello editamos /etc/modprobe.d/blacklist.conf y añadimos:

blacklist evdev

ahora lo que debemos hacer es cargar automáticamente el módulo de nuevo, así forzamos a udev a releer los nuevos dispositivos /dev/input/event* que se crearán. Para ello, creamos un script de arranque de esos que vemos en /etc/init.d/… y esto es lo que está particularizado para los Debian Like, haré un copia y pega de mi script, ya lo comentaré en profundidad más adelante. llamémoslo evdev_load. NOTA: los comentarios son necesarios :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/bin/sh
#
### BEGIN INIT INFO
# Provides:     evdev_load
# Required-Start:       $dbus
# Required-Stop:
# Default-Start:        2
# Default-Stop:
# X-Interactive:        true
# Short-Description:    Carga el evdev en el arranque
### END INIT INFO

case "$1" in
        start)
                echo "Cargando evdev"
                modprobe evdev
        ;;
esac

Una vez hecho esto, terminamos el proceso de la siguiente manera:

$ sudo update-rc.d evdev_load start 99 2

para que arranque cada vez que arranquemos el sistema.

Foto: JohnJMatlock

Suspensión e hibernación con uswsusp

Lunes, 4 de Julio de 2011 Gaspar Fernández Sin comentarios

Desde hace años, he tenido mala suerte con los sistemas de suspensión de sistema e hibernación. En mi época Windows (que casi todos hemos tenido), casi nunca suspendía el sistema, sobre todo porque, luego no espabilaba, vamos que, unas veces se quedaba el sistema dormido y no respondía, y otras veces parecía que volvía a responder pero no terminaba de encender. El gran problema era que pasara lo que pasara no podía monitorizar el problema, ni arreglarlo, por mucho que investigué. Aunque parece que a día de hoy ya no existe tanto problema con este sistema operativo.

Cuando entré en el mundo Linux, al principio tuve problemas similares, o que directamente no podía hibernar ni suspender porque el sistema no quería sencillamente, la verdad es que investigar un poco en el tema tampoco sirvió de mucho porque parecía que a todo el mundo le funcionaba directamente, menos a mí. Mi cruzada en este ámbito empezó con Gentoo, y por aquel entonces me paré a mirar todos los kernels que tenía disponibles y descubrí el kernel tuxonince, que era especial para hibernar y suspender. En Gentoo no tuve más problemas.

Aunque poco a poco toca renovarse, y en un netbook que utilizo para los viajes instalé Linux Mint Debian Edition, el netbook no es gran cosa, pero me hace el apaño y un tema que me preocupa, ahora sí, es la energía, ya que si estoy con batería (que dura unas escasas 2h:30) y por un momento dejo de utilizarlo, es tiempo que pierdo, por lo que vendría bien suspenderlo, que consuma poca energía y espabilarlo cuando vuelva a utilizarlo (apagarlo y encenderlo, puede ser muy pesado y en ocasiones gastar más energía aún, además de perder tiempo).
Como es normal, de serie no funciona ni la hibernación ni la suspensión, por lo que tuve que buscar alternativas, tal vez más adelante instale los parches de tuxonice, pero por el momento tengo prisa y no quiero compilar el kernel (que puede tirarse unas 3h).

Lo primero fue instalar uswsusp, y dado que no está marcado como estable en Debian, LMDE tampoco lo trae, por lo que las opciones son añadir sid a los repositorios, o bajarlo de aquí.

$ dpkg -i uswsusp_1.0-1_[plataforma].deb

Seguidamente, aunque hice pruebas con pm-utils (instalado por defecto), no logré que nada funcionara, incluso cambiando todas las configuraciones disponibles, por lo que instalé el hibernate script, que utilizaba yo con tuxonice, este sí que viene en el repositorio oficial:

$ apt-get install hibernate

De serie, no funcionó, aunque cambiando algo de configuración sí:

$ sudo nano /etc/hibernate/ususpend-ram.conf

Y cambiar las siguientes líneas:

1
2
USuspendRamForce yes  # Quitamos el comentario, porque mi sistema no lo reconoce automáticamente.
USuspendRamVbeSave yes   # Salvamos el estado del hardware, y luego lo restauramos.

Ahora, para hibernar ejecutamos el hibernate script, tanto hibernate como hibernate-ram para que todo funcione.
Más adelante probaré con tuxonice+LMDE, y publicaré mis resultados.

Índice de soluciones a todos los retos de #tuentiContest

Sábado, 2 de Julio de 2011 Gaspar Fernández Sin comentarios

Aunque se puede acceder a través de las categorías del blog, desechando un poco algunos contenidos, he decidido hacer un índice con las soluciones de todos los Challenges y sus últimas actualizaciones, porque a día de hoy todavía se siguen actualizando y añadiendo nuevas soluciones.
Esto también sirve de referencia para todos aquellos que van a hacer poco a poco y tranquilamente los retos, son y para tener un acceso directo a todos los retos sin necesidad de andar buscando por el blog:

Reto Última actualización Última colaboración
Challenge 1: Super Hard Sum 2011/07/03 @Rosapolis
Challenge 2: TLang 2011/07/08 captain_regex
Challenge 3: Emirps 2011/07/03 @Rosapolis
Challenge 4: Task Duration 2011/07/03 @Rosapolis
Challenge 5: The Milkman Problem 2011/07/03 @Rosapolis
Challenge 6: The Clock 2011/07/03 @Rosapolis
Challenge 7: The Tile Game 2011/07/03 @Rosapolis
Challenge 8: The Biologist Problem 2011/07/03 @Rosapolis
Challenge 9: Christmas Lights 2011/07/04 @lagunex
Challenge 10: Key Combos 2011/07/04 @lagunex
Challenge 11: Gas Stations 2011/07/08 @lagunex
Challenge 12: The Stargate Problem 2011/07/13 @lagunex
Challenge 13: The Other Clock 2011/07/13 @lagunex
Challenge 14: Colors Are Beautiful 2011/07/14 @lagunex
Challenge 15: The Robot 2011/07/19 @lagunex
Challenge 16: The Bus Stations 2011/07/19 @lagunex
Challenge 17: The ¿? Problem 2011/07/03 @Rosapolis
Challenge 18: The Riddle 2011/07/03 @Rosapolis
Challenge 19: The Caesar Salad 2011/07/03 @Rosapolis
Challenge 20: The Clumsy Programmer 2011/07/03 @Rosapolis

Iré actualizando estas páginas a medida que me vayan llegando soluciones. Si has resuelto los retos, ya hayas participado en el concurso o no, puedes enviarme un link con tus soluciones (en pastebin, github, tu blog, etc) en un comentario o un mensaje por twitter (@blakeyed).

Actualización: 2011/07/03 02:40 Añadidas nuevas soluciones a todos, por @frisco82 y @blakeyed
Actualización: 2011/07/03 14:00 Añadidas nuevas soluciones a todos menos el 16, por @Rosapolis
Actualización: 2011/07/04 12:54 Añadida la solución de @lagunex al Challenge 9
Actualización: 2011/07/04 17:35 Añadida la solución de @lagunex al Challenge 10
Actualización: 2011/07/08 12:44 Añadidas soluciones de captain_regex al Challenge 2 y de @lagunex al Challenge 11
Actualización: 2011/07/13 02:49 Añadida solución de @lagunex al Challenge 12
Actualización: 2011/07/13 16:11 Añadida solución de @lagunex al Challenge 13
Actualización: 2011/07/14 14:55 Añadida solución de @lagunex al Challenge 14
Actualización: 2011/07/19 17:55 Añadidas soluciones de @lagunex al Challenge 15 y Challenge 16

Recopilación de soluciones para los retos de #tuentiContest . Challenge #20

Jueves, 30 de Junio de 2011 Gaspar Fernández Sin comentarios

Últimamente he hablado acerca del I concurso de programación de Tuenti. Un concurso de programación Online que se llevó acabo durante la semana pasada (del 13 al 20 de Junio, muy mala fecha).

Podéis ver los enunciados de todos los problemas, con ejemplos sobre la entrada y salida (aunque a veces no hay que hacerles mucho caso) en la web oficial del concurso, pero en Vidas Concurrentes lo encontramos todo en español.

Challenge #20 : The Clumsy Programmer

Tenemos un viejo Debian de 32bits y hemos borrado nuestro home, además hemos perdido las claves para descifrar nuestros datos, ¡tenemos que recuperarla!

Este reto, casi nadie lo completamos, y en principio yo pensaba que era más difícil de lo que era. Romper un RSA de 1024 es algo muy lento, y vi que algunos lo resolvían en menos de 20 minutos. Cuando me enteré me arrepentí de no haber pasado un poco más de tiempo buscando información en lugar de abandonar, la verdad es que llevaba un ritmo de sueño muy raro esa semana, y preferí dormir un poco.

Para resolverlo, teníamos que tener en cuanta la época, no nos decían cuando, pero era un viejo Debian, era de 32bits y estábamos utilizando openssl. Parece ser que allá por 2008 se descubrió un fallo en la versión de OpenSSL que instalaba Debian (y derivados), en la que los números aleatorios necesarios para la clave RSA, en lugar de ser a través de /dev/random eran a través de la PID de OpenSSL, con lo cual tenemos muy pocas posibilidades teniendo en cuenta que muchas veces, las PID no es muy alta (más de 500 y menos de 15000, vamos generalmente), es decir, tenemos un número muy acotado de posibles claves RSA a utilizar, por lo que podemos hacer un script en bash para probarlas todas.

Para más información, podéis visitar:

Soluciones:

Si no estás en la lista y quieres plantear tu solución, deja un comentario con tu link !

Actualización 2011/07/03 01:52 : Añadida solución de @frisco82
Actualización 2011/07/03 13:52 : Añadida solución de @Rosapolis

Recopilación de soluciones para los retos de #tuentiContest . Challenge #16

Martes, 28 de Junio de 2011 Gaspar Fernández 2 comentarios

Últimamente he hablado acerca del I concurso de programación de Tuenti. Un concurso de programación Online que se llevó acabo durante la semana pasada (del 13 al 20 de Junio, muy mala fecha).

Podéis ver los enunciados de todos los problemas, con ejemplos sobre la entrada y salida (aunque a veces no hay que haerles mucho caso) en la web oficial del concurso, pero en Vidas Concurrentes lo encontramos todo en español.

Challenge #16 : The Bus Stations

Nos dan una serie de rutas de autobús entre varias ciudades, con su capacidad de autobuses por día, también nos dicen una ciudad de origen y destino y tenemos que decir cuántos autobuses como máximo podemos poner en marcha cada día.
Soluciones:

Si no estás en la lista y quieres plantear tu solución, deja un comentario con tu link !

Actualización 2011/07/03 01:49 : Añadida solución de @frisco82
Actualización 2011/07/03 13:50 : Añadido mirror a la solución de @Rosapolis
Actualización 2011/07/19 17:55 : Añadida la solución de @lagunex

Recopilación de soluciones para los retos de #tuentiContest . Challenge #12

Sábado, 25 de Junio de 2011 Gaspar Fernández 2 comentarios

Últimamente he hablado acerca del I concurso de programación de Tuenti. Un concurso de programación Online que se llevó acabo durante la semana pasada (del 13 al 20 de Junio, muy mala fecha).

Podéis ver los enunciados de todos los problemas, con ejemplos sobre la entrada y salida (aunque a veces no hay que haerles mucho caso) en la web oficial del concurso, pero en Vidas Concurrentes lo encontramos todo en español.

Challenge #12 : The Stargate Problem

Tenemos que dar saltos entre planetas. Llegar de la Tierra a Atlantis, dando saltos entre planetas a través de Stargates, cada salto tendrá un coste en tiempo, empezaremos en la fecha estelas 25000 y si podemos llegar en el pasado mejor. Eso sí, si no podemos determinar la fecha, tendremos que decir: “BAZINGA”

Soluciones:

Si no estás en la lista y quieres plantear tu solución, deja un comentario con tu link !

Actualización 2011/06/25 13:23 : Añadida solución de @enwillyado
Actualización 2011/06/28 08:30 : Añadida solución de @theom3ga
Actualización 2011/07/03 01:45 : Añadida solución de @frisco82
Actualización 2011/07/03 13:45 : Añadida solución de @Rosapolis
Actualización 2011/07/13 02:48 : Añadida solución de @lagunex

Recopilación de soluciones para los retos de #tuentiContest . Challenge #3

Miércoles, 22 de Junio de 2011 Gaspar Fernández Sin comentarios

Últimamente he hablado acerca del I concurso de programación de Tuenti. Un concurso de programación Online que se llevó acabo durante la semana pasada (del 13 al 20 de Junio, muy mala fecha).

Podéis ver los enunciados de todos los problemas, con ejemplos sobre la entrada y salida (aunque a veces no hay que haerles mucho caso) en la web oficial del concurso, pero en Vidas Concurrentes lo encontramos todo en español.

Challenge #3 :Emirps

Un emirp es un número que tanto él como su capicúa, son primos. Hay que realizar la suma de todos los emirps hasta el número especificado por stdin.

Soluciones:

Si no estás en la lista y quieres plantear tu solución, deja un comentario con tu link !

Actualización 2011/06/22 20:00 : Añadida solución de @Puigcerber
Actualización 2011/06/22 13:50 : Añadida solución de @javipinero
Actualización 2011/06/22 07:58 : Añadida solución de @theom3ga
Actualización 2011/07/02 22:32 : Añadida solución de @frisco82
Actualización 2011/07/03 13:35 : Añadida solución de @Rosapolis

Visita otras webs de la red