# rm-rf.es | Administración de sistemas

Bitácora personal de un SysAdmin Gnu/Linux, Windows, BSD...

Gestión de particiones con parted en Linux

gnu partedHace un tiempo aprendimos a gestionar discos y particiones con fdisk, ahora vamos ver como trabajar con el programa GNU parted, que permite particionar y redimensionar discos, así como crear, redimensionar y copiar sistemas de fichero extX, swap, FAT y FAT32 (luego veremos que es recomendable utilizar las herramientas propias de Linux en lugar que las que ofrece parted en algunos casos).

Vamos a partir de un disco (virtual) sin particionar. Lo primero que vemos al acceder a parted es un error, ya que parted necesita que el disco tenga una etiqueta (LABEL) para poder trabajar con él:

# parted /dev/sdb
GNU Parted 2.1
Usando /dev/sdb
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) print
Error: /dev/sdb: unrecognised disk label

Normalmente se utiliza la etiqueta ‘msdos’ ya que Microsoft y OS/2 es la que reconocen, así que la asignamos con el comando mklabel:

(parted) mklabel
¿Nuevo tipo de etiqueta de disco? msdos

En todo momento podéis ver los comandos disponibles escribiendo el signo de interrogación (?)

(parted) ?
  align-check TYPE N                        check partition N for TYPE(min|opt) alignment
  check NUMBER                             do a simple check on the file system
  cp [DESDE-DISPOSITIVO] DE-NUMERO A-NUMERO   copia el sistema de ficheros a otra partición
  help [COMMAND]                           print general help, or help on COMMAND
  mklabel,mktable LABEL-TYPE               create a new disklabel (partition table)
  mkfs NUMBER FS-TYPE                      make a FS-TYPE file system on partition NUMBER
  mkpart TIPO-PART [TIPO-SF] INICIO FIN     crea una partición
  mkpartfs TIPO-PART TIPO-SF INICIO FIN     crear una partición con un sistema de ficheros
...
...
...

print: listar discos duros, particiones y espacio libre

El comando print nos permite por un lado mostrar todos los dispositivos (discos duros) reconocidos por el sistema:

(parted) print devices
/dev/sdb (268MB)
/dev/sda (12,7GB)

También las particiones de cada uno y/o el espacio libre:

(parted) print free
Model: ATA VBOX HARDDISK (scsi)
Disk /dev/sdb: 268MB
Sector size (logical/physical): 512B/512B
Partition Table: msdos

Numero  Inicio  Fin    Tamaño  Typo  Sistema de ficheros  Banderas
        32,3kB  268MB  268MB         Free Space

mkpart: crear una partición sin filesystem

Parted nos da la opción de crear una partición y al mismo tiempo el sistema de ficheros (lo vemos más adelante), pero de momento únicamente vamos a crear una partición estándar sin asignar filesystem. Podemos hacer dos cosas, o seguir el asistente o escribir la línea de comandos completa directamente. Para comenzar lo más sencillo es el asistente:

Partición primaria de 100MB que será usada como filesystem ext4

(parted) mkpart
¿Tipo de partición?  primary/primaria/extended/extendida? primary
¿Tipo de sistema de ficheros?  [ext2]? ext4
¿Inicio? 1
¿Fin? 100

Si ejecutamos un print list veremos la nueva partición lista para ser formateada con mkfs.ext4:

(parted) print
Model: ATA VBOX HARDDISK (scsi)
Disk /dev/sdb: 268MB
Sector size (logical/physical): 512B/512B
Partition Table: msdos

Numero  Inicio  Fin     Tamaño  Typo     Sistema de ficheros  Banderas
 1      1049kB  99,6MB  98,6MB  primary

mkpartfs: crear una partición con filesystem

Como comentaba antes, parted permite dar formato a la partición en el proceso de creación, aunque claramente vemos al ejecutarlo que recomiendan encarecidamente hacer uso de las herramientas adecuadas para ello (mkfs.extX, e2fsprogs). Así que simplemente vamos a ver como hacerlo por curiosidad (además no soporta ni ext3 ni ext4, sólo ext2…):

