Ghost AcademyGhostLinux · Ghost Academy
GhostLinuxMódulo 107Examen 102-500

Tareas administrativas

LPI 107.1 Usuarios y gruposLPI 107.2 Automatización (cron/at)LPI 107.3 Localización e internacionalización

Este módulo es el corazón del trabajo diario de un administrador de sistemas: quién puede entrar al sistema, qué puede hacer una vez dentro, y qué tareas se ejecutan solas sin que nadie tenga que acordarse de lanzarlas a mano.

Objetivos de la unidad

1. LPI 107.1 — Gestionar usuarios y grupos

1.1 Crear, modificar y borrar usuarios

ComandoQué hace
useradd usuarioCrea un usuario — sin -m no crea directorio personal, al contrario de lo que la mayoría espera
useradd -m -s /bin/bash -c "Jose Perez" joseCrea usuario con directorio personal (-m, copiando /etc/skel), shell de login (-s) y comentario/nombre completo (-c)
usermod -aG grupo usuarioAñade el usuario a un grupo adicional — el -a (append) es crítico: sin él, -G reemplaza todos los grupos secundarios del usuario
usermod -L usuario / -UBloquea / desbloquea la cuenta (antepone/quita un ! al hash en /etc/shadow)
usermod -s /usr/sbin/nologin usuarioImpide el login interactivo sin borrar la cuenta — típico en cuentas de servicio
userdel usuarioBorra el usuario, conserva su directorio personal
userdel -r usuarioBorra el usuario y su directorio personal y su buzón de correo
root@lpic1:~#
$ useradd -m -s /bin/bash -c "Jose Perez" jose
root@lpic1:~#
$ usermod -aG sudo,docker jose
root@lpic1:~#
$ id jose
uid=1001(jose) gid=1001(jose) groups=1001(jose),27(sudo),998(docker)
El error de usermod -G sin -a es de los favoritos del examen: usermod -G docker jose (sin -a) elimina a jose de sudo si no lo incluyes también en la lista — porque -G solo sin modificador reemplaza la lista completa de grupos secundarios, no la amplía.

1.2 Grupos

ComandoQué hace
groupadd nombreCrea un grupo nuevo
groupmod -n nuevo_nombre viejo_nombreRenombra un grupo
groupdel nombreBorra un grupo (falla si es el grupo primario de algún usuario)
groups usuarioLista los grupos a los que pertenece

1.3 /etc/passwd, campo a campo

root@lpic1:~#
$ grep jose /etc/passwd
jose:x:1001:1001:Jose Perez:/home/jose:/bin/bash
#CampoValor del ejemplo
1Nombre de usuariojose
2Contraseñax — indica que el hash real vive en /etc/shadow, no aquí
3UID1001
4GID primario1001
5GECOS (nombre completo/comentario)Jose Perez
6Directorio personal/home/jose
7Shell de login/bin/bash
/etc/passwd tiene que seguir siendo legible por todos los usuarios (muchísimos comandos lo consultan para traducir UID a nombre), así que el hash de la contraseña se trasladó hace décadas a /etc/shadow, que no es legible por usuarios normales — por eso en el módulo 104 viste que ni siquiera tu propio usuario puede leer directamente ese fichero.

1.4 /etc/shadow, campo a campo

root@lpic1:~#
$ sudo grep jose /etc/shadow
jose:$6$abcd1234$hashmuylargo...:19987:0:90:7:30::
#CampoValor del ejemploSignificado
1Usuariojose—
2Hash de la contraseña$6$...$6$ = SHA-512; ! o !! = cuenta bloqueada; vacío = sin contraseña
3Último cambio19987Días desde el 1 de enero de 1970 (época Unix) del último cambio de contraseña
4Días mínimos0Días que deben pasar antes de poder cambiarla de nuevo
5Días máximos90Días que puede seguir siendo válida antes de forzar un cambio
6Días de aviso7Días antes de caducar en los que se avisa al usuario al entrar
7Días de inactividad30Días de margen tras caducar antes de bloquear la cuenta definitivamente
8Fecha de expiración(vacío)Fecha absoluta (en días desde 1970) en la que la cuenta deja de existir, independientemente de la contraseña
9Reservado(vacío)Sin uso actualmente

