Software">
Nothing Special   »   [go: up one dir, main page]

01 Material de Lectura 101

Descargar como pdf o txt
Descargar como pdf o txt
Está en la página 1de 21

Capítulo 1: Arquitectura del sistema (Tema 101)

En este capítulo hablaremos sobre los componentes de una computadora personal


poniendo énfasis en el hardware y el software base o sistema operativo. Como parte de
este análisis aprenderemos cómo manipular los dispositivos conectados a nuestro
equipo. Finalizaremos repasando el proceso de arranque de un sistema Linux desde el
momento en que se presiona el botón de encendido hasta que disponemos de un
sistema totalmente funcional.

Conociendo el sistema
En Linux "todo es un archivo" reza el dicho. En otras palabras, cada componente del
sistema puede ser manipulado como si fuera un archivo común y corriente en el
sentido de que se puede leer y escribir en él. Como ejemplo podemos citar a los
comúnmente llamados pseudo sistemas de archivos. Lejos de tratarse de dispositivos
reales donde podemos almacenar información variada, en realidad consisten en una
especie de ventana que nos permite acceder (leer) a información del sistema de una
manera relativamente amigable.

El directorio /proc
Según el Filesystem Hierarchy Standard, el directorio /proc es el método adecuado
para obtener información sobre el sistema ya que en el mismo se encuentra montado
el pseudo sistema de archivos proc. Además, en este directorio también encontraremos
datos sobre los procesos que están corriendo actualmente.
Al ingresar a /proc lo primero que nos llama la atención es que hay varios directorios
cuyo nombre es un número (1, 10, 12, 13, 606, etc.). Dicho número es el identificador
de un cierto proceso y cada subdirectorio dentro del mismo contiene información
asociada a dicho proceso. Cuando un proceso finaliza su ejecución, o es terminado, su
directorio asociado dentro de /proc desaparece.
Supongamos que deseamos inspeccionar más en detalle el proceso cuyo identificador
es 541. Para ello nos posicionamos en el directorio /proc/541 donde encontraremos
los siguientes archivos de interés (entre otros):
• cmdline: contiene los argumentos de la línea de comandos que se utilizaron para
iniciar el proceso.

• cwd: es un enlace al directorio actual del proceso.

• exe: es un enlace al ejecutable del proceso.

• status: muestra información detallada sobre el estado del proceso.


