# rm-rf.es

Unix: Mostrar listado de últimos reinicios de la máquina

Una entrada rápida y concisa, si queréis ver un historico de los reinicios de una máquina, ejecutad el comando “last reboot”, mostrará la fecha y hora de los últimos reinicios así como la versión de kernel de la máquina:

~$ last reboot
reboot   system boot  2.6.28-11-generi Fri Oct 23 20:52 - 21:58  (01:06)
reboot   system boot  2.6.28-11-generi Thu Oct 22 23:31 - 23:54  (00:23)
reboot   system boot  2.6.28-11-generi Thu Oct 22 21:05 - 23:18  (02:13)

Recordad que el comando “last” tiene más utilidades, como por ejemplo ver los últimos accesos a la máquina, simplemente ejecutad “last”:

~$ last
alex     pts/1        :0.0             Fri Oct 23 21:56   still logged in
alex     pts/0        :0.0             Fri Oct 23 21:54 - 21:58  (00:04)
alex     pts/0        :0.0             Fri Oct 23 21:40 - 21:47  (00:06)
alex     tty7         :0               Fri Oct 23 20:52   still logged in

Comando tr (unix): convertir mayúsculas a minúsculas y viceversa

Un truco rápido con el comando Unix tr, vamos a convertir las letras mayúsculas a minúsculas de un fichero.

Fichero test.txt:

$ cat test.txt
minusculas
MAYUSCULAS

Convertir mayúsculas en minúsculas del fichero test.txt:

$ cat test.txt | tr [:upper:] [:lower:]
minusculas
mayusculas

Convertir minúsculas en mayúsculas del fichero test.txt:

$ cat test.txt | tr [:lower:] [:upper:]
MINUSCULAS
MAYUSCULAS

Por supuesto, el comando tr nos ofrece muchas más opciones para transformación de carácteres, os dejo la ayuda del comando, recordad que en las páginas man hay mucha más información.

$ tr --help
Modo de empleo: tr [OPCIÓN]... CONJUNTO1 [CONJUNTO2]
Traducir, comprimir, y/o borrar caracteres de la entrada estándar,
escribiendo a la  entrada estándar.

  -c, -C, --complement    primer compliment SET1
  -d, --delete            borrar caracteres en SET1, no traducir
  -s, --squeeze-repeats   reemplazar cada secuencia de entradas de un caracter repetido
                            esta es una lista de SET1 con una sóla coincidencia
                            de ese caracter
  -t, --truncate-set1     primero truncar SET1 a la longitud de SET2
      --help     muestra esta ayuda y finaliza
      --version  informa de la versión y finaliza

Los CONJUNTOs se especifican como cadenas de caracteres. La mayoría se
representan a sí mismos.
Las secuencias válidas son las siguientes:

  \NNN            carácter con valor octal NNN (de uno a tres dígitos)
  \\              barra invertida
  \a              pitido audible (BEL)
  \b              espacio hacia atrás
  \f              salto de página
  \n              salto de línea
  \r              retorno de carro
  \t              tabulación horizontal
  \v              tabulación vertical
  CAR1-CAR2       todos los caracteres comprendidos entre CAR1 y CAR2 contados
                  en orden ascendente
  [CAR*]          en CONJUNTO2, copias de CAR hasta que se alcance la longitud
                  de CONJUNTO1
  [CAR*REPITE]    copia REPITE veces CAR; REPITE es octal si comienza con 0
  [:alnum:]       todas las letras y dígitos
  [:alpha:]       todas las letras
  [:blank:]       todos los espacios en blanco horizontales
  [:cntrl:]       todos los caracteres de control
  [:digit:]       todos los dígitos
  [:graph:]       todos los caracteres imprimibles, sin incluir el espacio
  [:lower:]       todas las letras minúsculas
  [:print:]       todos los caracteres imprimibles, incluyendo el espacio
  [:punct:]       todos los caracteres de puntuación
  [:space:]       todos los espacios en blanco horizontales y verticales
  [:upper:]       todas las letras mayúsculas
  [:xdigit:]      todos los números hexadecimales
  [=CAR=]         todos los caracteres que son igual que CAR