1.5 Envejecimiento de contraseñas: chage

root@lpic1:~#
$ chage -l jose
Last password change					: sep 15, 2026
Password expires					: dic 14, 2026
Password inactive					: ene 13, 2027
Account expires						: never
Minimum number of days between password change	: 0
Maximum number of days between password change		: 90
Number of days of warning before password expires	: 7
root@lpic1:~#
$ chage -M 60 -W 14 jose
root@lpic1:~#
$ chage -E 2027-01-01 jose
# fuerza que la cuenta expire en esa fecha exacta
Todo lo que hace chage se puede leer y editar también directamente en los campos 3-8 de /etc/shadow — chage es simplemente la forma segura y legible de hacerlo, sin arriesgarte a estropear el formato del fichero a mano.

1.6 /etc/group y comandos de identidad

root@lpic1:~#
$ grep sudo /etc/group
sudo:x:27:jose,maria

Cuatro campos: nombre del grupo, x (igual que en passwd, placeholder), GID, y la lista de usuarios miembros secundarios separados por comas — los usuarios cuyo grupo primario es este no aparecen aquí, ya están vinculados por el campo 4 de /etc/passwd.

root@lpic1:~#
$ whoami
jose
root@lpic1:~#
$ id
uid=1001(jose) gid=1001(jose) groups=1001(jose),27(sudo)

1.7 Valores por defecto: /etc/login.defs y /etc/default/useradd

root@lpic1:~#
$ grep -E '^UID_MIN|^UID_MAX|^PASS_MAX_DAYS' /etc/login.defs
UID_MIN			 1000
UID_MAX			60000
PASS_MAX_DAYS	90

/etc/login.defs fija los valores por defecto que usan useradd/chage cuando no se les da un valor explícito: a partir de qué UID empiezan los usuarios normales (por debajo quedan reservados para cuentas de sistema), y la caducidad de contraseña por defecto, entre otros.

🧰 Recursos relacionados (Ghost Academy)

Practica más — labs ya publicados en Ghost Academy sobre este tema: 👥 Usuarios & grupos (lab) · 🔑 Usuarios & permisos (lab)

2. LPI 107.2 — Automatizar tareas con cron y at

2.1 cron: tareas recurrentes

root@lpic1:~#
$ crontab -e
# abre el editor configurado (ver $EDITOR / update-alternatives) con el crontab del usuario actual
root@lpic1:~#
$ crontab -l
# backup diario a las 2:30 de la madrugada
30 2 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1
root@lpic1:~#
$ crontab -r
# BORRA el crontab completo del usuario actual, sin confirmar - cuidado

Cinco campos de tiempo, en este orden, antes del comando:

CampoRango
Minuto0-59
Hora0-23
Día del mes1-31
Mes1-12
Día de la semana0-7 (0 y 7 son ambos domingo)

Un * significa "cualquier valor". Se combinan con , (lista), - (rango) y / (paso):

root@lpic1:~#
$ cat miscrontab.txt
0 */4 * * * /scripts/sincroniza.sh
15,45 9-17 * * 1-5 /scripts/recordatorio.sh
0 0 1 * * /scripts/informe_mensual.sh
LíneaSe ejecuta
0 */4 * * *Cada 4 horas en punto (0:00, 4:00, 8:00...)
15,45 9-17 * * 1-5A los minutos 15 y 45 de cada hora, entre las 9 y las 17, de lunes a viernes
0 0 1 * *El día 1 de cada mes, a medianoche
Cadenas especiales que ahorran escribir los cinco campos: @reboot (al arrancar el sistema), @daily (equivalente a 0 0 * * *), @hourly, @weekly, @monthly, @yearly. El examen las pregunta tanto en su forma literal como pidiendo la expresión de cinco campos equivalente.

2.2 /etc/crontab y /etc/cron.d/: la diferencia con crontab -e

root@lpic1:~#
$ cat /etc/crontab
# m h dom mon dow user	command
17 *	* * *	root	run-parts /etc/cron.hourly
25 6	* * *	root	run-parts /etc/cron.daily
47 6	* * 7	root	run-parts /etc/cron.weekly
El crontab de un usuario (crontab -e, guardado en /var/spool/cron/crontabs/) tiene 5 campos de tiempo + comando. /etc/crontab y los ficheros en /etc/cron.d/ tienen un sexto campo extra — el usuario con el que se ejecuta la tarea — precisamente porque root puede definir ahí tareas para cualquier usuario, no solo las suyas.