Además, dentro de /proc encontramos dos archivos sumamente útiles que nos
brindan información sobre el uso de RAM y CPU llamados meminfo y cpuinfo,
respectivamente. En el primero las cantidades en realidad se expresan en kibibytes (1
KiB = 1024 B). Por razones de compatibilidad, se utiliza la nomenclatura kB debido a
que otros programas (como free, top, y ps) la requieren. De hecho, ese es uno de los
motivos por el que este archivo es tan importante, ya que es la fuente de datos para
otros programas.
¿Qué más podemos encontrar dentro de /proc? La siguiente lista nombra otros
archivos comunes junto con una breve descripción de estos (la cual puede ampliarse
en el man page de proc (man proc):
• dma nos muestra los canales de acceso directo a memoria (Direct Memory
Access) que se están utilizando.
• interrupts históricamente ha contenido el número de interrupciones por CPU y
por dispositivo de E/S, aunque a partir del kernel 2.6.24 también se incluyen
interrupciones internas (no asociadas con un dispositivo propiamente dicho).

• ioports es una lista de rangos de direcciones de E/S en uso.

• En uptime podremos ver dos números. El primero de ellos es el tiempo (en


segundos) que ha transcurrido desde el último inicio del sistema, mientras que el
segundo es la cantidad de tiempo que cada CPU ha estado inactivo.

Los tres primeros archivos resultan de particular importancia al tratar


con hardware un tanto antiguo. También son de interés para los
desarrolladores al permitirles verificar si el driver de un cierto
dispositivo se puede comunicar con los recursos de hardware que
necesita utilizar.

En resumen, proc (o procfs, como es también llamado) es un sistema de archivos


virtual que no contiene archivos reales sino información sobre la operación del
sistema. Puede considerarse como el centro de control del kernel.

El sistema de archivos sysfs


Si observamos la salida del comando mount desde la línea de comandos, veremos
varias líneas referidas a dispositivos especiales. El sistema de archivos sysfs es el
asociado a uno de ellos. En realidad, se trata de otro pseudo sistema de archivos
provisto por el kernel para que las aplicaciones puedan acceder a información sobre el
hardware y drivers.
En /sys (el punto de montaje de este sistema de archivos) encontramos información
variada sobre dispositivos. Entre esos datos podemos ver el estado de estos (en
funcionamiento o no), el fabricante y modelo, el tamaño (si corresponde) y el bus al
que están conectados. Veamos en la imagen siguiente el contenido típico de este
sistema de archivos:
tree -d -L 1 /sys

Los subdirectorios que vemos en la imagen anterior representan los sistemas


principales incluidos en sysfs. En estos directorios por lo general encontraremos
archivos de texto plano que contienen un solo valor. Por ejemplo, consideremos
/sys/bus. En el mismo se ubican una serie de subdirectorios que representan todos
los tipos de buses que están soportados en el kernel actual (ya sea compilados
estáticamente o mediante un módulo). Más particularmente, en
/sys/bus/usb/devices encontraremos información sobre los buses USB disponibles
en el equipo:
ls /sys/bus/usb/devices

En particular, dentro de /sys/bus/usb/devices/usb1 encontramos un subdirectorio


llamado power, y un archivo connected_duration. En el mismo se nos indica, en
milisegundos, el tiempo en que ha estado conectado el bus. Este dato debe coincidir
(aproximadamente) con el uptime del equipo.

Como podemos ver, sysfs provee datos que también están disponibles a través de
proc, aunque de una manera más estructurada.
Udev y el directorio /dev
Dentro de la estructura de directorios en Linux, los dispositivos presentes en el equipo
pueden observarse dentro del directorio /dev a partir de los datos presentes en /sys.
En esa ubicación encontraremos archivos que representan discos (incluyendo
particiones, grupos de volúmenes, y volúmenes lógicos), memoria, terminales, y otros.
En primer lugar, cuando se agrega o quita un dispositivo (o cambia su estado de
alguna forma) del sistema, el kernel lo informa al servicio systemd-udevd a fin de
prepararlo para su uso. Este último puede configurarse para responder a dichos
eventos mediante reglas en archivos con la extensión .rules dentro de los siguientes
directorios:
• /etc/udev/rules.d

• /run/udev/rules.d

• /usr/lib/udev/rules.d

Si existen archivos con nombres iguales, la prioridad más alta es dada a aquellos
dentro de /etc/udev/rules.d, seguida por /run/udev/rules.d, y luego por
/usr/lib/udev/rules.d. Como resultado, podemos identificar un dispositivo
basándonos en sus propiedades y sin importar el puerto de conexión o el orden en
que haya sido descubierto, podemos asignarle un nombre fijo.
Es importante mencionar que se dispone de udevadm, una herramienta para controlar
el funcionamiento de udev. Entre sus usos útiles, podemos destacar udevadm monitor
--kernel que muestra los eventos detectados por el kernel. Luego de ejecutar este
comando, tendremos que esperar a que se registre un cambio. A continuación,
podremos ver el detalle por la salida estándar. En la imagen siguiente observamos la
detección de un dispositivo USB conectado al equipo luego de ejecutar el comando:

Además del uso ilustrado en la imagen anterior, udevadm nos sirve para administrar la
lista de eventos en espera (udevadm settle y udevadm control) y nos permite
simular eventos (udevadm test) y debuguearlos.
Finalmente, para que una aplicación de escritorio envíe o reciba mensajes de otra
aplicación (o del kernel mismo) existe un mecanismo de comunicación llamado D-
Bus. Por ejemplo, cuando insertamos un dispositivo de almacenamiento extraíble,
udev envía un mensaje a través de D-Bus al gestor de ventanas para que muestre una
notificación por pantalla o provea un ícono de acceso directo al dispositivo.

Comandos útiles
Además de los ejemplos que mencionamos anteriormente, existen numerosas
herramientas que nos permiten examinar la operación del kernel y el estado de los
dispositivos conectados a nuestro equipo. A continuación, veremos un listado de las
más conocidas.

Ver módulos del kernel


Para mostrar información sobre el kernel que estamos utilizando actualmente,
usaremos el comando uname con las opciones -s (nombre), -r (release), y -v
(versión), pudiendo utilizarlas todas juntas como -srv o por separado. También
disponemos de la opción -a que devuelve los datos anteriores junto con el tipo de
procesador, la plataforma, y el sistema operativo.
La lista de los módulos del kernel en uso puede verse utilizando el comando lsmod.
Como la lista puede llegar a ser muy larga, es conveniente utilizar less para paginar el
resultado o grep para buscar uno en particular. Si hay alguno de la lista que capte
nuestra atención, podemos obtener más información sobre el mismo usando modinfo
seguido del nombre del módulo. A continuación, podemos apreciar el resultado de los
comandos
lsmod | grep 8139
modinfo 8139cp

En la imagen anterior aprendemos que el módulo 8139cp es el controlador de la placa


de red correspondientes a la serie RealTek RTL-8139C. El archivo que representa el
módulo reside en /lib/modules/4.9.0-4-686-
pae/kernel/drivers/net/ethernet/realtek/ con el nombre 8139cp.ko.
Si en algún momento necesitamos utilizar un módulo que no está cargado en el kernel,
podemos recurrir a dos herramientas llamadas insmod y modprobe para poner dicho
módulo en funcionamiento. ¿Cuál es la diferencia entre ambas herramientas? Mientras
modprobe es lo suficientemente inteligente para resolver dependencias, insmod no lo
es. Esto significa que modprobe puede cargar automáticamente otros módulos que
sean necesarios antes de hacer lo propio con el que le indicamos explícitamente.
Por ejemplo, para cargar el módulo ac97_bus:
modprobe --verbose ac97_bus

Para removerlo:
modprobe -r ac97_bus

Tengamos en cuenta que modprobe nos permite insertar o remover módulos, pero
dichos cambios no son permanentes; es decir que se pierden al reiniciar el equipo.
Para lograr que un módulo en particular se cargue al inicio del sistema, debemos
agregar el nombre del módulo en el archivo /etc/modules-load.d/modules.conf.
También es posible crear archivos separados con la extensión .conf dentro del mismo
directorio.
Por ejemplo, para cargar el módulo virtio-net.ko podríamos crear el archivo
/etc/modules-load.d/virtio-net.conf con el siguiente contenido (las líneas que
comienzan con # se consideran comentarios y son ignoradas):
# Load virtio-net.ko at boot
virtio-net

En el man page de modules-load.d podemos encontrar más información al respecto.

CPUs y dispositivos PCI, SCSI o SATA


Para acceder a información sobre el CPU (uno o más, si los hubiera) podemos emplear
el comando lscpu. Entre los datos que esta herramienta pone a nuestro alcance se
encuentran la configuración y las características que distinguen al procesador. En la
lista que se muestra en la imagen siguiente observamos la arquitectura
(Architecture), el modo de operación (CPU op-mode(s)), la marca (Vendor ID), el
modelo (Model name), y la velocidad (CPU MHz), por nombrar los más
representativos:
Los dispositivos PCI, SCSI, o SATA pueden ser inspeccionados mediante los comandos
lspci y lsscsi. Este último nos muestra SCSI y SATA por igual. Ambas utilidades
aceptan el uso de la opción -v para aumentar la verbosidad de la salida, traduciéndose
en mayor cantidad de detalles sobre los dispositivos. Veamos un ejemplo de cada
comando:
lsscsi
lsscsi -v

lspci
lspci -v
Además de estas herramientas, también podemos utilizar lsblk para ver todos los
dispositivos de bloques en forma de árbol. De esta manera tenemos la posibilidad de
ver las particiones de cada disco y los volúmenes lógicos, por nombrar dos ejemplos:

En la imagen de arriba podemos ver que sda posee 3 particiones (sda1, sda2, y sda5).
En una de ellas (sda5) reside el grupo de volúmenes llamado debianhome-vg y
dentro del mismo encontramos los volúmenes lógicos root, var, swap_1, tmp, y
home.
Dispositivos USB
En el archivo /var/lib/usbutils/usb.ids podemos encontrar una lista de dispositivos
USB por fabricante. El comando lsusb utiliza la información disponible en dicho
archivo para identificar la lista de dispositivos USB y sus buses de conexión presentes
en nuestro equipo. Estos datos pueden ser actualizados descargando la última versión
desde http://www.linux-usb.org/usb.ids.
En la imagen siguiente vemos la salida típica de este comando:

Tomemos como ejemplo el primer dispositivo de la lista de arriba (Hewlett-Packard


v165w Stick) para analizar los datos que se nos presentan:
• Bus 001 es el número del bus al que está conectado el dispositivo.

• Device 007 es el número de dispositivo conectado al Bus 001.


• ID 03f0:5307 es el id del dispositivo, donde 03f0 representa la identificación del
fabricante y 5307 la correspondiente al dispositivo propiamente dicho. Podemos
verificar esta información con grep -Ei '(03f0|5307)'
/var/lib/usbutils/usb.ids.

• Hewlett-Packard v165w Stick es el nombre del fabricante y del dispositivo.

Para mostrar más detalles podemos utilizar las opciones -v o -vv, tal como en otros
comandos mencionados anteriormente.

La secuencia de arranque
Al encender el equipo, el BIOS (Basic Input-Output System) o UEFI (Unified
Extensible Firmware Interface) llevan a cabo una revisión del hardware conocida
comúnmente como POST (Power-On Self Test). A continuación, se busca un gestor de
arranque (por lo general, GRUB) en el MBR (Master Boot Record) o en la partición
EFI de un dispositivo de almacenamiento.
A partir de ese momento, el control del proceso se pasa a manos de GRUB, que se
encargará de cargar el kernel, el cual reconocerá y configurará los dispositivos de
hardware presentes en el equipo y los preparará para su uso. Como próximo paso, el
núcleo también será responsable por ejecutar el primer proceso, también conocido
como init. Finalmente, este último utilizará el gestor del sistema (systemd o Upstart)
o los scripts de SysVinit para continuar el inicio de los demás servicios. El proceso de
arranque culmina al presentar una interfaz de inicio de sesión de modo texto o gráfico,
según sea el caso.

Los servicios o procesos son programas que corren en segundo plano


(de manera no interactiva). Otro nombre por el que son conocidos es
daemons (a veces traducido como demonios en castellano).

Ahora hagamos un repaso por los 3 métodos de gestión del sistema más utilizados a lo
largo del tiempo.

SysVinit
Hasta no hace mucho tiempo, la mayoría de las distribuciones más utilizadas
utilizaban como base de su funcionamiento el sistema de arranque y de
administración de servicios conocido como SystemV o SysVinit. Este sistema,
heredado de Unix, contempla 5 niveles útiles de funcionamiento (de ahí el nombre
SystemV, correspondiente al número 5 en el sistema romano) numerados del 1 al 5. A
estos se les suma el nivel 0 (apagado del equipo) y el 6 (reinicio del sistema). Cada uno
de ellos es lo que se conoce como niveles de corrida o runlevels en Linux.
Cada runlevel se encuentra asociado a un cierto número de servicios que por defecto
deben iniciarse automáticamente cuando encendemos el equipo, y que deben
detenerse al reiniciarlo o apagarlo. Por ejemplo, en el directorio /etc en un sistema
Debian Wheezy podemos encontrar 7 directorios con nombre rcN.d, donde N es un
número del 0 al 6. Es precisamente dentro de estos directorios que se encuentran una
serie de enlaces simbólicos a los ejecutables que inician y detienen los servicios del
sistema en cada runlevel respectivo, como vemos a continuación:

Por el momento, podemos asociar el concepto de enlaces simbólicos


(también llamados soft links) con el de acceso directo, con el que
quizás estemos más familiarizados. En síntesis, se trata de una
representación de un recurso del sistema que apunta a dicho recurso
pero que es independiente del mismo.

La S utilizada como prefijo en los nombres de los enlaces simbólicos


indica que, en este nivel de corrida en particular, se debe iniciar el
servicio asociado. Por otro lado, la letra K indica lo contrario (el
servicio debe apagarse o permanecer detenido al ingresar al runlevel
en cuestión).

Es importante tener en claro que lo primero que hace init es leer el archivo
/etc/inittab para identificar los próximos pasos a seguir. Por brevedad, nos
referiremos solamente a la detección del runlevel por defecto, lo que se indica en la
siguiente línea (2 en este ejemplo):
# The default runlevel.
id:2:initdefault:

A continuación, init se dirige a /etc/rc2.d en este caso. En este directorio podemos


apreciar una serie de enlaces simbólicos cuyos nombres comienzan con la letra S, tal
como mencionamos antes, y un número de dos dígitos. Cada uno de ellos apunta a un
servicio que se debe levantar en el runlevel 2 por orden numérico y alfabético). Por
ejemplo, de la imagen anterior podemos sacar la conclusión de que S01motd recibirá
atención en primer lugar, seguido por S13rpcbind, y así sucesivamente. Si hay dos o
más que compartan el mismo prefijo SXX, el orden de inicio se decide por orden
alfabético. De esta manera, S16rsyslog será llamado primero que S16virtualbox-
guest-utils (este último no se muestra en la imagen).
Para cambiar de runlevel temporariamente podemos invocar el comando telinit
seguido del nombre del nivel de corrida deseado. Por ejemplo, para cambiar al
runlevel 5:
telinit 5

El comando anterior hará que init se dirija al nivel de corrida 5 siguiendo el mismo
proceso que explicamos antes.

Por supuesto, si nos interesa cambiar el nivel de corrida de manera


permanente podemos editar el archivo /etc/inittab colocando el
número correspondiente como indicamos más arriba.
Con el correr del tiempo, las siguientes limitaciones se hicieron notorias en este
esquema:
• El proceso de inicio de servicios es estrictamente síncrono (se espera a que un
servicio esté corriendo antes de iniciar el próximo). Esto impacta en el tiempo
total de inicio del sistema.

• Necesidad de chequear dependencias antes de iniciar un servicio. Por ejemplo, que


el servicio de red esté disponible antes de iniciar un servidor web.

• Cualquier evento posterior al inicio del equipo necesita intervención manual del
usuario (identificación y montaje de dispositivos extraíbles, por nombrar dos
ejemplos).

Fueron precisamente estas desventajas que condujeron al desarrollo de otros


sistemas de arranque y administración de servicios como Upstart primero y systemd
después.

Upstart
Entre SysVinit y la adopción final de systemd por la mayoría de las distribuciones
principales GNU/Linux, surgió una alternativa conocida como Upstart. Fue
desarrollada por Canonical (la empresa detrás de Ubuntu) e integrada por primera
vez con Ubuntu 6.10 Edgy a fines de 2006. Posteriormente, Fedora la adoptó y utilizó
hasta la versión 14 inclusive. Hoy en día podemos encontrarla en RHEL 6.7 y
similares, los cuales gozan de soporte hasta fines de 2018.
Upstart se pensó como un reemplazo basado en eventos para SysVinit. Como tal,
supervisa tareas mientras el sistema está funcionando y responde a eventos tales
como la conexión o desconexión de dispositivos extraíbles. Además, también gestiona
los servicios durante el inicio y el apagado. Es importante notar que es 100%
compatible con los scripts clásicos de SysVinit. De esta manera, aquellos servicios que
provean un script para init pueden funcionar sin problemas bajo Upstart.
Por otro lado, Upstart también trabaja con archivos .conf dentro del directorio
/etc/init. En los mismos se define el funcionamiento de servicios, y tienen la siguiente
estructura: - Descripción del proceso
• Niveles de corrida en los cuales el proceso debe ejecutarse o eventos que deben
iniciarlo.

• Niveles de corrida en los cuales el proceso no debe correr o eventos que deben
detenerlo.

• Opciones

• Comando que se debe utilizar para lanzar el proceso


Consideremos el archivo de ejemplo backup.conf que mostramos a continuación. Los
comentarios presentes en el mismo (en líneas que comienzan con #) nos sirven como
guía para entender el funcionamiento del servicio que utiliza este archivo de
configuración):
# Servicio de prueba para Upstart
# Stanzas
# Stanzas define when and how a process is started and stopped
# See a list of stanzas here: http://upstart.ubuntu.com/wiki/Stanzas#resp
awn

# Runlevels para iniciar el servicio


start on runlevel [2345]
# Cuando detenerlo
stop on runlevel [016]
# Reiniciarlo en caso de falla
respawn
# Especificar directorio de trabajo
chdir /home/alumno/misarchivos
# Indicar el comando, junto con cualquier argumento necesario (opcional)
exec bash backup.sh arg1 arg2

A pesar de la aceptación que este sistema tuvo entre la comunidad en su momento,


con el tiempo cedió lugar al más robusto systemd. Incluso Canonical decidió
adoptarlo para Ubuntu luego de que el proyecto Debian hiciera lo mismo a partir de la
versión 8 (Debian Jessie).

Systemd
Es importante aclarar que systemd no surgió como un reemplazo de SysVinit porque
este último fuera defectuoso o porque hubiera usuarios y administradores que
estuvieran descontentos con el mismo. Más bien, comenzó como un proyecto para
desarrollar un sistema que fuera más eficiente al 1) iniciar menos servicios durante el
arranque (solamente aquellos que fueran estrictamente necesarios de acuerdo al uso
esperado y al hardware disponible), y 2) hacerlo en paralelo, en vez de manera
secuencial. En otras palabras, se buscó un sistema de inicio y de administración de
servicios que pudiera reaccionar dinámicamente ante cambios en el software y en el
hardware.

