Come posso spegnere un server Linux dopo averlo eseguito per 60 minuti?


18

Ho un server che è normalmente spento per motivi di sicurezza. Quando voglio lavorarci su, lo accendo, eseguo i miei compiti e lo spengo di nuovo. Le mie attività di solito non richiedono più di 15 minuti. Vorrei implementare un meccanismo per spegnerlo automaticamente dopo 60 minuti.

Ho studiato come farlo con cron, ma non credo sia il modo corretto perché cron non tiene conto dell'ultima accensione del server. Posso solo impostare schemi periodici, ma non tengono conto di quei dati.

Come potrei fare questa implementazione?


4
Dai un'occhiata a at(esecuzione singola).
Dirkt

14
Non l'ho fatto, ma il tuo script di accesso potrebbe iniziare un sudo shutdown -h +60che avvierebbe un conto alla rovescia di 60 minuti per il processo di spegnimento (-halt). Se volessi cancellarlo, potresti sudo shutdown -c (anche se non usa cron)
guiverc

7
A seconda della natura delle tue attività, forse vale la pena eseguirle all'interno di un contenitore docker, quindi non devi preoccuparti di spegnere un server. Il contenitore viene creato, esegue le attività e successivamente viene distrutto.
Vicente Olivert Riera,

6
Non aspettarti alcun reale vantaggio in termini di sicurezza da questo. La maggior parte delle vulnerabilità può essere sfruttata in meno di un secondo, quindi lo spegnimento dopo un'ora non impedisce lo sfruttamento. E un utente malintenzionato che ha trovato una vulnerabilità può attendere che tu accenda la macchina per eseguire l'attacco.
Kasperd,

2
Ri: il commento di @kasperd, lo riformulo dicendo che hai bisogno esattamente della stessa quantità di sicurezza sul tuo server, indipendentemente da quanto o meno sia effettivamente online. Nota, è un server, quindi si connette a qualcosa e ciò significa che qualcosa saprà quando è acceso: gli sweep automatici non sono ciò di cui ti preoccupi, sono connessioni di qualsiasi tipo e non puoi evitare che la massima sicurezza sia sempre l'unico modo.
StephenG

Risposte:


23

Se esegui le tue attività come lo stesso utente ogni volta, puoi semplicemente aggiungere il comando shutdown, facoltativamente con l'opzione -P, al tuo profilo. Il numero indica la quantità di minuti di ritardo del comando di arresto. Assicurati che il tuo utente abbia la possibilità di eseguire il comando di spegnimento tramite sudo senza password.

echo "sudo shutdown -P +60" >> ~/.profile

11
Il tempo è in minuti, non secondi. Prova shutdown -k -P 3600vs shutdown -k -P 60( -kstampa un messaggio a muro ma non ha altri effetti)
sebasth,

12
Ma prova prima il comando una volta, non vuoi che un arresto istantaneo sia associato al tuo profilo!
Fabian Röling,

17
Immagino che ogni login ssh provocherebbe una nuova chiamata di spegnimento. Il contatore si ripristinerebbe allora?
JoL

4
Potrebbe anche valere la pena ricordare che gli accessi non saranno consentiti negli ultimi 5 minuti, come menzionato nella manpage di spegnimento.
JoL

6
Si noti che 60 minuti dopo l'accesso non corrispondono a 60 minuti dopo l'avvio. Cosa succede se si avvia la macchina e poi si dimentica di accedere?
Hagen von Eitzen,

69

Esistono diverse opzioni.

  • Fornire tempo direttamente a shutdown -P:

    shutdown -P +60
    

    Nota che la shutdown pagina man sottolinea anche:

    Se viene utilizzato l'argomento time, 5 minuti prima che il sistema si blocchi, viene creato il file / run / nologin per garantire che non siano consentiti ulteriori accessi.

  • Usa il atcomando.

  • Creare un file di unità di sistema o uno script init che viene eseguito shutdown -P 60all'avvio.

  • Usa cron's @rebootper eseguire il comando dopo l'avvio.

    Aggiungi a (root) crontab:

    @reboot shutdown -P +60
    

