Comment puis-je arrêter un serveur Linux après avoir exécuté pendant 60 minutes?

18

J'ai un serveur qui est normalement éteint pour des raisons de sécurité. Lorsque je veux y travailler, je l'allume, j'exécute mes tâches et je l'arrête à nouveau. Mes tâches ne prennent généralement pas plus de 15 minutes. Je voudrais mettre en place un mécanisme pour l'arrêter automatiquement après 60 minutes.

J'ai recherché comment faire cela avec cron, mais je ne pense pas que ce soit la bonne façon car cron ne tient pas compte de la dernière mise sous tension du serveur. Je ne peux que définir des modèles périodiques, mais ils ne prennent pas en compte ces données.

Comment pourrais-je faire cette implémentation?

jmhostalet
la source
4
Jetez un œil à at(exécution unique).
dirkt
14
Je ne l'ai pas fait, mais votre script de connexion pourrait démarrer un sudo shutdown -h +60qui lancerait un compte à rebours de 60 minutes pour le processus d'arrêt (-halt). Si vous vouliez l'annuler, vous pourriez sudo shutdown -c (cela n'utilise pas cron cependant)
guiverc
7
Selon la nature de vos tâches, il peut être utile de les exécuter dans un conteneur Docker, vous n'avez donc pas à vous soucier de désactiver un serveur. Le conteneur est créé, il exécute vos tâches et il est détruit après cela.
Vicente Olivert Riera
6
Ne vous attendez pas à un réel avantage en termes de sécurité. La plupart des vulnérabilités peuvent être exploitées en moins d'une seconde, donc la mise hors tension après une heure ne va pas empêcher l'exploitation. Et un attaquant qui a trouvé une vulnérabilité peut attendre que vous allumiez la machine pour effectuer l'attaque.
kasperd du
2
Re: commentaire de @kasperd, je reformulerais comme disant que vous avez besoin exactement de la même quantité de sécurité sur votre serveur, peu importe combien ou peu il est réellement en ligne. Remarque, c'est un serveur donc il est connecté à quelque chose et cela signifie que quelque chose saura quand il est allumé - les balayages automatisés ne sont pas ce dont vous vous inquiétez, ce sont des connexions de toute sorte et vous ne pouvez pas éviter cela, donc la sécurité maximale est tout le temps la seule manière.
StephenG

Réponses:

23

Si vous exécutez vos tâches en tant que même utilisateur à chaque fois, vous pouvez simplement ajouter la commande d'arrêt, éventuellement avec l'option -P, à votre profil. Le nombre représente le nombre de minutes pendant lesquelles la commande d'arrêt est retardée. Assurez-vous que votre utilisateur a la possibilité d'exécuter la commande d'arrêt via sudo sans mot de passe.

echo "sudo shutdown -P +60" >> ~/.profile
Dirk Krijgsman
la source
11
Le temps est en minutes, pas en secondes. Try shutdown -k -P 3600vs shutdown -k -P 60( -kimprime le message mural mais n'a pas d'autre effet)
sebasth
12
Mais essayez la commande une première fois, vous ne voulez pas qu'un arrêt instantané soit lié à votre profil!
Fabian Röling
17
J'imagine que chaque connexion ssh entraînerait un nouvel appel d'arrêt. Le compteur se réinitialiserait-il alors?
JoL
4
Il peut également être utile de mentionner que les connexions ne seront pas autorisées au cours des 5 dernières minutes, comme indiqué dans la page de manuel d'arrêt.
JoL
6
Notez que 60 minutes après la connexion ne sont pas les mêmes que 60 minutes après le démarrage. Que faire si vous démarrez la machine et oubliez ensuite de vous connecter?
Hagen von Eitzen
69

Il existe plusieurs options.

  • Donnez du temps directement à shutdown -P:

    shutdown -P +60
    

    Notez que la shutdown page de manuel indique également:

    Si l'argument time est utilisé, 5 minutes avant la fermeture du système, le fichier / run / nologin est créé pour garantir qu'aucune connexion supplémentaire ne sera autorisée.

  • Utilisation at commande.

  • Créez un fichier d'unité systemd ou un script d'initialisation qui s'exécute shutdown -P 60au démarrage.

  • Utilisez cron @reboot pour exécuter la commande après le démarrage.

    Ajouter à (root) crontab:

    @reboot shutdown -P +60
    