Si lo pensamos bien, esta es una característica distintiva de los sistemas


de cómputo actuales. Por ejemplo, no hay necesidad de mantener el
servicio de impresión corriendo si no hay ninguna impresora conectada
al equipo o disponible a través de la red. Por otra parte, queremos que
se inicie de manera transparente si esa condición cambia.
A pesar de las bondades mencionadas en el párrafo anterior, muchas personas se
opusieron tenazmente a la adopción de systemd por parte de sus distribuciones
favoritas. Sin embargo, las reservas de la comunidad eventualmente cedieron,
resultando en la adopción de systemd en Fedora -lo cual derivó en Red Hat Enterprise
Linux 7 y eventualmente en CentOS 7-, ArchLinux, Debian, Ubuntu, y derivados de
estos últimos.

Targets en systemd
Bajo systemd, el concepto de runlevel o nivel de corrida solamente se mantiene por
compatibilidad con SysVinit. El componente básico de systemd se denomina unidad
(unit). Existen varias categorías de unidades: las más conocidas se denominan
servicios (services) y objetivos (targets). Las primeras son las que ejecutan los
daemons y sus dependencias en el orden apropiado. Por otro lado, las segundas se
utilizan para agrupar varias unidades. Estas últimas pueden compararse en cierta
forma a los clásicos runlevels.
Dentro de /lib/systemd/system podemos encontrar las definiciones de las distintas
unidades. Para empezar, cabe aclarar que los archivos de configuración de los targets
llevan el sufijo .target. Por ejemplo, podemos encontrar basic.target y multi-
user.target. Este último es el objetivo donde se encuentran agrupados la mayoría de
los daemons. Para funcionar correctamente, se necesita que basic.target esté
activado. Dicho de otra forma, antes de entrar en multi-user.target, todos los
servicios agrupados en basic.target deben haberse iniciado. A su vez, basic.target
requiere sysinit.target.

