Cum să activezi încărcarea automată a scripturilor în Ubuntu: Trei metode pregătite pentru producție
Activarea încărcării automate a scripturilor în Ubuntu înseamnă configurarea sistemului de operare pentru a executa automat unul sau mai multe scripturi shell sau servicii la pornirea sistemului, fără nicio intervenție manuală. Acest lucru se realizează prin trei mecanisme principale: directorul /etc/init.d/ bazat pe SysVinit (moștenire), shim-ul de compatibilitate /etc/rc.local și cadrul modern de unități de servicii systemd — acesta din urmă fiind abordarea autoritativă, recomandată pe toate versiunile Ubuntu începând cu 15.04.
Pentru administratorii de sistem care rulează sarcini de lucru într-un mediu de VPS Hosting, automatizarea la pornire nu este o comoditate — este o cerință de fiabilitate. O intrare de pornire automată configurată greșit sau absentă înseamnă că daemonii critici, agenții de monitorizare, scripturile de backup sau configurațiile de rețea personalizate nu reușesc să pornească în tăcere după o repornire, cauzând întreruperi de serviciu dificil de diagnosticat ulterior.
De ce contează automatizarea scripturilor de pornire pe serverele Ubuntu
Fiecare server Ubuntu de producție acumulează în timp scripturi operaționale: rutine de pre-încălzire a bazelor de date, declanșatoare de rotație a jurnalelor, inițializatoare de tuneluri VPN, încărcătoare de reguli de firewall și verificări ale stării aplicațiilor. Fără un mecanism structurat de încărcare automată, aceste scripturi depind în totalitate de execuția manuală — un singur pas ratat după o actualizare de kernel sau o repornire de urgență poate duce la întreruperi în cascadă.
Ecosistemul de automatizare la pornire al Ubuntu a evoluat semnificativ:
- SysVinit (pre-Ubuntu 15.04): Secvențial, lent, bazat pe scripturi. Fiecare serviciu îl bloca pe următorul.
- Upstart (Ubuntu 6.10–15.04): Bazat pe evenimente, mai rapid, dar acum depreciat.
- systemd (Ubuntu 15.04+): Activare paralelă a serviciilor, grafuri de dependențe, activare prin socket, control al resurselor bazat pe cgroup și jurnalizare structurată prin
journald.
Înțelegerea nivelului cu care lucrați — și de ce — vă împiedică să implementați o soluție funcțională într-un mediu de test care se defectează în tăcere în producție.
Metoda 1: Utilizarea directorului /etc/init.d/ (SysVinit / Scripturi LSB)
Cum funcționează
Directorul /etc/init.d/ este locul tradițional pentru scripturile de inițializare Linux Standard Base (LSB). Fiecare script din acest director este un script shell care răspunde la comenzi standardizate: start, stop, restart, status și opțional reload. Utilitarul update-rc.d creează legături simbolice în directoarele de nivel de execuție /etc/rcN.d/, determinând când și în ce ordine se execută scriptul în timpul secvențelor de pornire și oprire.
Pe sistemele Ubuntu moderne care rulează systemd, aceste scripturi sunt în continuare suportate printr-un nivel de compatibilitate numit systemd-sysv-generator, care convertește automat scripturile de inițializare LSB în unități systemd tranzitorii. Aceasta înseamnă că scripturile dvs. /etc/init.d/ vor rula în continuare, dar sunt învelite de systemd în loc să fie executate direct de SysVinit.
Implementare pas cu pas
Pasul 1: Creați scriptul
Scrieți scriptul și asigurați-vă că respectă convenția antetului LSB. Un exemplu minimal, sigur pentru producție:
#!/bin/bash
### BEGIN INIT INFO
# Provides: examplescript
# Required-Start: $remote_fs $syslog $network
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Example autoload script
# Description: Runs a custom initialization task at boot
### END INIT INFO
case "$1" in
start)
echo "Starting examplescript..."
/usr/local/bin/examplescript.sh &
;;
stop)
echo "Stopping examplescript..."
pkill -f examplescript.sh
;;
restart)
$0 stop
$0 start
;;
status)
pgrep -f examplescript.sh > /dev/null && echo "Running" || echo "Stopped"
;;
*)
echo "Usage: $0 {start|stop|restart|status}"
exit 1
;;
esac
exit 0Pasul 2: Plasați scriptul în /etc/init.d/
sudo cp examplescript /etc/init.d/examplescriptPasul 3: Faceți-l executabil
sudo chmod +x /etc/init.d/examplescriptPasul 4: Înregistrați-l în sistemul de nivel de execuție
sudo update-rc.d examplescript defaultsArgumentul defaults înregistrează scriptul pentru a porni la nivelurile de execuție 2, 3, 4 și 5 și pentru a se opri la nivelurile 0, 1 și 6 — comportamentul standard pentru majoritatea daemonilor de server.
Pasul 5: Verificați înregistrarea
ls -la /etc/rc2.d/ | grep examplescriptAr trebui să vedeți o legătură simbolică precum S01examplescript care indică înapoi spre /etc/init.d/examplescript.
Capcana critică
Cea mai frecventă greșeală cu această metodă este omiterea blocului de antet LSB. Fără el, update-rc.d nu poate determina ordinea dependențelor, iar systemd-sysv-generator poate atribui o ordine de execuție incorectă față de disponibilitatea rețelei sau montările sistemului de fișiere. Definiți întotdeauna explicit dependențele Required-Start.
Pentru a elimina scriptul din pornirea automată fără a-l șterge:
sudo update-rc.d examplescript disablePentru a-l elimina complet:
sudo update-rc.d examplescript removeMetoda 2: Utilizarea /etc/rc.local (Shim de compatibilitate)
Cum funcționează
/etc/rc.local este un mecanism moștenit care execută un script shell o singură dată, după ce toate serviciile standard de nivel multi-utilizator au pornit. Este cea mai simplă metodă posibilă de pornire automată — fără gestionarea serviciilor, fără declarații de dependențe, fără logică de repornire. Pe Ubuntu 18.04 și versiunile ulterioare, suportul rc.local este asigurat de unitatea systemd rc-local.service, care este dezactivată implicit și trebuie activată explicit.
Când să o utilizați
Utilizați /etc/rc.local doar pentru:
- Comenzi de inițializare unice care nu trebuie gestionate ca servicii
- Prototipare rapidă sau testare înainte de formalizarea unei unități systemd
- Exporturi simple de variabile de mediu sau ajustări ale parametrilor kernel
Nu utilizați /etc/rc.local pentru daemoni cu rulare îndelungată. Deoarece rulează într-un mod blocant, secvențial, fără supraveghere a proceselor, o comandă blocată în rc.local va întârzia sau va împiedica finalizarea secvenței de pornire.
Implementare pas cu pas
Pasul 1: Verificați dacă /etc/rc.local există
ls -la /etc/rc.localDacă nu există, creați-l:
sudo bash -c 'cat > /etc/rc.local << EOF
#!/bin/bash
exit 0
EOF'
sudo chmod +x /etc/rc.localPasul 2: Activați unitatea systemd rc-local (Ubuntu 18.04+)
sudo systemctl enable rc-local
sudo systemctl start rc-localPasul 3: Adăugați comanda dvs. înainte de exit 0
sudo nano /etc/rc.localInserați comanda dvs. deasupra liniei exit 0:
#!/bin/bash
/usr/local/bin/examplescript.sh >> /var/log/examplescript.log 2>&1 &
exit 0& de la sfârșit este esențial pentru orice comandă cu rulare îndelungată — bifurcă procesul în fundal astfel încât rc.local să nu blocheze.
Pasul 4: Verificați execuția
sudo systemctl status rc-localCapcana critică
Pe Ubuntu 20.04 și 22.04, rc-local.service are un timeout hardcodat de 30 de secunde. Dacă scriptul dvs. durează mai mult de 30 de secunde pentru a se finaliza, systemd va marca serviciul ca eșuat și comenzile ulterioare din rc.local nu se vor executa. Redirecționați explicit ieșirea și treceți în fundal procesele cu rulare îndelungată.
Metoda 3: Utilizarea unităților de servicii systemd (Recomandat)
De ce systemd este abordarea corectă pentru producție
systemd nu este pur și simplu un înlocuitor pentru SysVinit — este un manager complet de sistem și sesiune care oferă rezolvarea dependențelor, pornire paralelă, activare prin socket și D-Bus, generarea serviciilor la cerere, supravegherea proceselor cu repornire automată, izolarea resurselor bazată pe cgroup și agregarea jurnalelor structurate prin journald. Pentru orice sarcină de lucru care rulează pe un Server Dedicat sau VPS de producție, unitățile systemd sunt singurul mecanism adecvat pentru gestionarea scripturilor încărcate automat.
Anatomia unui fișier de unitate systemd
Un fișier de unitate .service este împărțit în trei secțiuni obligatorii:
[Unit]: Metadate, descriere lizibilă de om și declarații de dependențe (After=,Requires=,Wants=).[Service]: Parametri de execuție — binarul sau scriptul de rulat, tipul serviciului, politica de repornire, variabilele de mediu și opțiunile de sandboxing de securitate.[Install]: Definește care țintă systemd activează această unitate (WantedBy=multi-user.targeteste standardul pentru daemonii de server).
Implementare pas cu pas
Pasul 1: Pregătiți scriptul
Asigurați-vă că scriptul este executabil și se află într-o cale stabilă:
sudo cp examplescript.sh /usr/local/bin/examplescript.sh
sudo chmod +x /usr/local/bin/examplescript.shPasul 2: Creați fișierul de unitate
sudo nano /etc/systemd/system/examplescript.serviceUn fișier de unitate de nivel producție cu întărire de securitate:
[Unit]
Description=Example Autoload Script
Documentation=https://your-internal-wiki/examplescript
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStart=/usr/local/bin/examplescript.sh
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
RestartSec=5s
StandardOutput=journal
StandardError=journal
SyslogIdentifier=examplescript
User=nobody
Group=nogroup
NoNewPrivileges=true
ProtectSystem=strict
PrivateTmp=true
[Install]
WantedBy=multi-user.targetPasul 3: Reîncărcați daemonul systemd
După crearea sau modificarea oricărui fișier de unitate, trebuie să reîncărcați indexul de configurare al daemonului:
sudo systemctl daemon-reloadPasul 4: Activați serviciul pentru pornire automată
sudo systemctl enable examplescript.serviceAceasta creează o legătură simbolică în /etc/systemd/system/multi-user.target.wants/ care indică spre fișierul dvs. de unitate.
Pasul 5: Porniți serviciul imediat
sudo systemctl start examplescript.servicePasul 6: Verificați starea și jurnalele
sudo systemctl status examplescript.service
sudo journalctl -u examplescript.service -fÎnțelegerea tipurilor de servicii systemd
Directiva Type= din secțiunea [Service] este unul dintre cei mai neînțeleși parametri. Alegerea tipului greșit determină systemd să raporteze incorect disponibilitatea serviciului, ducând la eșecuri de dependențe.
| Tip | Comportament | Caz de utilizare |
|---|---|---|
simple | Procesul pornit de ExecStart este procesul principal. Systemd îl consideră gata imediat. | Scripturi și daemoni simpli care nu bifurcă |
forking | Procesul bifurcă și părintele iese. Systemd urmărește copilul prin fișierul PID. | Daemoni Unix tradiționali (ex., Apache cu PidFile) |
oneshot | Procesul rulează până la finalizare și iese. Systemd așteaptă înainte de a porni unitățile dependente. | Sarcini de inițializare unice, scripturi de configurare |
notify | Procesul semnalează disponibilitatea prin sd_notify(). | Daemoni cu integrare nativă systemd |
idle | Execuția este amânată până când toate joburile active sunt distribuite. | Sarcini de fundal cu prioritate scăzută |
Pentru un script care rulează o singură dată la pornire și iese, utilizați Type=oneshot cu RemainAfterExit=yes pentru a menține unitatea în stare „activă” după finalizarea scriptului.
Avansat: Ordonarea dependențelor cu After= și Wants=
Un eșec frecvent în producție apare când un script care necesită conectivitate la rețea pornește înainte ca stiva de rețea să fie complet inițializată. Lanțul corect de dependențe pentru scripturile dependente de rețea este:
After=network-online.target
Wants=network-online.targetAceasta este diferit de After=network.target, care garantează doar că interfețele de rețea au fost configurate — nu că sunt efectiv online și accesibile. Dependența network-online.target necesită ca systemd-networkd-wait-online.service sau echivalentul să confirme conectivitatea.
Comparație: Toate cele trei metode dintr-o privire
| Caracteristică | /etc/init.d/ | /etc/rc.local | Unitate systemd |
|---|---|---|---|
| Recomandat pentru producție | Nu | Nu | Da |
| Suport pentru pornire paralelă | Nu | Nu | Da |
| Supraveghere procese / repornire automată | Nu | Nu | Da |
| Gestionarea dependențelor | Limitată (anteturi LSB) | Niciuna | Completă |
| Jurnalizare structurată | Nu | Nu | Da (journald) |
| Sandboxing de securitate | Nu | Nu | Da |
| Complexitate | Scăzută | Foarte scăzută | Medie |
| Suportat pe Ubuntu 22.04+ | Prin nivel de compatibilitate | Prin rc-local.service | Nativ |
| Potrivit pentru daemoni cu rulare îndelungată | Parțial | Nu | Da |
| Potrivit pentru sarcini de inițializare unice | Da | Da | Da (oneshot) |
Greșeli frecvente și cum să le evitați
Rularea scripturilor ca root în mod inutil. Directivele User= și Group= din fișierele de unitate systemd vă permit să renunțați la privilegii. Un script care trebuie doar să scrie în /var/log/myapp/ nu are nevoie de root — creați un utilizator de sistem dedicat și atribuiți proprietatea directorului în consecință.
Neredirecționarea ieșirii în rc.local. Fără redirecționarea ieșirii, orice ieșire echo sau erori din comenzile rc.local ajung la consola sistemului și se pierd. Adăugați întotdeauna >> /var/log/yourscript.log 2>&1.
Utilizarea inconsistentă a căilor absolute. Serviciile systemd rulează într-un mediu minimal fără PATH al utilizatorului. Utilizați întotdeauna căi absolute pentru fiecare binar referențiat în ExecStart, inclusiv interpreți precum /usr/bin/python3 sau /bin/bash.
Uitarea daemon-reload după editarea fișierelor de unitate. systemd memorează în cache conținutul fișierelor de unitate. Dacă editați un fișier .service și nu rulați sudo systemctl daemon-reload, systemd va continua să folosească configurația veche.
Plasarea fișierelor de unitate în /lib/systemd/system/ pentru scripturi personalizate. Directorul /lib/systemd/system/ este gestionat de managerul de pachete. Fișierele de unitate personalizate aparțin în /etc/systemd/system/, care are prioritate și supraviețuiește actualizărilor de pachete.
Matrice de decizie practică: Ce metodă să utilizați
Utilizați acest cadru pentru a selecta metoda adecvată pentru scenariul dvs. specific:
- Daemon cu rulare îndelungată care trebuie repornit la eșec — unitate systemd cu
Restart=on-failure - Script de configurare unic care trebuie să se finalizeze înainte de pornirea altor servicii — unitate systemd cu
Type=oneshotși dependențeBefore= - Script care necesită ca rețeaua să fie complet online — unitate systemd cu
After=network-online.target - Comandă rapidă pentru testare sau prototipare —
/etc/rc.local(temporar) - Aplicație moștenită livrată cu un script de inițializare LSB —
/etc/init.d/cuupdate-rc.d - Orice rulează în producție — systemd, întotdeauna
Pentru administratorii care gestionează mai multe servere Ubuntu, luați în considerare asocierea gestionării unităților systemd cu instrumente de gestionare a configurației precum Ansible, care poate implementa și activa fișiere .service idempotent pe întreaga dvs. flotă. Dacă aveți nevoie de un mediu gestionat cu acces root complet pentru a implementa aceste configurații, VPS Hosting cu un Panou de Control VPS oferă flexibilitatea de a gestiona serviciile systemd direct fără restricții.
Pentru echipele care rulează sarcini de lucru intensive în resurse care necesită scripturi de pornire pentru a inițializa drivere GPU, medii CUDA sau servere de inferență ML, mediile de GPU Hosting beneficiază în mod deosebit de lanțurile de dependențe After= ale systemd, asigurând că driverele sunt complet încărcate înainte ca serviciile aplicației să încerce să se lege la resursele hardware.
Dacă scripturile dvs. încărcate automat interacționează cu configurații de server web sau rutine de inițializare a bazelor de date legate de un mediu de panou de control, instalările de VPS cu cPanel necesită atenție suplimentară — cPanel gestionează propriul nivel de supraveghere a serviciilor, iar unitățile systemd personalizate trebuie definite pentru a evita conflictele cu hook-urile de gestionare a serviciilor cPanel.
Listă de verificare tehnică a punctelor cheie
Înainte de a implementa orice script de pornire pe un server Ubuntu, verificați următoarele:
- Locația fișierului de unitate: Scripturile personalizate merg în
/etc/systemd/system/, nu în/lib/systemd/system/ - Bitul executabil: Confirmați cu
ls -la /path/to/script.sh— bitulxtrebuie setat - Căi absolute: Fiecare binar din
ExecStartfolosește o cale completă; fără dependență de$PATH - Declarații de dependențe:
After=network-online.targetpentru orice script dependent de rețea - Tipul serviciului:
Type=simplepentru daemoni persistenți,Type=oneshotpentru scripturi care rulează și ies - Minimizarea privilegiilor:
User=,Group=,NoNewPrivileges=true,ProtectSystem=strict - Jurnalizare configurată:
StandardOutput=journalșiStandardError=journalpentru integrareajournald - daemon-reload executat: Rulați întotdeauna
sudo systemctl daemon-reloaddupă crearea sau editarea fișierelor de unitate - Enable vs. start:
enablecreează legătura simbolică de pornire automată;startîl rulează imediat — ambele sunt necesare - Testat cu
journalctl: Confirmați execuția reușită cusudo journalctl -u yourservice.service --since "5 minutes ago"
Întrebări frecvente
Care este diferența dintre systemctl enable și systemctl start?
systemctl enable creează o legătură simbolică care determină serviciul să pornească automat la următoarea repornire. systemctl start pornește serviciul imediat în sesiunea curentă. De obicei aveți nevoie de ambele comenzi când configurați un serviciu nou pentru prima dată.
De ce serviciul meu systemd eșuează cu „executable not found” chiar dacă scriptul există?
Aceasta înseamnă aproape întotdeauna că calea ExecStart este incorectă sau scriptului îi lipsește bitul executabil. Verificați cu which yourscript și ls -la /path/to/script. Confirmați de asemenea că prima linie a scriptului dvs. este un shebang valid (#!/bin/bash sau #!/usr/bin/env python3), deoarece systemd nu invocă implicit un shell pentru ExecStart.
Pot rula un script la pornire o singură dată, nu la fiecare repornire?
Utilizați Type=oneshot cu o directivă ConditionPathExists=!/var/run/myscript.done în secțiunea [Unit]. Scriptul creează fișierul santinelă la prima rulare; repornirile ulterioare sar execuția deoarece condiția eșuează.
Este /etc/rc.local încă suportat pe Ubuntu 22.04?
Da, dar este dezactivat implicit. Trebuie să activați manual unitatea rc-local.service cu sudo systemctl enable rc-local și să vă asigurați că fișierul există și este executabil. Este suportat ca măsură de compatibilitate, nu ca practică recomandată.
Cum verific de ce un script de pornire nu a reușit să ruleze?
Rulați sudo journalctl -u yourservice.service -b pentru a vizualiza toate intrările de jurnal pentru acea unitate de la ultima repornire. Pentru eșecuri rc.local, verificați sudo systemctl status rc-local.service și examinați /var/log/syslog pentru intrări marcate cu timestamp în timpul secvenței de pornire.