Se produce la traducción si no se especifican CONJUNTO1 y CONJUNTO2, siempre
y cuando no aparezca la opción -d. -t se puede usar sólo al traducir.
CONJUNTO2 se expande a la longitud de CONJUNTO1, repitiendo su último
carácter tantas veces como sea necesario.  Los caracteres que sobran en
CONJUNTO2 no se tienen en cuenta. Solamente se garantiza que [:lower:]
y [:upper:] sean expandidos en orden ascendente; si se usa en
CONJUNTO2 al traducir, sólo se pueden usar en parejas, para
especificar conversión a mayúsculas.  -s usa CONJUNTO1 si no se está
traduciendo ni borrando; si no, la compresión usa CONJUNTO2 después de
la traducción o el borrado.

Cómo montar un sistema de ficheros NFS (Cliente Linux)

El Network File System (Sistema de archivos de red), o NFS, es un protocolo de nivel de aplicación, según el Modelo OSI. Es utilizado para sistemas de archivos distribuido en un entorno de red de computadoras de área local. Posibilita que distintos sistemas conectados a una misma red accedan a ficheros remotos como si se tratara de locales. Wikipedia

Vamos a suponer que tenemos montado un servidor con comparticiones NFS (otro día explicaré detalladamente como se monta un servidor NFS). En el caso de querer conectarnos a ese sistema de ficheros desde un equipo remoto (cliente), tendremos que hacerlo del siguiente modo:

mount host:/comparticion /punto/de/montaje

En el ejemplo encontramos:

  • Host: IP o FQDN del servidor que está compartiendo vía NFS
  • /compartición: Ruta que comparte el servidor NFS
  • /punto/de/montaje: Lugar en el que queremos montar la compartición NFS (Punto de montaje)

Un ejemplo real podría ser:

$ mkdir /mnt/compartido
$ mount 192.168.0.199:/home/compartido /mnt/compartido

Una vez realizado, si hacemos un df veremos que efectivamente la unidad ha sido montada satisfactoriamente, y tenemos acceso a ella a través de /mnt/compartido. Para que esto se mantenga tras el reinicio de la máquina, hemos de incluir la línea correspondiente en el fichero /etc/fstab. Por ejemplo, para el ejemplo anterior añadiríamos una línea similar a lo que sigue.

La estructura de la línea es la siguiente:

<server>:</path/of/dir> </local/mnt/point> nfs <options> 0 0

Y en nuestro ejemplo (con opcion de read-write, lectura escritura):

192.168.0.199:/home/compartido /mnt/compartido nfs rw 0 0

Recomiendo no obstante revisar la documentación de Red-Hat pues detallan de forma extensa y muy buena todas las opciones disponibles.

Próximamente montaremos un servidor NFS desde cero.

nohup: Mantiene la ejecución de un comando pese a salir de la terminal

El comando nohup permite mantener la ejecución de un comando (el cual le pasamos como un argumento) pese a salir de la terminal (logout), ya que hace que se ejecute de forma independiente a la sesión.

Básicamente, lo que hace es ignorar la señal HUP (señal que se envía a un proceso cuando la terminal que lo controla se cierra), esto implica que aunque cerremos la terminal, el proceso se siga ejecutando.

La propia ayuda disponible en la shell (y en las páginas man) nos ayudará a entender el modo de ejecución del comando:

$ nohup --help
Modo de empleo: nohup ORDEN [ARGUMENTO]...
       o bien:  nohup OPCIÓN
Ejecuta ORDEN, descartando las señales de colgar.

      --help     muestra esta ayuda y finaliza
      --version  informa de la versión y finaliza

si la entrada estándar es una terminal, redirigirla desde /dev/null.
si la salida estándar es una terminal, añadir la salida a `nohup.out` si es posible,
en caso contrario a `$HOME/nohup.out`.
si los errores van a una terminal, redirigirlos a la salida estándar.
Para guardar la salida a FILE, use `nohup COMMAND > FILE`