El objetivo basic.target en esencia cubre todo lo relacionado con el


inicio del sistema. Luego, podemos decir lo siguiente en general: Si en
A.target se indica Requires=B.target, hablamos que el objetivo B es
una dependencia del A.

Además, en systemd hablamos de objetivo por defecto para describir el estado que
alcanza el sistema al finalizar el proceso de arranque. Para ver cuál es el objetivo por
defecto en nuestro sistema, podemos utilizar el comando
systemctl get-default

¿De dónde proviene este dato? Se trata de un enlace simbólico llamado default.target
dentro de /lib/systemd/system que apunta a la definición del target indicado. Por
ejemplo, en la imagen siguiente podemos ver que
/lib/systemd/system/default.target es un soft link hacia
/lib/systemd/system/graphical.target:
Por supuesto, es posible cambiar el target por defecto si es necesario. Por ejemplo,
para cambiar el objetivo por defecto a graphical.target (entrará en efecto con el
próximo reinicio), debemos recurrir a:
systemctl set-default graphical.target

Además, para controlar el inicio y los servicios del sistema, en distribuciones que
utilizan systemd se dispone de una herramienta llamada systemctl.

En systemd se utiliza el término unit para referirse no solamente a


servicios, sino también a puntos de montaje, sockets, e incluso
dispositivos.

