Cómo «congelar / restaurar» la configuración de escritorio del alumno al iniciar el sistema

Seguro que existen soluciones más «profesionales» pero esta es la que mejor nos está funcionando en los Colegios.

Se trata de garantizar la «experiencia de usuario» permitiendo al alumno que adapte y modifique a su gusto el escritorio y configuración de los programas en su sesión (fondo de escritorio, complementos, ventanas, etc). Cuando se reinicie el ordenador la sesión del alumno volverá a una configuración inicial prefijada, lo que no implica necesariamente perder los documentos creados en la sesión anterior.

El proceso es relativamente sencillo:

  1. Creamos un fichero con la información que deseamos mantener, por ejemplo con:
    tar -zcf /home/alumno.tgz /home/alumno/.config /home/alumno/.local /home/alumno/.profile

    Podemos añadir todos aquellos directorios y ficheros que consideremos importantes. Personalmente tengo un pequeño shell-script  que me permite regenerar el archivo después de aplicar actualizaciones en el sistema.

  2. Editamos el fichero «/etc/rc.local» y añadimos la orden para restaurar la configuración del alumno:
    tar -zxf /home/alumno.tgz -C / >/dev/null 2>&1

    Este fichero se ejecutará al final del proceso de arranque de  Linux.  Otra posibilidad es programar la acción en el servicio de «cron» del sistema para que lo haga una vez a la semana o en los momentos en los que nos interese.

Problema en las últimas versiones de Ubuntu >= 16.10

El fichero «/etc/rc.local» no se incluye por defecto y crearle manualmente no es suficiente. El «problema» viene por el uso del nuevo «systemd» como sustituto del proceso «init.d»  de inicio del sistema.

Para comprobarlo prueba a habilitar «servicio»:

sudo systemctl enable rc-local

En caso de no disponer de «rc-local» obtendrás una respuesta similar a esta:

The unit files have no installation config (WantedBy, RequiredBy, Also, Alias
settings in the [Install] section, and DefaultInstance for template units).
This means they are not meant to be enabled using systemctl.
Possible reasons for having this kind of units are:
1) A unit may be statically enabled by being symlinked from another unit's
 .wants/ or .requires/ directory.
2) A unit's purpose may be to act as a helper for some other unit which has
 a requirement dependency on it.
3) A unit may be started when needed via activation (socket, path, timer,
 D-Bus, udev, scripted systemctl call, ...).
4) In case of template units, the unit is meant to be enabled with some
 instance name specified.

Solución

  1. Crea el fichero «/etc/rc.local» asegurándote de añadir la orden «exit» con el código de salida «0» u otro en caso de error:
    #!/bin/sh -e
    tar -zxf /home/alumno.tgz -C / >/dev/null 2>&1
    exit 0
  2. Asegúrate de que tenga los permisos de ejecución:
    sudo chmod +x /etc/rc.local
  3. Crea un fichero de definición del servicio de la forma
    sudo vi /etc/systemd/system/rc-local.service

    y añade el siguiente contenido:

    [Unit]
     Description=/etc/rc.local Compatibility
     ConditionPathExists=/etc/rc.local
    
    [Service]
     Type=forking
     ExecStart=/etc/rc.local start
     TimeoutSec=0
     StandardOutput=tty
     RemainAfterExit=yes
    
    [Install]
     WantedBy=multi-user.target
  4. Ahora habilita el servicio para que arranque al inicio del sistema:
    sudo systemctl enable rc-local

    y obtendrás una salida parecida a esta:

    Created symlink /etc/systemd/system/multi-user.target.wants/rc-local.service → /etc/systemd/system/rc-local.service.

    En caso contrario revisa el fichero «/etc/systemd/system/rc-local.service» y vuelve a intentarlo.

  5. Por último inicia el servicio:
    sudo systemctl start rc-local.service

    y comprueba su estado:

    sudo systemctl status rc-local.service

    Si todo ha ido bien obtendrás una salida similar a esta:

     rc-local.service - /etc/rc.local Compatibility
     Loaded: loaded (/etc/systemd/system/rc-local.service; enabled; vendor preset: enabled)
     Drop-In: /lib/systemd/system/rc-local.service.d
     └─debian.conf
     Active: active (exited) since jue 2017-01-12 16:05:17 CET; 6s ago
     Process: 5913 ExecStart=/etc/rc.local start (code=exited, status=0/SUCCESS)
    
    ene 12 16:05:17 linuxcasa1 systemd[1]: Starting /etc/rc.local Compatibility...
    ene 12 16:05:17 linuxcasa1 systemd[1]: Started /etc/rc.local Compatibility.

Opción 2: programación con «cron»

Si la solución anterior no es posible o prefieres depender del proceso «cron» del sistema (que a su vez debe estar habilitado) puedes ejecutar:

sudo crontab -e

y añadir la línea

@reboot  /bin/ tar -zxf /home/alumno.tgz -C / >/dev/null 2>&1

Explicación adicional sobre el inicio de servicios

init.d, también conocido como script SysV, permite iniciar y parar servicios durante la inicialización y cierre del sistema (los scripts de /etc/init.d/ también son procesados en sistemas con  «systemd» por compatibilidad).

  • Puedes definir en qué orden exactamente se ejecutarán los scripts, tanto al inicio como al cerrar el sistema.
  • Estos scripts (si están bien definidos) deben soportar los parámetros start y stop por lo menos (siguiendo las recomendaciones de Debian).

crontab (y en particular con  @reboot).

  • cron puede ejecutar cualquier comando o script.
  • cualquier usuario puede agregar a su lista de tareas una de tipo  @reboot
  • en sistemas basados en  Debian (como Ubuntu y derivados)  que ya implementan «systemd» las líneas «@reboot»  se ejecutan durante el objetivo (nivel de ejecución)  multi-user.target.
  • en sistemas  SysV (no systemd), las llamadas   @reboot de cron se ejecutarán en el momento (orden) en el que se ejecute el propio servicio de cron.
  • es muy fácil programar el mismo script para que se ejecute al inicio y/o de forma periódica.

/etc/rc.local está desaconsejado (se considera una mala práctica y se propone su desaparición) pero mantiene algunas características interesantes:

  • permite ejecutar cualquier comando o script.
  • en sistemas basados en Debian con SysV (no systemd)  rc.local suele ser el último servicio en iniciarse.
  • sin embargo en sistemas con  systemd: rc.local por defecto se ejecuta después  el objetivo  network.target ( y antes de network-online.target )