Recentemente ho riscontrato due diversi problemi su due diversi host Linux. Ognuno ha richiesto un'elusione unica perché devo ancora trovare una vera soluzione. Tuttavia, il metodo per fornire ogni elusione era lo stesso:eseguire un comando durante o subito dopo l'avvio di Linux.
Il rc.local
file era, e in alcuni casi è ancora, il posto in cui gli amministratori di sistema Linux possono inserire i comandi che devono essere eseguiti all'avvio. Uso di rc.local
il file non solo è deprecato ma dopo un paio d'ore di tentativi, non funzionava in ogni caso. Questo nonostante il fatto che systemd
la documentazione menziona l'uso di un "generatore" che genera systemd
servizi da un rc.local
file se ne esiste uno. (Sembra essere un buon modo come qualsiasi altro per imporre la deprecazione, facendo in modo che non funzioni.)
I dettagli del mio problema specifico non sono particolarmente rilevanti per questa discussione, quindi userò un comando semplice e facilmente rintracciabile come contenuto del nostro file di avvio locale. Aggiungeremo una riga con la data a un file di registro locale per verificare che il programma Bash che dobbiamo eseguire all'avvio funzioni effettivamente.
Avvio e avvio
La comprensione del processo di avvio e avvio di Linux è importante per la configurazione di Linux e la risoluzione dei problemi di avvio. In realtà, ci sono due sequenze di eventi che sono necessarie per avviare un computer Linux e renderlo utilizzabile:boot e startup. La sequenza di avvio inizia all'accensione del computer e termina quando il kernel viene inizializzato e systemd
viene lanciato. Il processo di avvio prende quindi il sopravvento e termina il compito di portare il computer Linux in uno stato operativo.
Nel complesso, il processo di avvio e avvio di Linux è abbastanza semplice da capire. Comprende i seguenti passaggi, che verranno descritti in seguito in modo più dettagliato:
- Autotest all'accensione del BIOS (POST)
- Caricatore di avvio (GRUB2)
- kernel
systemd
Per una descrizione molto più dettagliata delle sequenze di avvio e avvio, fare riferimento al mio articolo, Introduzione ai processi di avvio e avvio di Linux.
Avvio locale
Gli amministratori di sistema a volte aggiungono comandi alla sequenza di avvio che sono utili localmente. Queste aggiunte possono mirare ad avviare o eseguire processi locali che non fanno parte dello standard systemd
avviare. È possibile aggiungere un nuovo systemd
service unit per avviare ogni programma necessario all'avvio, ma il vecchio rc.local
il metodo ha fornito un singolo file eseguibile per tutte le esigenze di avvio locale. Anche noi possiamo usare questo approccio a file singolo con systemd
. L'eleganza di questa soluzione è che semplifica l'aggiunta di più comandi di avvio in un secondo momento, senza la necessità di aggiungere più unità di servizio a systemd
.
La nostra soluzione è creare un unico systemd
service unit e inserire tutti i comandi Linux necessari nel file eseguibile. Ci sono due parti in questa soluzione. Uno è ovvio:abbiamo bisogno di un file eseguibile. E due, dobbiamo creare un'unità di servizio per systemd
che esegue l'eseguibile.
Crea il file eseguibile
Questo è un esercizio banale per qualsiasi amministratore di sistema che abbia familiarità con la programmazione Bash. In effetti, creeremo un programma Bash e lo collocheremo nella posizione FHS (Filesystem Hierarchical Standard) di Linux per i file eseguibili locali, /usr/local/bin
. Potrebbe essere addotto un argomento per posizionare questo file eseguibile in un'altra posizione, ma /usr/local/bin
è quello che ha più senso per me poiché questa posizione rende facile per l'amministratore di sistema eseguire lo script dalla riga di comando, se necessario. Il /usr/local/bin
la directory è sempre nel $PATH
di ogni utente , incluso quello dell'utente root.
Crea il mystartup.sh
file mostrato qui e inserirlo in /usr/local/bin
(assicurati di renderlo eseguibile). Assicurati di utilizzare la posizione di Bash corretta per la tua distribuzione. Ad esempio, le distribuzioni basate su Debian individuano Bash in /bin/bash
.
#!/usr/bin/bash
################################################################################
# mystartup.sh
#
# This shell program is for testing a startup like rc.local using systemd.
# By David Both
# Licensed under GPL V2
#
################################################################################
# This program should be placed in /usr/local/bin
################################################################################
# This is a test entry
echo `date +%F" "%T` "Startup worked" >> /root/mystartup.log
Nota: I commenti nei file inclusi indicano dove devono trovarsi.
Assicurati di testare questo eseguibile eseguendolo dalla riga di comando. La prima volta che esegui questo script di shell, dovresti vedere un nuovo file, /root/mystartup.log
, con ora e data insieme al testo, "Startup worked"
. Creiamo questo file di registro e vi aggiungiamo righe ogni volta che lo script viene eseguito come semplice test per assicurarci che il nostro script funzioni.
Esegui lo script un altro paio di volte. I tuoi risultati dovrebbero essere simili a quelli qui:
[root@testvm1 ~]# mystartup.sh
[root@testvm1 ~]# cat mystartup.log
2019-09-12 19:58:00 Startup worked
2019-09-12 19:58:17 Startup worked
2019-09-12 19:58:54 Startup worked
2019-09-12 19:59:00 Startup worked
2019-09-12 20:01:08 Startup worked
2019-09-12 20:04:01 Startup worked
2019-09-12 20:04:13 Startup worked
2019-09-12 20:06:11 Startup worked
2019-09-12 20:06:28 Startup worked
2019-09-16 09:51:21 Startup worked
2019-09-16 09:51:51 Startup worked
Questo è tutto ciò che dobbiamo fare per creare il file che potrebbe eventualmente contenere i nostri comandi di avvio locali. Basta aggiungere a questo file tutto ciò che deve essere eseguito all'avvio.
Crea il servizio systemd
L'unità di servizio che creeremo ora è un systemd
standard file dell'unità di servizio. Questo semplice file viene utilizzato solo per eseguire mystartup.sh
script all'avvio.
Crea un nuovo file, /usr/local/lib/systemd/system/mystartup.service
e aggiungi i contenuti mostrati di seguito:
################################################################################
# mystartup.service
#
# This service unit is for testing my systemd startup service
# By David Both
# Licensed under GPL V2
#
################################################################################
# This program should be placed in /usr/local/lib/systemd/system/.
# Create a symlink to it from the /etc/systemd/system directory.
################################################################################
[Unit]
Description=Runs /usr/local/bin/mystartup.sh
[Service]
ExecStart=/usr/local/bin/mystartup.sh
[Install]
WantedBy=multi-user.target
Non è necessario che questo file sia eseguibile. Questo file potrebbe anche trovarsi in /etc/systemd/system
, ma come file locale è meglio posizionarlo in /usr/local
ramo della struttura della directory, con un collegamento ad esso da /etc/systemd.system
.
Ora vai su /etc/systemd/system
e creare il collegamento simbolico nel file dell'unità di servizio:
[root@testvm1 system]# ln -s /usr/local/lib/systemd/system/mystartup.service
Verifica l'unità di servizio
Dovremmo testare il file dell'unità di servizio finale prima di riavviare l'host Linux per il test finale. Innanzitutto, verifichiamo che systemd
vede il servizio:
[root@testvm1 ~]# systemctl status mystartup
● mystartup.service - Runs /usr/local/bin/mystartup.sh
Loaded: loaded (/usr/local/lib/systemd/system/mystartup.service; linked; vendor preset: disabled)
Active: inactive (dead)
[root@testvm1 ~]#
Questo risultato ci dice che il servizio è riconosciuto da systemd
. Ora, avviamo il servizio. In questo modo verrà eseguito lo script ma non verrà configurato il nuovo servizio da eseguire all'avvio:
[root@testvm1 ~]# systemctl start mystartup
Controlla il contenuto del file di registro per verificare che la nuova riga sia stata aggiunta.
Abilita il servizio
Non resta che abilitare il servizio in modo che venga eseguito all'avvio:
[root@testvm1 ~]# systemctl enable mystartup
Created symlink /etc/systemd/system/multi-user.target.wants/mystartup.service →
/usr/local/lib/systemd/system/mystartup.service.
[root@testvm1 ~]#
Test finale
Prima di riavviare, diamo un'occhiata a journalctl
comando e come possiamo usarlo per visualizzare le voci del diario relative a mystartup.service
. Possiamo anche usare il journalctl
comando per verificarlo perché systemd
tiene un diario di tutto ciò che fa.
Nel comando seguente, -u
l'opzione mostra solo le voci per mystartup
unità:
[root@testvm1 ~]# journalctl -u mystartup
-- Logs begin at Mon 2019-04-15 22:50:27 EDT, end at Mon 2019-09-16 11:44:30 EDT. --
Sep 16 11:09:28 testvm1 systemd[1]: Started Runs /usr/local/bin/mystartup.sh.
[root@testvm1 ~]#
Ora, riavvia l'host Linux e controlla il file di registro per assicurarti che sia stata aggiunta una nuova riga:
[root@testvm1 ~]# systemctl status mystartup
● mystartup.service - Runs /usr/local/bin/mystartup.sh
Loaded: loaded (/usr/local/lib/systemd/system/mystartup.service; enabled; vendor preset: disabled)
Active: inactive (dead) since Mon 2019-09-16 11:45:59 EDT; 1min 30s ago
Process: 819 ExecStart=/usr/local/bin/mystartup.sh (code=exited, status=0/SUCCESS)
Main PID: 819 (code=exited, status=0/SUCCESS)
Sep 16 11:45:55 testvm1 systemd[1]: Started Runs /usr/local/bin/mystartup.sh.
[root@testvm1 ~]# journalctl -u mystartup
-- Logs begin at Mon 2019-04-15 22:50:27 EDT, end at Mon 2019-09-16 11:47:45 EDT. --
Sep 16 11:09:28 testvm1 systemd[1]: Started Runs /usr/local/bin/mystartup.sh.
-- Reboot --
Sep 16 11:45:55 testvm1 systemd[1]: Started Runs /usr/local/bin/mystartup.sh.
[root@testvm1 ~]#
Conclusione
Lo script della shell Bash che abbiamo creato per questo esperimento viene eseguito una volta all'avvio e quindi esce. Non rimane in memoria come demone perché non è stato progettato per farlo.
Nel caso non l'avessi notato, la procedura che abbiamo utilizzato per creare il nostro servizio di avvio locale può essere utilizzata anche per creare qualsiasi nuovo servizio per systemd
. Non è così difficile una volta che sappiamo come farlo.
Aggiorna
Subito dopo la pubblicazione di questo articolo ho ricevuto un'e-mail da Tom Murphy che mi informava dell'esistenza di rc-local
servizio che fa parte di systemd
. Apprezzo quell'email perché non ero a conoscenza di quel servizio, quindi ho imparato qualcosa di nuovo.
È possibile aggiungere il supporto per il vecchio rc.local
abilitando il servizio con il comando systemctl enable rc-local
. I comandi nel file rc.local verranno eseguiti al prossimo avvio. Ovviamente puoi utilizzare systemctl enable rc-local
per eseguire rc.local
immediatamente.
Tuttavia, è ancora vero che rc.local è obsoleto. La pagina man per systemd-rc-local-generator
afferma:"Il supporto per /etc/rc.local è fornito solo per la compatibilità con sistemi System V specifici. Tuttavia, si consiglia vivamente di evitare di utilizzare questo script oggi e di fornire invece file di unità appropriati con le dipendenze appropriate per gli script da eseguire durante il processo di avvio."
Risorse
-
DataBook Linux Filesystem Hierarchical Standard (FHS) per Linux
-
Informazioni su GNU GRUB
-
Manuale di GNU GRUB
-
Record di avvio principale
-
Specifica multiboot
-
informazioni di sistema
-
processo di avvio del sistema
-
systemd indice delle pagine man
-
Un'introduzione ai processi di avvio e avvio di Linux
[Vuoi provare Red Hat Enterprise Linux? Scaricalo ora gratuitamente.]