A continuación, presentamos las opciones más utilizadas de systemctl. En todas ellas


hacemos referencia a un servicio ficticio llamado miservicio:
• Iniciar el servicio: systemctl start miservicio.service

• Configurarlo para que inicie al arrancar el equipo: systemctl enable


miservicio.service

• Detenerlo: systemctl stop miservicio.service

• Impedir que inicie al arrancar el equipo: systemctl disable


miservicio.service

• Reiniciar el servicio: systemctl restart miservicio.service

• Averiguar si está configurado para arrancar al inicio: systemctl is-enabled


miservicio.service
• Averiguar si está corriendo actualmente: systemctl is-active
miservicio.service o systemctl -l status miservicio.service (esta última
variante provee más información sobre el estado y la operación del servicio).

En los ejemplos anteriores, podemos omitir el .service si estamos seguros que no


hay otra unit de distinto tipo con el nombre miservicio.
Cuando es necesario realizar tareas de mantenimiento o de emergencia será necesario
que nos cambiemos al modo monousuario. Para llevar a cabo esta acción haremos uso
de
systemctl rescue

o
systemctl emergency

La diferencia entre rescue y emergency consiste en que la última es mucho más


reducida. La primera provee servicios básicos y monta sistemas de archivos, mientras
que la segunda no.