Per gli ultimi due metodi, è possibile utilizzare sleep 3600 && shutdown -P nowinvece di utilizzare l'argomento time shutdownper ritardare l'arresto di 60 minuti. In questo modo è possibile accedere all'ultimo momento prima dell'arresto.


2
Penso che con il sleepcomando, devi ancora specificare un tempo per shutdown- vorremmo usare nowper quell'argomento se abbiamo già fatto l'attesa (ma nota che non riceverai molti avvisi per salvare il tuo lavoro prima di esso scompare da sotto di te!).
Toby Speight,

1
Sebbene shutdown -P 60funzioni, non è il modo in cui il comando deve essere invocato. Secondo la pagina man che dovresti usare shutdown -P +60. --- Anche l'arresto senza un argomento temporale (nell'esempio sleep 3600 && shutdown -P) verrà ritardato di un minuto (come shutdown -P +1). Come ha scritto Toby Speight probabilmente vorrai usarlo shutdown -P now.
pabouk,

34

Sembra un problema XY .

Le mie attività non richiedono in genere più di 15 minuti. Vorrei implementare un meccanismo per spegnerlo automaticamente dopo 60 minuti.

Se si arresta dopo 60 minuti, si corre il rischio che si stia verificando un problema particolarmente complicato e che sia necessario solo più tempo. Molte delle soluzioni precedenti non renderebbero facile ritardare l'arresto.

Se l'attività non è un'attività interattiva, ma invece è un'attività con script che viene automaticamente attivata da un'altra macchina, @sdkks ha fornito un'ottima soluzione per quello; dovresti semplicemente incaricare la macchina di eseguire lo spegnimento non appena lo script e tutte le sue attività finiscono.

Tuttavia, se l'attività è un'attività interattiva, suggerirei invece di eseguire il rilevamento inattivo.

Se si esegue la propria attività in una GUI (X11), è possibile rilevare le sessioni della GUI inattiva utilizzando l'approccio descritto qui: Eseguire un comando quando il sistema è inattivo e quando è di nuovo attivo

Se si esegue l'attività tramite un terminale, è possibile rilevare gli utenti che hanno effettuato l'accesso utilizzando il whocomando. È possibile impostare un cronjob che spegne la macchina se whorestituisce un risultato vuoto. Si noti che questo sarà un approccio piuttosto conservativo; non spegnerà il sistema se hai lasciato la console collegata, ma inattiva.

Se vuoi essere un po 'più aggressivo e disconnettere anche le sessioni terminali inattive, puoi combinare l'approccio precedente con la disconnessione automatica delle sessioni SSH inattive ClientAliveInterval e ClientAliveCountMax. Un altro approccio per questo se non si dispone di SSH, ma si dispone di una sessione terminale locale, consiste nell'utilizzare il tempo di inattività del terminale restituito dal wcomando.


2
Questo è un punto molto importante. Qualunque cosa tu attui, è nel tuo interesse assicurarti di poter anche annullare lo spegnimento.
Ombra

1
Qualcosa è andato storto se continua a funzionare a 60m, quindi forse ricominciare da capo. Questo può essere molto costoso dal punto di vista del cloud. Non assicurare un arresto in un'occasione mi ha fatto tornare indietro di oltre $ 4.000.
mckenzm,

8

Sebbene le risposte precedenti qui soddisfino tutti i requisiti di perfezione, puoi anche spegnere la macchina non appena le attività sono state completate.

bashgli script possono essere trapped, il che significa che alcuni segnali possono essere intercettati e determinati compiti possono essere eseguiti quando necessario. EXITè uno dei segnali che possono essere intrappolati.

Saresti in grado di:

  1. Imposta un trapfor per i EXITtuoi script di shell automatizzati, che significa terminare le tue attività automatizzate
  2. Imposta un valore trapper .bashrc EXIT, ovvero ogni volta che esci da quella macchina, spegnilo.

L'opzione n. 1 sarebbe il caso ideale, a condizione che i tuoi compiti non richiedano ispezioni ad hoc e giudizio manuale.

L'opzione n. 2 riguarderebbe i casi in cui ti dimenticheresti di uscire dal terminale senza spegnerlo. C'è un avvertimento però; se si hanno più terminali sulla stessa macchina aperti e si esce da uno di essi, la macchina si spegnerà comunque. (Può essere scritto per evitarlo, ma non complicherò la soluzione.)

