systemd és el sistema d'inicialització i gestió de serveis més utilitzat en distribucions Linux modernes (Ubuntu, Debian, Fedora, CentOS, Arch, etc.).
Funcions principals:
Avantatges sobre SysV init tradicional:
systemctl és la comanda principal per interactuar amb systemd.
# Iniciar un servei
sudo systemctl start nginx
# Aturar un servei
sudo systemctl stop nginx
# Reiniciar un servei
sudo systemctl restart nginx
# Recarregar configuració sense reiniciar
sudo systemctl reload nginx
# Reiniciar només si està actiu
sudo systemctl try-restart nginx
# Recarregar o reiniciar
sudo systemctl reload-or-restart nginx
# Habilitar servei al boot (crea symlink)
sudo systemctl enable nginx
# Deshabilitar servei al boot
sudo systemctl disable nginx
# Habilitar i iniciar
sudo systemctl enable --now nginx
# Deshabilitar i aturar
sudo systemctl disable --now nginx
# Comprovar si està habilitat
systemctl is-enabled nginx
# Estat detallat d'un servei
systemctl status nginx
# Comprovar si està actiu
systemctl is-active nginx
# Comprovar si ha fallat
systemctl is-failed nginx
# Llistar tots els serveis
systemctl list-units --type=service
# Llistar només serveis actius
systemctl list-units --type=service --state=active
# Llistar serveis que han fallat
systemctl list-units --type=service --state=failed
# Veure totes les units
systemctl list-unit-files
# Veure què requereix un servei
systemctl list-dependencies nginx
# Veure què depèn d'aquest servei
systemctl list-dependencies --reverse nginx
Els fitxers de servei es guarden a:
/etc/systemd/system/ (creats per l'administrador)/lib/systemd/system/ (instal·lats per paquets)[Unit]
Description=Descripció del servei
Documentation=https://exemple.cat/docs
After=network.target
Requires=postgresql.service
Wants=redis.service
[Service]
Type=simple
User=usuari
Group=grup
WorkingDirectory=/opt/app
ExecStart=/opt/app/start.sh
ExecStop=/opt/app/stop.sh
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
RestartSec=5s
Environment="VAR1=valor1" "VAR2=valor2"
EnvironmentFile=/etc/app/config
[Install]
WantedBy=multi-user.target
Metadades i dependències:
Description: Descripció breuDocumentation: URL de documentacióAfter: Iniciar després d'aquestes unitsBefore: Iniciar abans d'aquestes unitsRequires: Units imprescindibles (falla si falten)Wants: Units opcionals (no falla si falten)Configuració del servei:
Type: Tipus de servei
simple: El procés principal és el que inicia ExecStart (per defecte)forking: El procés fa fork i el pare surtoneshot: Procés que s'executa i acaba (per scripts)notify: El procés notifica quan està llestidle: Espera que tots els jobs acabinExecStart: Comanda per iniciar
ExecStop: Comanda per aturar (opcional)
ExecReload: Comanda per recarregar (opcional)
Restart: Quan reiniciar automàticament
no: Mai reiniciar (per defecte)on-failure: Només si fallaon-abnormal: Si acaba anormalmentalways: Sempre reiniciarRestartSec: Temps d'espera abans de reiniciar
User, Group: Usuari i grup per executar
WorkingDirectory: Directori de treball
Environment: Variables d'entorn
StandardOutput, StandardError: On redirigir stdout/stderr
Com instal·lar el servei:
WantedBy: Targets que volen aquest serveiRequiredBy: Targets que requereixen aquest servei#!/bin/bash
# /opt/monitor/monitor.sh
while true; do
echo "[$(date)] Monitoritzant sistema..."
df -h / >> /var/log/monitor.log
free -h >> /var/log/monitor.log
sleep 300 # 5 minuts
done
Fitxer de servei /etc/systemd/system/monitor.service:
[Unit]
Description=Monitor del sistema
After=network.target
[Service]
Type=simple
User=root
ExecStart=/opt/monitor/monitor.sh
Restart=always
RestartSec=10s
[Install]
WantedBy=multi-user.target
Activar:
# Fer executable l'script
chmod +x /opt/monitor/monitor.sh
# Recarregar systemd per veure el nou servei
sudo systemctl daemon-reload
# Iniciar i habilitar
sudo systemctl enable --now monitor.service
# Comprovar estat
systemctl status monitor.service
# Veure logs
journalctl -u monitor.service -f
// /opt/myapp/server.js
const http = require('http');
const server = http.createServer((req, res) => {
res.writeHead(200);
res.end('Hello World!');
});
server.listen(3000, () => {
console.log('Servidor escoltant al port 3000');
});
Fitxer de servei /etc/systemd/system/myapp.service:
[Unit]
Description=My Node.js App
After=network.target
[Service]
Type=simple
User=www-data
WorkingDirectory=/opt/myapp
ExecStart=/usr/bin/node server.js
Restart=on-failure
RestartSec=5s
StandardOutput=journal
StandardError=journal
Environment="NODE_ENV=production"
Environment="PORT=3000"
[Install]
WantedBy=multi-user.target
Per scripts que s'executen una vegada i acaben:
#!/bin/bash
# /opt/scripts/cleanup.sh
echo "Netejant fitxers temporals..."
find /tmp -type f -mtime +7 -delete
echo "Neteja completada"
Fitxer de servei /etc/systemd/system/cleanup.service:
[Unit]
Description=Neteja de fitxers temporals
[Service]
Type=oneshot
ExecStart=/opt/scripts/cleanup.sh
Executar manualment:
sudo systemctl start cleanup.service
systemd usa journald per gestionar logs.
# Veure tots els logs
journalctl
# Logs en temps real (com tail -f)
journalctl -f
# Logs d'un servei específic
journalctl -u nginx
# En temps real d'un servei
journalctl -u nginx -f
# Últimes 100 línies
journalctl -u nginx -n 100
# Des d'un moment específic
journalctl -u nginx --since "2024-01-08 10:00:00"
journalctl -u nginx --since today
journalctl -u nginx --since yesterday
journalctl -u nginx --since "1 hour ago"
# Entre dates
journalctl --since "2024-01-08 00:00:00" --until "2024-01-08 23:59:59"
# Només errors
journalctl -u nginx -p err
# Prioritats:
# 0: emerg (emergència)
# 1: alert
# 2: crit (crític)
# 3: err (error)
# 4: warning
# 5: notice
# 6: info
# 7: debug
# Revertir ordre (més antics primer)
journalctl -r
# Format JSON
journalctl -u nginx -o json
# Veure espai ocupat pels logs
journalctl --disk-usage
# Netejar logs antics
sudo journalctl --vacuum-time=7d # Mantenir només 7 dies
sudo journalctl --vacuum-size=100M # Mantenir màxim 100MB
Els timers són una alternativa a cron, integrada amb systemd.
Cal crear 2 fitxers:
Exemple: Backup diari
/etc/systemd/system/backup.service:
[Unit]
Description=Backup diari de dades
[Service]
Type=oneshot
ExecStart=/opt/scripts/backup.sh
User=backup
StandardOutput=journal
StandardError=journal
/etc/systemd/system/backup.timer:
[Unit]
Description=Executar backup cada dia a les 2 AM
[Timer]
OnCalendar=daily
OnCalendar=02:00
Persistent=true
[Install]
WantedBy=timers.target
Opcions d'OnCalendar:
OnCalendar=hourly # Cada hora
OnCalendar=daily # Cada dia a les 00:00
OnCalendar=weekly # Cada dilluns a les 00:00
OnCalendar=monthly # Primer dia del mes a les 00:00
OnCalendar=*-*-* 02:00:00 # Cada dia a les 2 AM
OnCalendar=Mon-Fri 09:00 # De dilluns a divendres a les 9 AM
OnCalendar=*-*-01 00:00:00 # Primer dia de cada mes
OnCalendar=Sat *-*-* 00:00:00 # Cada dissabte
Altres opcions:
OnBootSec=5min # 5 minuts després del boot
OnUnitActiveSec=1h # 1 hora després de l'última execució
OnActiveSec=10s # 10 segons després d'activar el timer
Activar el timer:
# Recarregar systemd
sudo systemctl daemon-reload
# Habilitar i iniciar el timer
sudo systemctl enable --now backup.timer
# Veure estat del timer
systemctl status backup.timer
# Llistar tots els timers
systemctl list-timers
# Veure quan s'executarà
systemctl list-timers --all
# Forçar execució immediata
sudo systemctl start backup.service
zenity permet crear diàlegs gràfics des de scripts bash.
sudo apt install zenity
Missatge informatiu:
zenity --info --text="Procés completat correctament!"
Pregunta Sí/No:
if zenity --question --text="Vols continuar?"; then
echo "Usuari va dir SÍ"
else
echo "Usuari va dir NO"
fi
Entrada de text:
NOM=$(zenity --entry --text="Introdueix el teu nom:")
echo "Hola, $NOM!"
Contrasenya:
PASS=$(zenity --password --title="Autenticació")
Selecció de fitxer:
FITXER=$(zenity --file-selection --title="Selecciona un fitxer")
echo "Has seleccionat: $FITXER"
Selecció de directori:
DIR=$(zenity --file-selection --directory --title="Selecciona un directori")
Llista de selecció:
OPCIO=$(zenity --list \
--title="Selecciona una opció" \
--column="ID" --column="Descripció" \
1 "Opció 1" \
2 "Opció 2" \
3 "Opció 3")
echo "Has seleccionat l'opció $OPCIO"
Barra de progrés:
(
echo "10" ; sleep 1
echo "# Processant fitxers..." ; sleep 1
echo "30" ; sleep 1
echo "# Comprimint..." ; sleep 1
echo "60" ; sleep 1
echo "# Gairebé fet..." ; sleep 1
echo "100"
) | zenity --progress \
--title="Procés en curs" \
--text="Iniciant..." \
--percentage=0 \
--auto-close
Barra de progrés pulsant:
find / -name "*.log" | zenity --progress \
--pulsate \
--text="Cercant fitxers log..." \
--auto-close
Calendari:
DATA=$(zenity --calendar --title="Selecciona una data" --format="%Y-%m-%d")
echo "Data seleccionada: $DATA"
Formulari:
DADES=$(zenity --forms \
--title="Formulari d'usuari" \
--text="Introdueix les dades" \
--add-entry="Nom" \
--add-entry="Cognoms" \
--add-entry="Email" \
--add-calendar="Data de naixement")
echo "Dades: $DADES"
Error:
zenity --error --text="Ha ocorregut un error!"
Avís:
zenity --warning --text="Atenció: Aquesta acció no es pot desfer"
notify-send mostra notificacions al sistema de notificacions del desktop.
sudo apt install libnotify-bin
Notificació simple:
notify-send "Títol" "Missatge de la notificació"
Amb urgència:
# Urgència baixa
notify-send -u low "Info" "Això és informació"
# Urgència normal (per defecte)
notify-send -u normal "Avís" "Això és un avís"
# Urgència crítica
notify-send -u critical "Error" "Això és un error!"
Amb icona:
notify-send -i dialog-information "Info" "Procés completat"
notify-send -i dialog-warning "Avís" "Atenció necessària"
notify-send -i dialog-error "Error" "Ha fallat el procés"
Amb timeout:
# Desapareix després de 5000 ms (5 segons)
notify-send -t 5000 "Missatge temporal" "Aquest missatge desapareixerà aviat"
Exemple pràctic: Monitor de disc
#!/bin/bash
LIMIT=80
US=$(df -h / | tail -1 | awk '{print $5}' | sed 's/%//')
if [ $US -gt $LIMIT ]; then
notify-send -u critical \
-i dialog-warning \
"Disc gairebé ple" \
"El disc està al ${US}% de capacitat!"
fi
yad (Yet Another Dialog) és similar a zenity però amb més opcions.
sudo apt install yad
# Exemple amb múltiples botons
yad --text="Què vols fer?" \
--button="Backup:0" \
--button="Restaurar:1" \
--button="Cancel·lar:2"
case $? in
0) echo "Fent backup..." ;;
1) echo "Restaurant..." ;;
2) echo "Cancel·lat" ;;
esac
#!/bin/bash
##############################################
# Script de backup amb interfície gràfica
##############################################
# Funcions per a diàlegs
mostrar_info() {
zenity --info --title="Backup" --text="$1"
}
mostrar_error() {
zenity --error --title="Error" --text="$1"
}
preguntar() {
zenity --question --title="Confirmació" --text="$1"
}
# Menú principal
OPCIO=$(zenity --list \
--title="Sistema de Backup" \
--text="Selecciona una opció:" \
--column="Acció" \
"Fer backup" \
"Restaurar backup" \
"Veure backups" \
"Configuració" \
"Sortir")
case "$OPCIO" in
"Fer backup")
# Seleccionar directori
ORIGEN=$(zenity --file-selection --directory \
--title="Selecciona directori per fer backup")
if [ -z "$ORIGEN" ]; then
mostrar_error "No s'ha seleccionat cap directori"
exit 1
fi
if preguntar "Fer backup de $ORIGEN?"; then
# Fer backup amb barra de progrés
(
echo "20" ; echo "# Preparant..."
sleep 1
echo "40" ; echo "# Comprimint fitxers..."
tar -czf backup.tar.gz "$ORIGEN" 2>&1
echo "80" ; echo "# Verificant..."
sleep 1
echo "100" ; echo "# Completat!"
) | zenity --progress \
--title="Creant backup" \
--percentage=0 \
--auto-close
notify-send -i dialog-information \
"Backup completat" \
"S'ha creat correctament el backup"
mostrar_info "Backup creat correctament!"
fi
;;
"Veure backups")
BACKUPS=$(ls -lh backup_*.tar.gz 2>/dev/null | awk '{print $9"|"$5"|"$6" "$7}')
if [ -z "$BACKUPS" ]; then
mostrar_info "No hi ha backups disponibles"
else
echo "$BACKUPS" | zenity --list \
--title="Backups disponibles" \
--column="Fitxer" --column="Mida" --column="Data" \
--width=600 --height=400
fi
;;
"Sortir")
exit 0
;;
esac
systemctl per controlar serveis: start, stop, restart, enable, disable/etc/systemd/system/journalctl per veure logs dels serveissystemctl daemon-reload després de crear/modificar serveis