Logs de inicio
A fin de investigar inconvenientes cuando se produzcan, a menudo recurriremos a los
registros de operación (también llamados logs) del sistema. Mediante el comando
dmesg (diagnostic msg) podemos acceder a los mensajes emitidos por el kernel a lo
largo de la secuencia de arranque hasta el momento actual.
Por motivo de que cuando ejecutamos dmesg sin opciones se muestran todos los
mensajes, por lo general resulta útil aplicar un paginador como less, un filtro como
head o tail (para ver los primeros o los últimos registros), o utilizar grep para
identificar los resultados que cumplen con un patrón. Con respecto a esta última
alternativa, en el ejemplo que aparece a continuación veríamos solamente los
mensajes relativos a los dispositivos USB:
dmesg | less
dmesg | grep -i usb

Otra forma de refinar la información que podemos extraer de dmesg consiste en


especificar el origen (o facilidad, tal cual se llama en la documentación de la
herramienta) y el nivel del mensaje.
Entre los orígenes disponibles se encuentran los siguientes:
• kern: mensajes del kernel

• user: mensajes de nivel de usuario

• mail: sistema de correo


• daemon: daemons del sistema

• auth: mensajes de autenticación/seguridad

• syslog: mensajes generados internamente por syslogd

• lpr: subsistema de impresión