cleanup(){
    # Do some tasks before terminating
    echo oh la la, cleaning is so nice
    echo "See you later, world"
    sudo poweroff & # finally shutdown
}
trap cleanup EXIT

Questo può essere alla fine .bashrcdell'opzione n. 2, da qualche parte nella parte superiore dello script per l'opzione n. 1.

Perché non usare poweroffalla fine dello script?

Preferisco usare set -eo pipefailin cima ai miei script. Se si verifica un errore, non fallirà silenziosamente; smetterà di eseguire più comandi. trapdi EXITsegnale dovrebbe coprire i casi in cui lo script termina prematuramente a causa di errori.

Tuttavia, per le tue attività, ciò potrebbe anche significare che la macchina si spegnerà prima che siano completate.

Ho un semplice bashmodello che uso per rendere più semplice il debug degli script; forse potrebbe essere di qualche utilità. Si prega di vedere questo riassunto .


D'accordo, e per essere sicuro forse un momento della giornata spegnimento da cron. Questo è il freno di un uomo morto.
mckenzm,

@Abigail per lo script, deve essere sopra, perché .bashrcpreferirei il fondo nel caso in cui qualcos'altro lo sovrascriva. La tua preoccupazione non sembra chiara, puoi forse condividere uno snippet di esempio su repl.it?
sdkks,

@mckenzm non capisco. Puoi condividere il codice di esempio o ulteriori spiegazioni?
sdkks,

5

Sviluppando commento @dirkt, è possibile inserire un atcomando sul .bashrco .profileo qualsiasi altro file di vostri usi shell su login per programmare lo spegnimento automatico dopo 60 minuti i dati di accesso.

Qualcosa di simile a:

at now + 60 minutes -f /sbin/halt

Questo compito è proprio nel atvicolo. Puoi anche vedere le atattività in/var/spool/
sdkks

5
Vorrei sconsigliare l'utilizzo atin questo contesto perché sopravvive ai riavvii. Se OP dovesse accedere, arrestare manualmente e quindi riconnettersi nel giro di un'ora, si darebbe il calcio d'inizio prima che passasse un'ora dopo il suo ultimo accesso quando il primo processo di spegnimento programmato.
Aaron,

@Aaron è vero. Non ci ho pensato. La persistenza di avvio è un avvertimento per questa soluzione.
sdkks,

5

Quanto segue viene eseguito commandcon parametri e, se si completa correttamente, disattiverà immediatamente la casella, presupponendo che l'utente possa eseguirlo poweroff. Potrebbe essere necessario utilizzare sudo poweroff.

command --parameters && poweroff

Considerando che il seguente semplicemente viene eseguito poweroffimmediatamente al termine del comando:

command --parameters ; poweroff

Se ritieni che il comando abbia bisogno di tempo di riposo dopo il completamento, esegui

command --parameters ; sleep 3600 ; poweroff

Se ritieni che il comando possa essere eseguito straordinariamente, puoi vincolarlo a un'ora:

timeout 1h command --parameters ; poweroff

timeoutfa parte del coreutilspacchetto, quindi probabilmente lo hai già.


3

Se sei davvero preoccupato per la sicurezza, usa un timer per presa meccanica sulla fonte di alimentazione. Basta impostarlo su ogni volta che vuoi che si spenga. In questo modo nessuno può accedere in remoto e disabilitare lo spegnimento. Avresti bisogno di un accesso fisico.


2
Corruzione del filesystem?
Xen2050,

@ Xen2050 non è un problema su nessun file system moderno (journaling).
Tom,

1
@Tom Hai una fonte per umounts forzati che non causeranno mai corruzione del filesystem se c'è journaling? Mi sembra nuovo, mi piacerebbe leggerlo. Almeno deve contrassegnare il filesystem come sporco, forzando un fsck giusto?
Xen2050,

1
Nella maggior parte dei casi, dovrebbe semplicemente riprodurre nuovamente il diario e completarlo. Un powerdown non dovrebbe causare la corruzione del filesystem su un filesystem journaled, sebbene non vi siano garanzie a meno che non si usi un filesystem come ZFS che è specificamente progettato per questo caso.
Tom,