WARNING: you are attempting to use parted to operate on (mkpartfs) a file system.
parted’s file system manipulation code is not as robust as what you’ll find in
dedicated, file-system-specific packages like e2fsprogs. We recommend
you use parted only to manipulate partition tables, whenever possible.
Support for performing most operations on most types of file systems
will be removed in an upcoming release.

(parted) mkpartfs
WARNING: you are att.....
will be removed in an upcoming release.
¿Tipo de partición?  primary/primaria/extended/extendida? primary
¿Tipo de sistema de ficheros?  [ext2]? ext2
¿Inicio? 100
¿Fin? 200

Y ya tenemos la partición con sistema de ficheros ext2:

(parted) print
Model: ATA VBOX HARDDISK (scsi)
Disk /dev/sdb: 268MB
Sector size (logical/physical): 512B/512B
Partition Table: msdos

Numero  Inicio  Fin     Tamaño  Typo     Sistema de ficheros  Banderas
 1      1049kB  99,6MB  98,6MB  primary
 2      99,6MB  200MB   101MB   primary  ext2
# mount /dev/sdb2 /test
# df -h | grep /test
/dev/sdb2              90M   13K   86M   1% /test
# umount /test

rm: eliminar una partición

Para eliminar una partición con parted es tan simple como ejecutar “rm” seguido del número de la partición:

(parted) print
Model: ATA VBOX HARDDISK (scsi)
Disk /dev/sdb: 268MB
Sector size (logical/physical): 512B/512B
Partition Table: msdos

Numero  Inicio  Fin     Tamaño  Typo     Sistema de ficheros  Banderas
 1      1049kB  99,6MB  98,6MB  primary
 2      99,6MB  200MB   101MB   primary  ext2
(parted) rm 2  /pre>

check: comprobación de un filesystem

Existen otras opciones, como por ejemplo hacer un check al sistema de ficheros, pero igual que con mkpartfs recomiendan utilizar herramientas propias del sistema como fsck. Además, no soportan sistemas de ficheros ext4 o ext3:

(parted) check 1
WARNING: you are attempting to use parted to operate on (check) a file system.
parted's file system manipulation code is not as robust as what you'll find in
dedicated, file-system-specific packages like e2fsprogs.  We recommend
you use parted only to manipulate partition tables, whenever possible.
Support for performing most operations on most types of file systems
will be removed in an upcoming release.
Sin Implementación: El soporte para abrir el sistema de ficheros ext4 aún no está implementado.

Si revisáis la página man o la propia salida de ‘?’ veréis otras opciones, como mkfs para formatear sistemas de ficheros (como comentaba antes, no recomendable) y otras más interesantes como rescue, que permite recuperar una partición perdida indicando su posición de inicio y fin:

(parted) rescue INICIO FIN

Os recomiendo como siempre revisar la página man o la salida de ‘?’ para descubrir todas sus posibilidades, como redimensionar una partición con resize, moverla con move, etc. Eso sí, recordad que es preferible usar los comandos/herramientas propios del sistema para mayor seguridad en estos casos.

Configurar una VLAN en Linux con vconfig

La forma más conocida de configurar una VLAN en Linux es la de copiar el fichero de configuración de la interfaz y añadir/cambiar ciertos parámetros, ejemplo en RHEL asumiendo el ID 80 para la VLAN:

# cp -p /etc/sysconfig/network-scripts/ifcfg-eth0 /etc/sysconfig/network-scripts/ifcfg-eth0.80
# vim /etc/sysconfig/network-scripts/ifcfg-eth0.80
    # Añadimos:
    VLAN=yes
    # Cambiamos el dispositivo:
    DEVICE=eth0.80
# /etc/init.d/network restart

El comando vconfig nos simplifica un poco la tarea de gestionar una o varias VLAN. Para el ejemplo anterior, sería tan sencillo como:

# vconfig add eth0 80
Added VLAN with VID == 80 to IF -:eth0:-

Ya tenemos la interfaz creada:

# ifconfig eth0.80
eth0.80   Link encap:Ethernet  HWaddr 08:00:27:E7:48:CC
          BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 b)  TX bytes:0 (0.0 b)

Podemos ver información detallada sobre ella en /proc/net/vlan/:

# cat /proc/net/vlan/eth0.80
eth0.80  VID: 80	 REORDER_HDR: 1  dev->priv_flags: 1
         total frames received            0
          total bytes received            0
      Broadcast/Multicast Rcvd            0

      total frames transmitted            0
       total bytes transmitted            0
            total headroom inc            0
           total encap on xmit            0
Device: eth0
INGRESS priority mappings: 0:0  1:0  2:0  3:0  4:0  5:0  6:0 7:0
 EGRESS priority mappings:

Podríamos asignarle la IP con el comando ifconfig:

# ifconfig eth0.80 192.168.1.222 netmask 255.255.255.0

Y si quisiéramos eliminar la interfaz:

# ifconfig eth0.80 down && vconfig rem eth0.80

Recordad que tiene que estar cargado en el kernel el módulo 8021q:

# lsmod | grep 8021q
8021q                  19491  0
garp                    5901  1 8021q

En fin, ¡para gustos los colores!

SELinux ‘semanage: command not found’

semanage (SELinux Policy Management tool) es un comando que permite configurar políticas de SELinux en RHEL, CentOS, etc. Lo más probable es que en un sistema Red Hat 6 instalado por defecto (base) el comando no se encuentre disponible:

# semanage login -l
semanage: command not found

Si visteis el artículo que hice hace un tiempo sobre trucos de yum recordaréis que con “whatprovides” podemos encontrar rápidamente el paquete que contiene un determinado binario/fichero:

# yum whatprovides */semanage
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * base: sunsite.rediris.es
 * extras: sunsite.rediris.es
 * updates: sunsite.rediris.es
libsemanage-devel-2.0.43-4.el6.i686 : Header files and libraries used to build
                                    : policy manipulation tools
Repo        : base
Matched from:
Filename    : /usr/include/semanage

policycoreutils-python-2.0.83-19.1.el6.i686 : SELinux policy core python
                                            : utilities
Repo        : base
Matched from:
Filename    : /usr/sbin/semanage

policycoreutils-python-2.0.83-19.8.el6_0.i686 : SELinux policy core python
                                              : utilities
Repo        : updates
Matched from:
Filename    : /usr/sbin/semanage

Así que instalamos el paquete (y sus dependencias) y listo:

# yum install policycoreutils-python-2.0.83-19.1.el6.i686
# semanage login -l

Login Name         SELinux User           MLS/MCS Range            

__default__               unconfined_u              s0-s0:c0.c1023
root                      unconfined_u              s0-s0:c0.c1023
system_u                  system_u                  s0-s0:c0.c1023

Arrancar Linux manualmente desde Grub (configuración de Grub borrada o incorrecta)

Existe la posibilidad de que llegue un día, arranquemos uno de nuestros sistemas GNU/Linux y en el momento en el que deberíamos visualizar el menú de Grub con los sistemas y Kernel disponibles para arrancar nos encontremos con esto:

grub>
grub shell

Antes de entrar en modo pánico debemos tener unas nociones básicas que nos permiten arrancar un sistema manualmente desde Grub cuando su fichero de configuración ha sido borrado o está vacío/incorrecto. Básicamente se trata de construir y ejecutar manualmente las líneas que componen cada entrada en el fichero grub.conf o menu.lst. El siguiente ejemplo práctico ha sido realizado sobre un sistema CentOS (RHEL, Fedora, etc) con el fichero /etc/grub.conf | /boot/grub/grub.conf eliminado.

Bien, para arrancar el sistema de forma correcta tenemos que establecer una secuencia de tres comandos en la que especifiquemos lo siguiente:

Partición que contiene el kernel