• news: subsistema de red


Y en cuanto a los niveles:
• emerg: emergencia (el sistema está inutilizable)

• alert: alerta (se requiere una acción de inmediato)

• crit: condición crítica

• err: condiciones de error

• warn: condiciones de advertencia

• notice: condición normal pero significativa

• info: de carácter informativo

• debug: mensajes de nivel de debug

Por ejemplo, con


dmesg --level=err,warn

mostraremos únicamente los mensajes de error o advertencia provenientes de


cualquier origen. También podemos agregar la opción --facility=kern para filtrar
los resultados todavía más:
dmesg --level=err,warn --facility=kern

Además de dmesg, systemd provee una utilidad llamada journalctl para acceder al
registro de eventos de arranque (y de otras clases también). Con journalctl --boot
podemos acceder a los datos correspondientes a un booteo en particular. La lista de
inicios para los que se dispone de información puede verse reemplazando --boot con
--list-boots. En la imagen siguiente podemos apreciar el resultado, donde -0 se
utiliza para indicar el booteo indicado como 0. En este caso se trata del inicio actual:
journalctl --list-boots
journalctl --boot -0 | head -n 5
journalctl --boot -0 | tail -n 5
Además, journalctl admite opciones que nos permiten ver datos de unidades
específicas. Por ejemplo, con la opción --unit=UNIT podemos visualizar datos de la
unidad representada por UNIT. Es decir, el comando
journalctl --unit=cron --boot

nos devolverá la lista de registros relacionados con cron durante el inicio del sistema.
Por otro lado, si nos interesa mostrar los eventos de una prioridad dada únicamente,
tenemos a nuestra disposición la opción --priority. Al indicar un nivel de prioridad
veremos los mensajes correspondientes al mismo y a todos los menores. Por ejemplo,
journalctl --boot --priority=4

nos mostrará los mensajes de nivel 4 (warning) hasta 0 (emerg), si los hubiere.

Si deseamos que el sistema responda a eventos ACPI (Advanced


Configuration and Power Interface) como el presionar el botón de
suspender, y cerrar la tapa o desconectar el cargador de una laptop
podemos recurrir a acpid. Este daemon queda a la escucha de eventos
y ejecuta programas cuando ocurren. El administrador puede
configurar qué es lo que debe suceder ante cada evento mediante los
archivos de configuración ubicados en /etc/acpi/events.

El proceso de inicio de sesión


Cuando ingresamos un usuario y su correspondiente contraseña para iniciar sesión en
el sistema, esta información se compara con la disponible en los archivos
/etc/passwd y /etc/shadow. En el primero de ellos encontramos información de
cada cuenta de usuario y en el segundo las contraseñas hasheadas de las cuentas que
tienen permitido el inicio de sesión. Por lo general, en distribuciones modernas las
contraseñas se protegen utilizando el algoritmo SHA-512. Este método dificulta
muchísimo el adivinar una contraseña a partir de la cadena de texto que la representa.
Si la contraseña que ingresamos ha sido aceptada por el sistema nos aparece el
contenido del archivo /etc/motd que suele estar vacío pero que le sirve al
administrador para dejar mensajes dirigidos a los usuarios con información
pertinente. Por ejemplo:
Hoy a las 20:00 horas se efectuará un backup. Les agradezco dejar todas las aplicaciones
cerradas.
A continuación, el sistema operativo nos devuelve el prompt, o la línea de comandos
preparada para recibir nuestras órdenes. En el caso de Debian el prompt inicial está
compuesto por dos partes:
• El nombre del usuario actual, seguido del símbolo **@**.

• El nombre del equipo.


• El directorio inicial de trabajo, más conocido como el home o el directorio
personal del usuario en cuestión. El símbolo ~ se utiliza para representar este
directorio.
• Si estamos logueados como root, veremos el símbolo # a continuación. De otra
manera (usuario común), se mostrará el signo $.
Además de su directorio personal, cada usuario tiene asignado un shell o intérprete de
comandos. Se trata de un programa que recibe los comandos que escribimos y que los
envía al sistema operativo para ser ejecutados.
El intérprete utilizado en la mayoría de las distribuciones actuales (de las cuales
Debian no es la excepción) se llama Bash (Bourne-Again SHell). Bash tiene la
posibilidad de ejecutar comandos en tiempo real pero además tiene un poderoso
lenguaje de programación de scripts. Permite generar programas con funciones,
control de flujo, creación de archivos, seguimiento de procesos, entre otros.