1
La ripetizione del diario può fallire - ho avuto una sessione fsck molto difficile un paio di settimane fa dopo un'interruzione di corrente di ½ secondo su una macchina senza UPS. Quello stava usando ext4 con un giornale; non è completamente invincibile!
Toby Speight,

2

Se sei in una systemdmacchina, puoi usare un timer monotonico

L'unità timer /etc/systemd/system/shutdown_after_an_hour.timer

[Unit]
Description=shutdown after an hour

[Timer]
OnBootSec=1h

[Install]
WantedBy=timers.target

L'unità timer /etc/systemd/system/shutdown_after_an_hour.service:

[Unit]
Description=shutdown after an hour

[Service]
ExecStart=/sbin/poweroff --force --no-wall
Type=oneshot

È abilitato tramite

# systemctl enable shutdown_after_an_hour.timer

Il suo stato (in particolare quanto tempo rimane prima dell'arresto) è disponibile tramite

# systemctl list-timers shutdown_after_an_hour.timer

Funzionerà al prossimo riavvio, non è utile systemctl startdurante la sessione quando viene creato in quanto non funzionerà (perché non è stato attivato durante il riavvio) o spegne immediatamente la macchina se trascorsa un'ora. Non so quale accadrà di fatto, non ho mai testato quel caso specifico.


1

Prova a mettere lo script ( sudo shutdown -P 3600) nella /etc/init.ddirectory per eseguirlo automaticamente all'avvio.

Oppure prova a utilizzare anacron, aggiungendo il comando nel /etc/anacrontabfile. Suggerisco anche di utilizzare nohupdavanti al comando per essere sicuro che il comando funzioni ancora dopo il logout.


1
A seconda della distribuzione, potrebbe non essere eseguito semplicemente in init.d
sdkks il

@sdkks, hai ragione. Anacron può anche essere considerato. inserendo lo script in / etc / anacrontab, usato anche con 'nohup' in caso di disconnessione.
Saveriofr

1
@Saveriofr Puoi modificare la tua risposta per migliorarne la qualità (meglio che pubblicare informazioni aggiuntive come commento).
Anthony G - giustizia per Monica,

1

Sfrutta il file di logout di Shell

Se hai solo bisogno del server per attività interattive o non interattive avviate dal tuo UID, considera di inserire i tuoi comandi di arresto nel tuo file ~ / .bash_logout . Il Manuale GNU Bash dice:

Quando una shell di accesso interattiva viene chiusa o una shell di accesso non interattiva esegue il comando di uscita incorporato, Bash legge ed esegue i comandi dal file ~ / .bash_logout, se esiste.

Pertanto, l'aggiunta di "sudo poweroff" o simile al file di disconnessione spegne il server non appena si disconnette la sessione corrente o quando viene chiamata una sessione Bash non interattiva exit. Si potrebbe anche scegliere di utilizzare in o passare un tempo di ritardo per l'arresto se si preferisce rinviare l'arresto.

Per un approccio più interattivo a questo, potresti inserire i seguenti Bashism nel tuo file di logout:

# Shutdown unless N or n is pressed within 30 seconds.
shopt -s nocasematch
read -t 30 -N 1 -p 'Shutdown now? (Y/n) '
[[ "$REPLY" =~ n ]] || sudo poweroff

Avvertenze

Ci sono alcuni avvertimenti che dovresti tenere a mente su questa soluzione:

  • Questo probabilmente funzionerà anche con un terminale avviato da X Windows, ma probabilmente non funzionerebbe per una sessione X11 che non è stata avviata startxo simile.
  • Se si dispone di script non interattivi che chiamano exit, è possibile che si verifichino arresti non previsti.
  • Il file sudoers potrebbe richiedere una password se non è stato specificato NOPASSWDper i comandi di arresto o se non è stato chiamato sudo -vprima di eseguire il comando di arresto.
  • Probabilmente ci sono altri casi limite a cui non ho ancora pensato.

In breve, potresti voler considerare se questo approccio soddisfa le tue reali esigenze o se un approccio completamente diverso come il monitoraggio dell'assenza di utenti che hanno effettuato l'accesso o qualche altra alternativa è una scommessa migliore. Il tuo chilometraggio varierà sicuramente.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.