Una vez que estemos en la shell de Grub, si ejecutamos el comando root a secas nos dirá la partición en la cual se encuentra el/los kernel (podéis usar [TAB] para ver los comandos disponibles:

grub> root
 (hd0,0): Filesystem type is ext2fs, partition type 0x83

Ya sabemos que la partición que contiene el kernel, imágenes initrd y demás es la (hd0,0), podemos navegar por ella usando el comando find y haciendo uso de la tabulación para el auto-completado de nombres, lo verificamos:

grub> find (hd0,0)/ <- presionad [TAB]
 Possible files are: lost+found grub efi initramfs-2.6... vmlinux-2.6.....

Una vez verificado ejecutamos el siguiente comando (normalmente no es necesario ya que como vemos anteriormente lo detecta automáticamente):

grub> root (hd0,0)

Especificar el kernel y ruta al filesystem

grub> kernel /vmlinuz-2.6.32-71.el6.i686  ro root=/dev/sda1

Ya sabemos que el kernel está en /vml* así que lo especificamos como veis en la línea superior, usad el auto completado con [TAB] para no tener que escribir todo el nombre. Especificamos que en primera instancia se tiene que arrancar en modo lectura (ro) y finalmente la ruta a la partición root de nuestro sistema (dev/sda1). La partición root es la que contiene /sbin/init, también se puede especificar mediante el UUID. Si no sabemos cual es podemos localizarla con el siguiente comando:

grub> find /sbin/init
 (hd0,1)

(hd0,1)=/dev/sda2

Otra forma sería consultando el fichero fstab:

grub> cat (hd0,1)/etc/fstab

Ubicación del Initial RAM disk

El RAM disk se encuentra en la misma ruta/partición que el kernel:

grub> initrd /initramfs-2.6.32-71.el6.i686.img

Secuencia completa para arrancar el sistema

Haciendo un resumen y añadiendo el último comando para arrancar el sistema (boot) quedaría así:

grub> root (hd0,0)
grub> kernel /vmlinuz-2.6.32-71.el6.i686  ro root=/dev/sda1
grub> initrd /initramfs-2.6.32-71.el6.i686.img
grub> boot

Si todo va bien, debería arrancar sin problemas el sistema. Una vez dentro podréis restaurar el Grub con tranquilidad.

RHEL/CentOS 6: adios System V, hola Upstart

Uno de los cambios importantes que hemos encontrado con la salida de Red Hat Enterprise Linux 6 y por consiguiente CentOS 6 es el cambio del sistema de arranque de los servicios. El nuevo sistema tiene por nombre Upstart y reemplaza al que nos acompañó durante muchos años, System V.

Una de las principales diferencias entre System V y Upstart es que el primero trabaja de forma sincrona mientras que Upstart lo hace de forma asíncrona, es decir, no arranca/para un servicio después de otro sino que puede hacerlo en paralelo. Esto implica un aumento considerable de la velocidad de arranque y evita que un servicio tenga esperar a que otro termine para poder arrancar. Otra característica interesante de Upstart es que tiene la capacidad de supervisar los servicios mientras el sistema está funcionando. Upstart también es compatible con los scripts de arranque del sistema System V por lo cual la migración de un sistema a otro es más sencilla.

Los scripts de arranque basados en System V seguirán emplazados en /etc/init.d, mientras que los basados en Upstart debemos añadirlos en /etc/init/*.conf. Podemos ver un ejemplo de la sintaxis utilizada revisando cualquiera de los que ahí se encuentran. De momento podréis ver que únicamente hay scripts propios de sistema, los servicios siguen teniendo sus scripts de arranque en init.d. Vamos a crear un script sencillo para que veáis su funcionamiento. Básicamente queremos que un script propio de prueba esté siempre corriendo, que arranque en el runlevel 3 y que si cae se levante de forma automática:

vim /etc/init/test.conf

#
# Este servicio arranca y monitoriza nuestro script test.sh.
start on runlevel 3

respawn
respawn limit 15 5
exec sh /root/test.sh

Mediante “respawn” especificamos que en caso de que el servicio termine de forma inesperada, Upstart intente levantarlo. Después, con “respawn limit” especificamos el número de intentos y durante cuanto tiempo. En caso de pasar ese tiempo/número de intentos dejaría de intentarlo y el servicio quedaría detenido.

Arrancamos el servicio con el comando initctl:

# initctl start test
test start/running, process 1581

Si matamos el script, veremos en el log /var/log/messages como automáticamente lo levanta. En caso de tener 10 intentos fallidos durante 5 segundos (especificado en el script) dejaría de intentarlo y el script quedaría parado:

# kill 1581
# tail -2 /var/log/messages
Oct 30 19:18:45 server1 init: test main process (1581) killed by TERM signal
Oct 30 19:18:45 server1 init: test main process ended, respawning

Podéis encontrar más información sobre initctl en la salida de ayuda del propio comando, páginas man, etc. También de init:

# initctl help
Job commands:
  start                       Start job.
  stop                        Stop job.
  restart                     Restart job.
  reload                      Send HUP signal to job.
  status                      Query status of job.
  list                        List known jobs.

Event commands:
  emit                        Emit an event.

Other commands:
  reload-configuration        Reload the configuration of the init daemon.
  version                     Request the version of the init daemon.
  log-priority                Change the minimum priority of log messages from the init daemon
  help                        display list of commands

For more information on a command, try `initctl COMMAND --help'.
# man init
# man initctl

Getlibs: encontrar dependencias en librerías (64 vs 32 bits)

El otro día tuvimos que instalar software de 32 bits en una máquina virtual de Debian de 64 bits. Tras la instalación encontramos problemas con dependencias incumplidas que hacían referencia a librerías de 32 bits que no se encontraban instaladas en el sistema. A partir de ahí, gracias a getlibs (¡y a Ángel!) pudimos instalar de forma sencilla todas las librerías necesarias. Todo ello debido a que dicho software no disponía de versión para Debian en 64 bits.

Lo primero que hicimos fue descargar e instalar getlibs:

$ wget http://frozenfox.freehostia.com/cappy/getlibs-all.deb
$ sudo dpkg -i getlibs-all.deb

Después sólo queda ejecutar getlibs seguido de la ruta al binario que da problemas para que automáticamente podamos resolver todas las dependencias:

$ getlibs
Usage: getlibs /path/to/binary
       getlibs -l i386librarytoinstall.so
       getlibs -p i386packagename
       getlibs -w www.website.com/i386package.deb
       getlibs -i /home/alex/i386package.deb
       See 'man getlibs' for more commands

¿Cómo arrancar en modo emergencia en RHEL 6 / CentOS 6?

Existen una serie de runlevels que nos permiten arrancar un sistema Linux con distintas características según nuestras necesidades. En el anterior enlace los tenéis detallados. En anteriores versiones de RHEL, CentOS y derivados cuando necesitábamos acceder al sistema en modo emergencia (sin necesidad de especificar la clave de root y sin los sistemas de ficheros montados en modo RW) añadíamos a la línea de arranque que se le pasa al kernel en el grub el parámetro emergency. Este parámetro ya no se usa y se ha pasado a utilizar dos variantes.

En primer lugar, hay que decir que para acceder cambiando el runlevel hay que añadir a la línea de comando que se pasa al kernel el número del runlevel. Para ello, en el grub presionamos la letra a y añadimos el número del runlevel:

RHEL-grub

Presionamos ‘a’ para añadir un parámetro nuevo a la línea y ya podemos añadir el runlevel deseado.

RHEL-grub2

Para RHEL 6, CentOS6 y derivados, en lugar de emergency tenemos dos opciones para entrar en modo emergencia:

  • single: Modo single user, el arranque será como el runlevel 1 pero sin ejecutar los scripts de arranque en /etc/rc1.d
  • init=/bin/sh: Este sería el equivalente al modo emergencia, no ejecuta ningún script de arranque e únicamente monta la partición raíz (/) en modo lectura.

Si queremos ver el proceso de arranque, podemos quitar de la línea las palabras rhgb quiet (arranque gráfico). Para entrar en modo emergencia quedaría una línea como la de la siguiente imagen. Presionamos ENTER y arrancará el sistema:

Emergency mode RHEL 6

ACL (Access Control List) en sistemas de ficheros GNU/Linux

Para un usuario medio de GNU/Linux e incluso para la mayoría de usuarios avanzados, las posibilidades que nos ofrecen el sistema de permisos y propietario estándar es más que suficiente. No obstante, conviene conocer el sistema de listas de control de acceso, conocido comúnmente como ACL (Access Control List) que nos permite extender estos permisos a nivel de ficheros y directorios.

Estas ACL permiten definir permisos concretos para un determinado usuario o grupo en ficheros y directorios, además, se asignan igual que los permisos estándar, con formato octal o simbólico (rwx). Básicamente, en caso de tener un fichero o directorio con unos permisos concretos determinados para su propietario y grupo, nos permite añadir usuarios o grupos extra con unos permisos completamente independientes a los definidos con los permisos estándar.

Activar ACL en el sistema de ficheros

Verificamos con el comando tune2fs si el sistema de ficheros sobre el que queremos tener ACL tiene activado ACL:

# tune2fs -l /dev/mapper/VolGroup00-LogVol00 | grep acl
Default mount options:    user_xattr acl

En caso de no aparecer la opción, tendríamos que remontar el filesystem añadiendo la flag, para hacerlo persistente habría que añadirla en el /etc/fstab.

[root@cluster01 ~]# mount -o remount,acl /
# mount
/dev/mapper/VolGroup00-LogVol00 on / type ext3 (rw,acl)

Ver y cambiar las ACL en ficheros/directorios

Para listar los permisos genéricos de un fichero o directorio y las ACL utilizamos el comando getfacl

# getfacl prueba.tmp
# file: prueba.tmp
# owner: root
# group: root
user::rw-
group::r--
other::r--

El fichero prueba.tmp no tiene ACL establecidas, sólo vemos los permisos estándar. Para comenzar a añadir permisos de ACL utilizamos el comando setfacl. En la página man encontramos información relativa a la sintaxis y formato para el cambio de permisos en usuarios y grupos, máscara y otros:

      [d[efault]:] [u[ser]:]uid [:perms]
              Permissions of a named user. Permissions of the file owner if uid is empty.

       [d[efault]:] g[roup]:gid [:perms]
              Permissions of a named group. Permissions of the owning group if gid is empty.

       [d[efault]:] m[ask][:] [:perms]
              Effective rights mask

       [d[efault]:] o[ther][:] [:perms]
              Permissions of others.

Vamos a ver algún ejemplo. En este primer caso vamos a asignar permiso total (777) al usuario foo contra el fichero anterior, del cual es propietario root.

# setfacl -m u:foo:7 prueba.tmp

Y ahí lo tenemos, con sus permisos especiales asignados con ACL:

# getfacl prueba.tmp 
# file: prueba.tmp
# owner: root
# group: root
user::rw-
user:foo:rwx
group::r--
mask::rwx
other::r--

También los podemos asignar con notación simbólica en lugar de octal, vamos a cambiarlo a únicamente lectura para foo:

# setfacl -m u:foo:r prueba.tmp
# getfacl prueba.tmp 
# file: prueba.tmp
# owner: root
# group: root
user::rw-
user:foo:r--
group::r--
mask::r--
other::r--

Si nos fijamos, al listar el fichero con un ls vemos que ha aparecido un ‘+’ indicando que hay ACLs asignadas:

# ll prueba.tmp
-rw-r--r--+ 1 root root 0 Sep 28 17:32 prueba.tmp

Si con el parámetro ‘-m’ cambiabamos las ACL, con ‘-x’ las borramos para un usuario concreto, y con ‘-b’ para todas las asignadas al fichero:

# setfacl -x u:foo prueba.tmp
# setfacl -b prueba.tmp

A la hora de asignar ACL para directorios, resulta interesante poder asignar unas ACL por defecto para todas aquellos subdirectorios que se vayan creando, así como los ficheros que contenga y se vayan metiendo. Vamos a asignar permiso total al usuario foo para el directorio prueba, es prácticamente igual que con ficheros pero añadiendo la ‘d’ de default:

# setfacl -m d:u:foo:rwx testdir

Nota: Sólo a los directorios se les puede añadir ACLs por defecto, si lo hacéis en ficheros:

# setfacl -m d:u:foo:rwx test
setfacl: /root/test: Only directories can have default ACLs

Si revisamos las ACL del directorio vemos asignados todos los default, podríamos también cambiarlo para el propietario, el grupo y ‘otros’ además de para los nuevos usuarios que añadamos vía ACL:

# getfacl testdir/
# file: testdir
# owner: root
# group: root
user::rwx
group::r-x
other::r-x
default:user::rwx
default:user:foo:rwx
default:group::r-x
default:mask::rwx
default:other::r-x

Espero que esta introducción a las ACL en GNU/Linux os haya sido de utilidad, es un mundo poco explorado pero lleno de posibilidades.