Las carpetas /etc/cron.hourly/, /etc/cron.daily/, /etc/cron.weekly/ y /etc/cron.monthly/ contienen scripts completos (no líneas de crontab) que run-parts ejecuta todos, uno a uno, en el momento indicado — la forma habitual de que un paquete instalado añada su propia tarea periódica sin tocar ningún crontab existente.

root@lpic1:~#
$ cat /etc/cron.allow 2>/dev/null; cat /etc/cron.deny 2>/dev/null
jose

Si existe /etc/cron.allow, solo los usuarios listados ahí pueden usar crontab. Si no existe pero sí existe /etc/cron.deny, pueden todos salvo los listados. Si no existe ninguno de los dos, el comportamiento por defecto depende de la distro (en Debian/Ubuntu, todos pueden).

2.3 at: una única ejecución puntual

root@lpic1:~#
$ at 23:00
at> /usr/local/bin/apagar_servicios.sh
at> <EOT>
job 7 at Wed Sep 30 23:00:00 2026
root@lpic1:~#
$ at now + 2 hours
# acepta expresiones relativas: minutes, hours, days, weeks
root@lpic1:~#
$ atq
7	Wed Sep 30 23:00:00 2026 a jose
root@lpic1:~#
$ atrm 7
# cancela el trabajo numero 7 antes de que se ejecute
cronat
Para quéTareas que se repitenUna única ejecución en el futuro
Listar pendientescrontab -latq
CancelarEditar con crontab -e y borrar la líneaatrm <job>
Control de acceso/etc/cron.allow / /etc/cron.deny/etc/at.allow / /etc/at.deny (misma lógica)
Para equipos que no están encendidos las 24 horas (portátiles, estaciones de trabajo), existe anacron: en vez de depender de que el reloj marque exactamente la hora programada, comprueba al arrancar si una tarea diaria/semanal/mensual se quedó sin ejecutar mientras el equipo estaba apagado, y la lanza entonces. En sistemas con systemd, los timers (systemctl list-timers, módulo 101) son la alternativa moderna que cubre ambos casos a la vez.
🧰 Recursos relacionados (Ghost Academy)

Practica más — labs ya publicados en Ghost Academy sobre este tema: ⏰ Cron (lab) · 📅 Crontab: programando tareas (lab)

Herramienta interactiva — del Toolkit de Ghost Academy: 🛠️ CronCraft: generador visual de crontab

3. LPI 107.3 — Localización e internacionalización

3.1 Idioma y codificación: locale

root@lpic1:~#
$ locale
LANG=es_ES.UTF-8
LC_CTYPE="es_ES.UTF-8"
LC_NUMERIC="es_ES.UTF-8"
LC_TIME="es_ES.UTF-8"
LC_COLLATE="es_ES.UTF-8"
LC_MONETARY="es_ES.UTF-8"
LC_MESSAGES="es_ES.UTF-8"
LC_ALL=
VariableControla
LANGValor por defecto para todas las categorías LC_* que no se fijen explícitamente — la que normalmente basta con cambiar
LC_TIMEFormato de fechas y horas
LC_NUMERICSeparador decimal y de miles
LC_MONETARYFormato de cantidades monetarias
LC_COLLATEOrden alfabético (afecta a sort, módulo 103)
LC_MESSAGESIdioma de los mensajes del sistema y los programas
LC_ALLSobrescribe todas las demás LC_* y a LANG — pensada sobre todo para forzar un idioma concreto puntualmente en un único comando, no para uso permanente
root@lpic1:~#
$ LC_ALL=C date
Wed Sep 30 18:30:03 UTC 2026
LC_ALL=C (o LC_ALL=POSIX) antes de un comando es el truco clásico para forzar salida en inglés y formato "neutro" — muy usado al escribir scripts, para que su salida no cambie según el idioma configurado en la máquina donde se ejecuten.

3.2 Generar e instalar locales