Apagado y reinicio del sistema


Aunque en teoría Linux puede funcionar durante semanas, meses, e incluso años sin
necesidad aparente de reiniciar o o apagar el equipo, pueden surgir situaciones en las
que es necesario hacerlo. Esto puede deberse a la necesidad de reemplazar un
dispositivo de hardware interno, al mantenimiento eléctrico de la red desde donde
recibe energía el equipo, o a un simulacro para verificar que el mismo puede
reaccionar correctamente ante un evento inesperado.
Ante tales casos, es preciso conocer las opciones de las que disponemos a fin de
proceder correctamente y con cautela. Dentro de lo posible, debemos evitar a toda
costa el apagar cualquier equipo (no solamente aquellos que corren Linux) a la fuerza
o desconectándolos repentinamente del suministro de energía eléctrica. Para casos
críticos (servidores principalmente), los equipos deben estar conectados a una UPSs o
a un generador independiente en paralelo.
Para apagar el equipo disponemos de las siguientes alternativas (la primera se incluye
por compatibilidad hacia atrás con el runlevel 0):
init 0
poweroff
halt
shutdown -h [CUANDO] [MENSAJE OPCIONAL]

Las alternativas para reiniciarlo son similares (la primera se incluye por
compatibilidad hacia atrás con el runlevel 6):
init 6
reboot
shutdown -r [CUANDO] [MENSAJE OPCIONAL]

Bajo SysVinit, la utilización de shutdown traía aparejada la ventaja de que los procesos
que estuvieran corriendo se detenían correctamente, y los sistemas de archivos se
desmontaban prolijamente, a diferencia de las otras opciones que provocaban un
apagado abrupto del equipo. Por otra parte, bajo systemd todos los comandos
anteriores son sinónimos, y constituyen enlaces simbólicos al propio sistema de inicio
o a systemctl.
De todas maneras, tanto en el caso de apagar como para reiniciar el equipo, la ventaja
de usar shutdown consiste en poder indicar el momento en el que se realizará la acción
deseada (now para ahora, o una hora específica en el formato de 24 hs HH:MM) y
enviar un mensaje (opcional) para alertar a los usuarios que estén conectados al
sistema.
Por ejemplo, el siguiente comando
shutdown -r 14:00 'El sistema se reiniciará a las 14 hs'

enviará el mensaje entre comillas a los usuarios que estén conectados y agendará el
reinicio del sistema para las 14:00 hs.
Si existe un apagado pendiente y deseamos cancelarlo, podemos utilizar la opción -c
para tal fin:
shutdown -c 'El apagado ha sido cancelado. Puede continuar trabajando nor
malmente.'
Cuando hay un apagado o reinicio agendado o en curso no es posible iniciar nuevas
sesiones de usuario. Si es cancelado, se levantará esa restricción.

Enviar mensajes a terminales


Además de shutdown (al reiniciar o apagar un equipo), hay otra herramienta llamada
wall que nos permite enviar mensajes a las terminales durante el funcionamiento
normal del sistema. Esto puede sernos útil para alertar sobre cambios inminentes a
los usuarios conectados.
En primer lugar, para poder enviar mensajes a una terminal dada es necesario que la
misma admita operaciones de escritura. Aunque suele ser el valor por defecto,
podemos chequear este dato utilizando el comando mesg. Si el mismo devuelve is y,
significa que la terminal aceptará mensajes. De otra forma, si la salida es is n, significa
que no podremos enviar mensajes a dicha terminal. Para cambiar este valor, podemos
utilizar mesg y o mesg n para habilitar o deshabilitar la escritura, respectivamente.
A continuación, ilustramos el uso de wall y mesg utilizando dos terminales. En una de
ellas ejecutaremos este último comando para verificar que dicha terminal pueda
recibir mensajes. Desde la otra terminal enviaremos el mensaje Hola a todos. Vamos a
proceder a hacer cambios en la configuración de Apache.:

Es importante aclarar que usuarios con privilegios limitados también pueden escribir
a las terminales de otros usuarios siempre y cuando estas últimas lo acepten. Sin
embargo, no podrán evitar el banner con la opción -n, cosa que solamente el
superusuario puede hacer.

También podría gustarte