Pour les deux dernières méthodes, vous pouvez également utiliser sleep 3600 && shutdown -P nowau lieu d'utiliser l'argument time shutdownpour retarder l'arrêt de 60 minutes. De cette façon, les connexions sont possibles jusqu'au dernier moment avant l'arrêt.

sebasth
la source
2
Je pense qu'avec la sleepcommande, vous devez toujours spécifier une heure pour shutdown- nous voudrions utiliser nowpour cet argument si nous avons déjà fait l'attente (mais notez que vous n'obtiendrez pas beaucoup d'avertissement pour enregistrer votre travail avant disparaît sous vous!).
Toby Speight
1
Bien que shutdown -P 60cela fonctionne, ce n'est pas la façon dont la commande doit être invoquée. Selon la page de manuel que vous devez utiliser shutdown -P +60. --- L'arrêt sans argument temporel (dans l'exemple sleep 3600 && shutdown -P) sera également retardé d'une minute (comme shutdown -P +1). Comme Toby Speight l'a écrit, vous voudrez probablement l'utiliser shutdown -P now.
pabouk
33

Cela ressemble à un problème XY .

Mes tâches ne prennent généralement pas plus de 15 minutes. Je voudrais mettre en place un mécanisme pour l'arrêter automatiquement après 60 minutes.

Si vous arrêtez après 60 minutes, vous courez le risque de rencontrer un problème particulièrement compliqué et de simplement avoir plus de temps. La plupart des solutions précédentes ne permettraient pas de retarder facilement l'arrêt.

Si la tâche n'est pas une tâche interactive, mais plutôt une tâche scriptée qui est automatiquement déclenchée à partir d'une autre machine, @sdkks a donné une excellente solution pour cela; vous devriez vraiment demander à la machine d'exécuter la mise hors tension dès que le script et toutes ses tâches se terminent.

Cependant, si votre tâche est une tâche interactive, je vous suggère de faire une détection d'inactivité à la place.

Si vous effectuez votre tâche dans une interface graphique (X11), vous pouvez détecter les sessions GUI inactives en utilisant l'approche décrite ici: Exécutez une commande lorsque le système est inactif et lorsqu'il est à nouveau actif

Si vous effectuez la tâche via un terminal, vous pouvez détecter les utilisateurs connectés à l'aide de la whocommande. Vous pouvez configurer un cronjob qui arrête la machine s'il whorenvoie un résultat vide. Notez que ce sera une approche assez conservatrice; il n'arrêtera pas le système si vous avez laissé la console connectée, mais inactif.

Si vous voulez être un peu plus agressif et déconnecter également les sessions de terminal inactives, vous pouvez combiner l'approche précédente avec la déconnexion automatique des sessions SSH inactives ClientAliveInterval et ClientAliveCountMax. Si vous n'avez pas SSH, mais avez une session de terminal locale, une autre approche consiste à utiliser le temps d' inactivité du terminal tel que renvoyé par la wcommande.

Lie Ryan
la source
2
C'est un point très important. Quoi que vous mettiez en œuvre, il est dans votre intérêt de vous assurer que vous pouvez également annuler l'arrêt.
Shadow
1
Quelque chose a mal tourné s'il tourne toujours à 60 mètres, alors recommencez peut-être. Cela peut être très coûteux dans le cloud. Ne pas assurer un arrêt à une occasion m'a fait perdre plus de 4 000 $.
mckenzm
8

Bien que les réponses précédentes ici satisfassent toutes à la perfection, vous pouvez également mettre votre machine hors tension dès que les tâches sont terminées.

bashles scripts peuvent être trapped, ce qui signifie que certains signaux peuvent être interceptés et certaines tâches peuvent être exécutées en cas de besoin. EXITest l'un des signaux qui peuvent être piégés.

Vous pourrez:

  1. Définissez un trappour EXITvos scripts shell automatisés, ce qui signifie la fin de vos tâches automatisées
  2. Définissez un trappour votre .bashrc EXIT, ce qui signifie que lorsque vous vous déconnectez de cette machine, éteignez-le.

L'option n ° 1 serait le cas idéal, à condition que vos tâches ne nécessitent pas d'inspection ad hoc et de jugement manuel.

L'option # 2 couvrirait les cas où vous oublieriez de quitter le terminal sans éteindre. Il y a cependant une mise en garde; si vous avez plusieurs terminaux ouverts sur la même machine et que vous sortez de l'un d'eux, il éteindra tout de même la machine. (Il peut être scripté pour éviter cela, mais je ne compliquerai pas la solution.)

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

Cela peut être à la fin de l' .bashrcoption # 2, quelque part en haut de votre script pour l'option # 1.

Pourquoi ne pas utiliser poweroffà la fin du script?

Je préfère utiliser set -eo pipefailen haut de mes scripts. Si une erreur se produit, elle n'échouera pas en silence; il cessera d'exécuter plus de commandes. trapde EXITsignal doit couvrir les cas où le script se termine prématurément en raison d'erreurs.

Cependant, pour vos tâches, cela peut également signifier que la machine s'arrêtera avant d'être terminée.

J'ai un bashmodèle simple que j'utilise pour faciliter le débogage des scripts; cela pourrait peut-être être utile. S'il vous plaît voir cet essentiel .

sdkks
la source
D'accord, et pour être sûr, peut-être une heure de fermeture de cron. C'est le frein d'un mort.
mckenzm
@Abigail pour le script, il doit être au-dessus, car .bashrcje préférerais le bas au cas où quelque chose d'autre le remplacerait. Votre préoccupation ne semble pas claire, pouvez-vous partager un exemple d'extrait sur repl.it peut-être?
sdkks
@mckenzm je ne comprends pas. Pouvez-vous partager un exemple de code ou plus d'explications?
sdkks
5

En élaborant sur le commentaire @dirkt, vous pouvez insérer une atcommande sur votre .bashrcou.profile ou tout autre fichier votre shell utilise sur connexion pour programmer un arrêt automatique 60 minutes après votre connexion.

Quelque chose comme:

at now + 60 minutes -f /sbin/halt
M. Shunz
la source
Cette tâche est à vous at. Vous pouvez également voir les attâches dans/var/spool/
sdkks
5
Je déconseille de l'utiliser atdans ce contexte car il survit aux redémarrages. Si OP devait se connecter, s'arrêter manuellement, puis se reconnecter en l'espace d'une heure, il serait expulsé avant qu'une heure ne se soit écoulée après sa dernière connexion lors du premier processus d'arrêt programmé.
Aaron
@Aaron c'est vrai. Je n'y ai pas pensé. La persistance du démarrage est une mise en garde pour cette solution.
sdkks
5

Ce qui suit s'exécute commandavec des paramètres et s'il se termine avec succès, il désactivera la boîte immédiatement, en supposant que l'utilisateur peut s'exécuter poweroff. Il peut être nécessaire de l'utiliser sudo poweroff.

command --parameters && poweroff

Alors que le suivant s'exécute simplement poweroffimmédiatement à la fin de la commande:

command --parameters ; poweroff

Si vous pensez que la commande a besoin de repos après exécution, exécutez

command --parameters ; sleep 3600 ; poweroff

Si vous pensez que la commande peut s'exécuter en heures supplémentaires, vous pouvez la limiter à une heure:

timeout 1h command --parameters ; poweroff

timeoutfait partie du coreutilspackage, vous l'avez probablement déjà.

Criggie
la source
3

Si vous êtes vraiment préoccupé par la sécurité, utilisez une minuterie de prise mécanique sur la source d'alimentation. Réglez-le simplement à l'heure à laquelle vous souhaitez qu'il s'arrête. De cette façon, personne ne peut se connecter à distance et désactiver l'arrêt. Vous auriez besoin d'un accès physique.

gogators
la source
2
Corruption du système de fichiers?
Xen2050
@ Xen2050 ne pose aucun problème sur aucun système de fichiers moderne (journalisation).
Tom
1
@Tom Avez-vous une source pour les montages forcés ne causera jamais de corruption du système de fichiers s'il y a journalisation? Cela me semble nouveau, j'aimerais le lire. À tout le moins, il doit marquer le système de fichiers comme sale, forçant un fsck à droite?
Xen2050
1
Dans la plupart des cas, il suffit de rejouer le journal et d'en finir. Une mise hors tension ne devrait pas endommager le système de fichiers sur un système de fichiers journalisé, bien qu'il n'y ait aucune garantie à moins que vous n'utilisiez un système de fichiers tel que ZFS qui est spécifiquement conçu pour ce cas.
Tom
1
La relecture du journal peut échouer - J'ai eu une session fsck très difficile il y a quelques semaines à la suite d'une coupure de courant d'une demi-seconde sur une machine sans onduleur. Cela utilisait ext4 avec un journal; ce n'est pas complètement invincible!
Toby Speight
2

Si vous êtes dans une systemdmachine, vous pouvez utiliser une minuterie monotone

L'unité de minuterie /etc/systemd/system/shutdown_after_an_hour.timer

[Unit]
Description=shutdown after an hour

[Timer]
OnBootSec=1h

[Install]
WantedBy=timers.target

L'unité de minuterie /etc/systemd/system/shutdown_after_an_hour.service:

[Unit]
Description=shutdown after an hour

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

Il est activé via

# systemctl enable shutdown_after_an_hour.timer

Son état (en particulier le temps restant avant l'arrêt) est disponible via

# systemctl list-timers shutdown_after_an_hour.timer

Cela fonctionnera au prochain redémarrage, il n'est pas utile de systemctl start lors de la session lors de sa création car il ne fonctionnera pas (car il n'a pas été déclenché lors du redémarrage) ou arrêtera la machine tout de suite si passé une heure. Je ne sais pas lequel se passera en fait, je n'ai jamais testé ce cas spécifique.

WoJ
la source
1

Essayez de mettre le script ( sudo shutdown -P 3600) dans le /etc/init.drépertoire pour l'exécuter automatiquement au démarrage.

Ou essayez d'utiliser anacron, en ajoutant la commande dans le /etc/anacrontabfichier. Je suggère également d'utiliser nohupdevant la commande pour être sûr que la commande fonctionne toujours après la déconnexion.

Saveriofr
la source
1
Selon la distribution, il peut ne pas être exécuté simplement en étant dans init.d
sdkks
@sdkks, vous avez raison. Anacron peut également être envisagé. mettre le script dans / etc / anacrontab, également utilisé avec 'nohup' en cas de déconnexion.
Saveriofr
1
@Saveriofr Vous pouvez modifier votre réponse pour améliorer sa qualité (mieux que de publier des informations supplémentaires en tant que commentaire).
Anthony G - justice pour Monica
1

Tirez parti du fichier de déconnexion de votre shell

Si vous n'avez besoin du serveur que pour des tâches interactives ou non interactives démarrées par votre UID, pensez à placer vos commandes d'arrêt dans votre fichier ~ / .bash_logout . Le manuel GNU Bash dit:

Lorsqu'un shell de connexion interactif se ferme ou qu'un shell de connexion non interactif exécute la commande intégrée exit, Bash lit et exécute des commandes à partir du fichier ~ / .bash_logout, s'il existe.

Ainsi, l'ajout de "sudo poweroff" ou similaire à votre fichier de déconnexion mettrait le serveur hors tension dès que vous vous déconnectez de votre session en cours, ou lorsqu'une session Bash non interactive appelle exit. Vous pouvez également choisir d'utiliser à ou passer un temps de retard à l' arrêt si vous préférez reporter l'arrêt.

Pour une approche plus interactive de cela, vous pouvez mettre les bashismes suivants dans votre fichier de déconnexion:

# 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

Avertissements

Il y a quelques mises en garde que vous devez garder à l'esprit à propos de cette solution:

  • Cela fonctionnera probablement même sous un terminal démarré par X Windows, mais ne fonctionnera probablement pas pour une session X11 qui n'a pas été lancée par startx ou similaire.
  • Si vous avez des scripts non interactifs qui appellent exit , vous pouvez rencontrer des arrêts vous ne vous attendiez pas.
  • Votre fichier sudoers peut vous demander un mot de passe si vous n'avez pas spécifié NOPASSWDpour les commandes d'arrêt, ou si vous n'avez pas appelésudo -v avant d'exécuter votre commande d'arrêt.
  • Il y a probablement d'autres cas marginaux auxquels je n'ai pas encore pensé.

En bref, vous voudrez peut-être déterminer si cette approche répond à vos besoins réels, ou si une approche complètement différente telle que la surveillance de l'absence d'utilisateurs connectés ou une autre alternative est un meilleur pari. Votre kilométrage variera certainement.

CodeGnome
la source