Un ejemplo sencillo sería la ejecución en segundo plano de un script cualquiera, gracias al comando nohup permitiremos la continuidad de la ejecución en caso de cualquier problema con la sesión, shell de ejecución, etc:

$ nohup ./miscript.sh &

Por defecto, la salida del comando, que normalmente aparecería directamente en la terminal, será procesada a un fichero llamado nohup.out que aparecerá en la ruta donde nos encontremos al ejecutar el comando.

Monitorización de CPU y actividad de discos duros con iostat

El comando iostat es utilizado para monitorizar la actividad de los dispositivos, particiones y sistemas en red (NFS) del sistema, además también muestra una media en % del uso de CPU en la máquina.

Una muestra de la salida del comando iostat:

$ iostat
Linux 2.6.28-11-generic (sistemas) 	01/07/09 	_i686_	(2 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
          12,70    0,00    3,72    0,90    0,00   82,77

Device:            tps   Blk_read/s   Blk_wrtn/s   Blk_read   Blk_wrtn
sda               4,38       127,82        85,96    1811478    1218136
sda1              0,00         0,00         0,00          6          0
sda2              0,06         1,80         5,14      25446      72792
sda3              3,93       103,94        76,24    1473036    1080432
sda5              0,31        22,02         4,58     312118      64912

Podéis ver que para los dispositivos nos muestra en columnas lo siguiente:

Device: (Dispositivo) tps (transferencias por segundo, cada una es una única request de I/O al dispositivo) Blk_read/s (Bloques de datos leidos por segundo) Blk_wrtn/s (Bloques de datos escritos por segundo) Blk_read (Bloques totales de datos leidos) Blk_wrtn (Bloques totales de datos escritos por segundo).

La primera vez que ejecutamos el comando, nos muestra un reporte con datos recopilados desde el último reinicio, posteriormente recopilará los datos desde la última vez que hemos ejecutado el comando. El uso y opciones del comando es el siguiente:

Uso: iostat [ opciones ] [ [ ] ]

Las opciones son:

[ -c ] [ -d ] [ -N ] [ -n ] [ -h ] [ -k | -m ] [ -t ] [ -V ] [ -x ]
[ [ ... ] | ALL ] [ -p [ | ALL ] ]

Donde las opciones más comunes son el intervalo, mediante el cual podemos especificar el tiempo en segundos entre cada reporte, “-c” para mostrar el reporte de utilización de cpu, “-d” para mostrar la utilización de los dispositivos, “-m” para mostrar los datos en megas, etc.

Como siempre, toda la información sobre cada opción y la salida del programa la tenéis muy detallada en la página man:

man iostat

A continuación podéis ver unos ejemplos:

iostat -d 2

Mostrará el reporte de dispositivos cada dos segundos

iostat -d 2 6

Mostrará séis reportes con un intervalo entre cada uno de 2 segundos

iostat -x hda hdb 2 6

Mostrará un reporte con estadísticas extendidas, cada dos segundos y en séis ocasiones de los dispositivos hda y hdb.

Apache: Semget: No space left on device

Si no conseguís arrancar apache y encontráis en el error_log entradas como estas:

[Fri Apr  3 19:25:05 2009] [warn] pid file /usr/local/apache/logs/httpd.pid overwritten -- Unclean shutdown of previous Apache run?
semget: No space left on device
[Fri Apr  3 19:50:05 2009] [warn] pid file /usr/local/apache/logs/httpd.pid overwritten -- Unclean shutdown of previous Apache run?
semget: No space left on device
[Fri Apr  3 20:00:05 2009] [warn] pid file /usr/local/apache/logs/httpd.pid overwritten -- Unclean shutdown of previous Apache run?
semget: No space left on device
[Fri Apr  3 20:17:12 2009] [warn] pid file /usr/local/apache/logs/httpd.pid overwritten -- Unclean shutdown of previous Apache run?
semget: No space left on device
[Fri Apr  3 20:17:34 2009] [warn] pid file /usr/local/apache/logs/httpd.pid overwritten -- Unclean shutdown of previous Apache run?
semget: No space left on device

El problema se centra en el kernel del sistema, significa que no queda espacio en el array de semáforos de Apache. Podéis ver el llenado ejecutando el siguiente comando:

# ipcs -s
------ Matrices semáforo -------
key        semid      propietario perms      nsems
0x00000000 3538944    nobody    600        1
0x00000000 3571713    nobody    600        1
0x00000000 3604482    nobody    600        1
0x00000000 3637251    nobody    600        1
0x00000000 3670020    nobody    600        1
0x00000000 3702789    nobody    600        1
0x00000000 3735558    nobody    600        1
0x00000000 3768327    nobody    600        1
0x00000000 3801096    nobody    600        1
0x00000000 3833865    nobody    600        1
0x00000000 7340143    nobody    600        1
0x00000000 7372912    nobody    600        1
0x00000000 7405681    nobody    600        1
0x00000000 7438450    nobody    600        1
0x00000000 7471219    nobody    600        1
0x00000000 7503988    nobody    600        1
0x00000000 7536757    nobody    600        1
0x00000000 7569526    nobody    600        1
0x00000000 7602295    nobody    600        1
0x00000000 7635064    nobody    600        1
0x00000000 7667833    nobody    600        1
0x00000000 7700602    nobody    600        1
0x00000000 7733371    nobody    600        1
0x00000000 7766140    nobody    600        1
0x00000000 7798909    nobody    600        1
0x00000000 7831678    nobody    600        1
0x00000000 7864447    nobody    600        1

Para no tener que reiniciar, la solución es vaciar este array, podéis hacerlo de este modo:

ipcs -s | awk '{print "ipcrm -s " $2}' | bash

Ahora ya podemos reiniciar apache sin problemas. Quizás ahora toca revisar si alguna aplicación está provocando este llenado.

Unix: Operadores de control

Es extremadamente útil (y casi necesario) conocer los operadores de control de consola Unix, que te permitiran combinar comandos, a continuación os muestro el modo de usar estos operadores de control:

Ejecutar un comando si el anterior devuelve el estado “zero exit”:

Para ello utilizaremos el operador de control && El segundo comando solamente se ejecutará si el anterior devuelve estado “zero exit”, o lo que es lo mismo, se ejecuta correctamente, ejemplo:

cd tmp/a/b/c && tar xvf ~/archivo.tar

En este ejemplo, se descomprimira archivo.tar en la ruta a la que accedemos, pero solo si esta existe, o lo que es lo mismo, si “cd tmp/a/b/c” se ejecuta correctamente.

Ejecutar un comando si el anterior devuelve el estado ” non-zero exit”:

Ahora vamos a hacer justo lo contario, solo ejecutaremos el segundo comando si el primero falla. Para ello concatenaremos los comandos con el operador de control ||, ejemplo:

cd tmp/a/b/c || mkdir -p tmp/a/b/c

En este ejemplo, crearemos el árbol de directorios tmp/a/b/c solamente si el comando anterior falla, es decir, si no existe.

Los dos operadores de control pueden combinarse si se desea, para crear comandos un poquito más complejos, ejemplo:

cd tmp/a/b/c || mkdir -p tmp/a/b/c && tar xvf -C tmp/a/b/c ~/archive.tar

Artículo basado en Unix Tips de IBM.

Quitar carácteres ^M del final de las líneas en ficheros que provienen de Windows

Muchas veces si editamos con VI o desde algún otro editor Unix un fichero que proviene de Windows puede que nos encontremos con los carácteres ^M al final de todas las líneas. Realmente no hay ningún problema, pero resulta bastante incómodo, os dejo un par de formas de eliminarlos de forma rápida y sencilla:

Con SED:

sed 's/<Ctrl-V><Ctrl-M>//g' -i fichero

Con VI:

<Esc>:%s/<Ctrl-V><Ctrl-M>//g

Vía | blog.transmit.net