root@lpic1:~#
$ cat /etc/locale.gen | grep -v '^#' | grep .
es_ES.UTF-8 UTF-8
root@lpic1:~#
$ locale-gen
Generating locales (this might take a while)...
  es_ES.UTF-8... done
Generation complete.
root@lpic1:~#
$ update-locale LANG=es_ES.UTF-8

En Debian/Ubuntu, el proceso completo para añadir un idioma nuevo es: descomentar la línea correspondiente en /etc/locale.gen (o usar dpkg-reconfigure locales, que hace lo mismo de forma interactiva), ejecutar locale-gen para generarla de verdad, y update-locale para fijarla como la activa por defecto en /etc/default/locale.

3.3 Zona horaria

root@lpic1:~#
$ timedatectl
               Local time: mié 2026-09-30 18:30:03 UTC
           Universal time: mié 2026-09-30 18:30:03 UTC
                 RTC time: mié 2026-09-30 18:30:03
                Time zone: Europe/Madrid (CEST, +0200)
System clock synchronized: yes
              NTP service: active
root@lpic1:~#
$ timedatectl list-timezones | grep Madrid
Europe/Madrid
root@lpic1:~#
$ timedatectl set-timezone Europe/Madrid

La configuración persiste como un enlace simbólico en /etc/localtime apuntando a la zona horaria correspondiente dentro de /usr/share/zoneinfo/, y el nombre en texto plano se guarda además en /etc/timezone. En sistemas más antiguos sin timedatectl, el equivalente es dpkg-reconfigure tzdata.

3.4 Convertir entre codificaciones: iconv

root@lpic1:~#
$ file documento.txt
documento.txt: ISO-8859 text
root@lpic1:~#
$ iconv -f ISO-8859-1 -t UTF-8 documento.txt -o documento_utf8.txt
Un fichero de texto con acentos que se ve como símbolos extraños (ñ en vez de ñ) casi siempre es un problema de codificación, no de contenido — se creó en una codificación antigua como ISO-8859-1 (Latin-1) y se está leyendo asumiendo UTF-8, o al revés. iconv convierte de una a otra sin tener que reescribir el fichero a mano.

Práctica guiada

  1. Crea un usuario nuevo con directorio personal y shell bash, añádelo a un grupo secundario con usermod -aG, y confirma con id.
  2. Consulta su entrada completa en /etc/passwd y (como root) en /etc/shadow, e identifica cada campo con las tablas de este módulo.
  3. Configúrale una caducidad de contraseña de 60 días con chage -M 60 y compruébalo con chage -l.
  4. Programa con crontab -e una tarea que escriba la fecha en un fichero cada 5 minutos (*/5 * * * * date >> /tmp/marca.txt), espera y comprueba el resultado.
  5. Programa una tarea puntual con at now + 2 minutes y revísala con atq antes de que se ejecute.
  6. Comprueba tu locale actual, y prueba a ejecutar LC_ALL=C date para ver la diferencia de formato.
  7. Revisa tu zona horaria con timedatectl y confirma que coincide con la que esperas.

Resumen de comandos del módulo

BloqueComandos clave
107.1 Usuarios y gruposuseradd, usermod, userdel, groupadd/groupmod/groupdel, chage, id/groups/whoami
107.2 Automatizacióncrontab -e/-l/-r, /etc/cron.d/, run-parts, at, atq, atrm
107.3 Localizaciónlocale, locale-gen, update-locale, timedatectl, iconv

Autoevaluación

  1. ¿Por qué usermod -G docker jose (sin -a) puede ser peligroso si jose ya pertenecía al grupo sudo?
  2. ¿Qué campo de /etc/passwd contiene el placeholder x, y dónde vive el dato real?
  3. ¿Qué diferencia de formato hay entre el crontab de un usuario (crontab -e) y /etc/crontab?
  4. ¿Qué cadena especial de cron equivale a 0 0 * * *?
  5. ¿Cuándo usarías at en vez de cron?
  6. ¿Qué variable fijarías para forzar que un único comando muestre su salida en formato "neutro" sin cambiar la configuración permanente del sistema?
  7. Un fichero de texto se ve con símbolos raros en vez de tildes. ¿Qué herramienta usarías para solucionarlo, y qué necesitas saber antes de usarla?
← 106 · Interfaces y X11Índice del curso108 · Servicios esenciales →