¿Cómo apago un servidor Linux después de ejecutarlo durante 60 minutos?

18

Tengo un servidor que normalmente está apagado por razones de seguridad. Cuando quiero trabajar en él, lo enciendo, ejecuto mis tareas y lo apago nuevamente. Mis tareas generalmente no toman más de 15 minutos. Me gustaría implementar un mecanismo para apagarlo automáticamente después de 60 minutos.

He investigado cómo hacer esto con cron, pero no creo que sea la forma correcta porque cron no tiene en cuenta cuándo se encendió el servidor por última vez. Solo puedo establecer patrones periódicos, pero no tienen en cuenta esos datos.

¿Cómo podría hacer esta implementación?

jmhostalet
fuente
44
Echa un vistazo a at(ejecución única).
Dirkt
14
No he hecho esto, pero su secuencia de comandos de inicio de sesión podría iniciar una sudo shutdown -h +60que iniciaría un contador de 60 minutos para el proceso de apagado (-halt). Si desea cancelarlo, podría sudo shutdown -c (aunque esto no usa cron)
guiverc
77
Dependiendo de la naturaleza de sus tareas, tal vez valga la pena ejecutarlas dentro de un contenedor acoplable, por lo que no debe preocuparse por apagar un servidor. El contenedor se crea, ejecuta sus tareas y se destruye después de eso.
Vicente Olivert Riera
66
No espere ningún beneficio de seguridad real de esto. La mayoría de las vulnerabilidades pueden explotarse en menos de un segundo, por lo que apagarse después de una hora no evitará la explotación. Y un atacante que encontró una vulnerabilidad puede esperar a que encienda la máquina para realizar el ataque.
Kasperd
2
Re: Comentario de @kasperd, lo reformularía diciendo que necesita exactamente la misma cantidad de seguridad en su servidor, independientemente de cuánto o poco esté realmente en línea. Tenga en cuenta que es un servidor, por lo que se conecta a algo y eso significa que algo sabrá cuando está encendido: los barridos automáticos no son lo que le preocupa, son conexiones de ningún tipo y no puede evitar eso, por lo que la máxima seguridad todo el tiempo es la única forma.
StephenG

Respuestas:

23

Si ejecuta sus tareas como el mismo usuario cada vez, simplemente puede agregar el comando de apagado, opcionalmente con la opción -P, a su perfil. El número representa la cantidad de minutos que se demora el comando de apagado. Asegúrese de que su usuario tenga la capacidad de ejecutar el comando de apagado a través de sudo sin una contraseña.

echo "sudo shutdown -P +60" >> ~/.profile
Dirk Krijgsman
fuente
11
El tiempo es en minutos, no segundos. Try shutdown -k -P 3600vs shutdown -k -P 60( -kimprime el mensaje del muro pero no tiene otro efecto)
sebasth el
12
¡Pero intente el comando una vez primero, no desea que un apagado instantáneo esté vinculado a su perfil!
Fabian Röling
17
Me imagino que cada inicio de sesión ssh causaría una nueva llamada de apagado. ¿Se restablecería el contador entonces?
JoL
44
También podría valer la pena mencionar que no se permitirán inicios de sesión en los últimos 5 minutos, como se menciona en la página de manual de apagado.
JoL
66
Tenga en cuenta que 60 minutos después del inicio de sesión no es lo mismo que 60 minutos después del inicio. ¿Qué sucede si arranca la máquina y luego olvida iniciar sesión?
Hagen von Eitzen
69

Hay varias opciones.

  • Proporcione tiempo directamente a shutdown -P:

    shutdown -P +60
    

    Tenga en cuenta que la shutdown página del manual también señala:

    Si se utiliza el argumento de tiempo, 5 minutos antes de que el sistema se caiga, se crea el archivo / run / nologin para garantizar que no se permitirán más inicios de sesión.

  • Usa el atcomando.

  • Cree un archivo de unidad systemd o un script de inicio que se ejecute shutdown -P 60al inicio.

  • Use cron @rebootpara ejecutar el comando después del arranque.

    Agregar a crontab (raíz):

    @reboot shutdown -P +60
    

Para los dos últimos métodos, también puede usar en sleep 3600 && shutdown -P nowlugar de usar el argumento de tiempo shutdownpara retrasar el apagado por 60 minutos. De esta manera, los inicios de sesión son posibles hasta el último momento antes de que se emita el apagado.

sebasth
fuente
2
Creo que con el sleepcomando, aún necesita especificar un tiempo para shutdown- nos gustaría usar nowpara ese argumento si ya hemos hecho la espera (pero tenga en cuenta que no recibirá muchas advertencias para guardar su trabajo antes desaparece debajo de ti!).
Toby Speight
1
Aunque shutdown -P 60funciona, no es la forma en que se debe invocar el comando. De acuerdo con la página del manual que debe usar shutdown -P +60. --- También el apagado sin un argumento de tiempo (en el ejemplo sleep 3600 && shutdown -P) se retrasará un minuto (como shutdown -P +1). Como escribió Toby Speight, probablemente querrás usarlo shutdown -P now.
pabouk
34

Esto parece un problema XY .

Mis tareas no suelen durar más de 15 minutos. Me gustaría implementar un mecanismo para apagarlo automáticamente después de 60 minutos.

Si se apaga después de 60 minutos, corre el riesgo de que esté teniendo un problema particularmente complicado y solo necesite más tiempo. Muchas de las soluciones anteriores no facilitarían el retraso del cierre.

Si la tarea no es una tarea interactiva, sino que es una tarea programada que se activa automáticamente desde otra máquina, @sdkks dio una gran solución para eso; Realmente deberías asignarle a la máquina que se apague tan pronto como finalice el script y todas sus tareas.

Sin embargo, si su tarea es interactiva, le sugiero que haga una detección inactiva.

Si realiza su tarea en una GUI (X11), puede detectar las sesiones de GUI inactivas utilizando el enfoque descrito aquí: ejecute un comando cuando el sistema esté inactivo y cuando esté activo nuevamente

Si realiza la tarea a través de un terminal, puede detectar usuarios conectados con el whocomando. Puede configurar un cronjob que apaga la máquina si whodevuelve un resultado vacío. Tenga en cuenta que este será un enfoque bastante conservador; no apagará el sistema si dejó la consola conectada, pero inactiva.

Si desea ser un poco más agresivo y desconectar también las sesiones de terminal inactivas, puede combinar el enfoque anterior con desconectar automáticamente las sesiones SSH inactivas ClientAliveInterval y ClientAliveCountMax. Otro enfoque para esto si no tiene SSH, pero tiene una sesión de terminal local, es usar el tiempo de inactividad del terminal tal como lo devuelve el wcomando.

Lie Ryan
fuente
2
Este es un punto muy importante. Independientemente de lo que implemente, le conviene asegurarse de que también puede cancelar el cierre.
Sombra
1
Algo ha salido mal si todavía se está ejecutando a 60 m, así que tal vez solo comience de nuevo. Esto puede ser muy costoso en la nube. No garantizar un cierre en una ocasión me retrasó más de $ 4,000.
mckenzm
8

Aunque las respuestas anteriores aquí satisfacen el requisito de perfección, también puede apagar la máquina tan pronto como se realicen las tareas.

bashlos scripts pueden ser trapped, lo que significa que ciertas señales pueden ser interceptadas y ciertas tareas pueden ejecutarse cuando sea necesario. EXITEs una de las señales que pueden quedar atrapadas.

Podrías:

  1. Establezca una trappara EXITsus scripts de shell automatizados, lo que significa la finalización de sus tareas automatizadas
  2. Establezca un trappara su .bashrc EXIT, lo que significa que cada vez que cierre sesión en esa máquina, apáguela.

La opción n. ° 1 sería el caso ideal, siempre que sus tareas no requieran inspección ad hoc y juicio manual.

La opción n. ° 2 cubriría los casos en los que olvidaría salir del terminal sin apagarlo. Sin embargo, hay una advertencia; Si tiene varias terminales abiertas para la misma máquina y sale de una de ellas, igual apagará la máquina. (Se puede programar para evitar eso, pero no complicaré la solución).

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

Esto puede ser al final de la .bashrcopción # 2, en algún lugar en la parte superior de su script para la opción # 1.

¿Por qué no usar poweroffal final del guión?

Prefiero usar set -eo pipefailen la parte superior de mis scripts. Si ocurre algún error, no fallará en silencio; dejará de ejecutar más comandos. trapde EXITseñal debe cubrir los casos en que el script termina prematuramente debido a errores.

Sin embargo, para sus tareas, esto también puede significar que la máquina se apagará antes de que se complete.

Tengo una bashplantilla simple que uso para facilitar la depuración de scripts; tal vez podría ser de alguna utilidad. Por favor vea esta esencia .

sdkks
fuente
De acuerdo, y para estar seguro, tal vez un momento del día apagado de cron. Este es el freno de un hombre muerto.
mckenzm
@Abigail para script, tiene que estar arriba, porque .bashrcpreferiría el fondo en caso de que algo más lo sobrescriba. Su preocupación no parece clara, ¿puede compartir un fragmento de ejemplo en repl.it quizás?
sdkks
@mckenzm No entiendo. ¿Puedes compartir código de muestra o más explicaciones?
sdkks
5

Abundando en @dirkt comentario, se puede insertar un atcomando en su .bashrco .profileo cualquier archivo que usa su shell en inicio de sesión para programar un apagado automático de 60 minutos después de su inicio de sesión.

Algo como:

at now + 60 minutes -f /sbin/halt
Señor shunz
fuente
Esta tarea está en atel callejón. También puede ver atlas tareas en/var/spool/
sdkks
55
Aconsejaría no usar aten este contexto porque sobrevive los reinicios. Si OP iniciara sesión, apagara manualmente y luego volviera a iniciar sesión en el lapso de una hora, sería expulsado antes de que transcurriera una hora después de su último inicio de sesión cuando el primer proceso de apagado programado.
Aaron
@ Aaron es verdad. No he pensado en eso. La persistencia de arranque es una advertencia para esta solución.
sdkks
5

Lo siguiente se ejecuta commandcon parámetros, y si se completa con éxito, se apagará la casilla de inmediato, suponiendo que el usuario pueda ejecutar poweroff. Puede que necesite usar sudo poweroff.

command --parameters && poweroff

Mientras que el siguiente simplemente se ejecuta poweroffinmediatamente cuando termina el comando:

command --parameters ; poweroff

Si cree que el comando necesita tiempo de descanso después de la finalización, ejecute

command --parameters ; sleep 3600 ; poweroff

Si cree que el comando podría ejecutar horas extras, puede restringirlo a una hora:

timeout 1h command --parameters ; poweroff

timeoutes parte del coreutilspaquete, por lo que probablemente ya lo tenga.

Criggie
fuente
3

Si realmente le preocupa la seguridad, use un temporizador de salida mecánica en la fuente de alimentación. Simplemente configúrelo a la hora que desee que se apague. De esta manera, nadie puede iniciar sesión de forma remota y desactivar el apagado. Necesitarías acceso físico.

gogators
fuente
2
Corrupción del sistema de archivos?
Xen2050
@ Xen2050 no es un problema en ningún sistema de archivos moderno (diario).
Tom
1
@Tom ¿Tiene una fuente para realizar montajes forzados que nunca causarán daños en el sistema de archivos si hay un diario? Suena nuevo para mí, me gustaría leerlo. Como mínimo, debe marcar el sistema de archivos como sucio, forzando un fsck, ¿verdad?
Xen2050
1
En la mayoría de los casos, solo debe reproducir el diario y terminar con él. Un apagado no debe causar daños en el sistema de archivos en un sistema de archivos registrado, aunque no hay garantías a menos que use un sistema de archivos como ZFS que está específicamente diseñado para este caso.
Tom
1
La repetición del diario puede fallar: tuve una sesión fsck muy difícil hace un par de semanas después de un corte de energía de ½ segundo a una máquina sin UPS. Eso estaba usando ext4 con un diario; ¡No es completamente invencible!
Toby Speight
2

Si está en una systemdmáquina, puede usar un temporizador monótono

La unidad de temporizador /etc/systemd/system/shutdown_after_an_hour.timer

[Unit]
Description=shutdown after an hour

[Timer]
OnBootSec=1h

[Install]
WantedBy=timers.target

La unidad de temporizador /etc/systemd/system/shutdown_after_an_hour.service:

[Unit]
Description=shutdown after an hour

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

Se habilita a través de

# systemctl enable shutdown_after_an_hour.timer

Su estado (en particular, cuánto tiempo queda antes del apagado) está disponible a través de

# systemctl list-timers shutdown_after_an_hour.timer

Funcionará en el próximo reinicio, no es útil systemctl startdurante la sesión cuando se crea, ya que no funcionará (porque no se activó durante el reinicio) o apagará la máquina de inmediato si ha pasado una hora. No sé cuál sucederá de hecho, nunca he probado ese caso específico.

WoJ
fuente
1

Intente colocar el script ( sudo shutdown -P 3600) en el /etc/init.ddirectorio para ejecutarlo automáticamente al inicio.

O intente usar anacron, agregando el comando en el /etc/anacrontabarchivo. También sugiero usar nohupdelante del comando para asegurarse de que el comando aún funciona después de cerrar sesión.

Saveriofr
fuente
1
Dependiendo de la distribución, podría no ejecutarse simplemente estando en init.d
sdkks
@sdkks, tienes razón. Anacron también puede ser considerado. poniendo el script en / etc / anacrontab, también se usa con 'nohup' en caso de cierre de sesión.
Saveriofr
1
@Saveriofr Puede editar su respuesta para mejorar su calidad (mejor que publicar información adicional como comentario).
Anthony G - justicia para Monica
1

Aproveche el archivo de cierre de sesión de su Shell

Si solo necesita el servidor para tareas interactivas o no interactivas iniciadas por su UID, considere colocar sus comandos de apagado en su archivo ~ / .bash_logout . El manual de GNU Bash dice:

Cuando sale un shell de inicio de sesión interactivo, o un shell de inicio de sesión no interactivo ejecuta el comando de salida incorporado, Bash lee y ejecuta comandos del archivo ~ / .bash_logout, si existe.

Por lo tanto, agregar "sudo poweroff" o similar a su archivo de cierre de sesión apagará el servidor tan pronto como cierre la sesión de su sesión actual, o cuando llame una sesión Bash no interactiva exit. También podría optar por utilizar en o pasar un tiempo de retardo de apagado , si usted prefiere aplazar el cierre.

Para un enfoque más interactivo de esto, puede poner los siguientes Bashisms en su archivo de cierre de sesión:

# 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

Advertencias

Hay algunas advertencias que debe tener en cuenta sobre esta solución:

  • Esto probablemente funcionará incluso bajo una terminal iniciada por X Windows, pero probablemente no funcionaría para una sesión X11 que no fue iniciada por startx o similar.
  • Si tiene scripts no interactivos que llaman exit, puede experimentar paradas que no esperaba.
  • Su archivo sudoers puede solicitar una contraseña si no ha especificado NOPASSWDlos comandos de apagado, o si no ha llamado sudo -vantes de ejecutar su comando de apagado.
  • Probablemente hay otros casos extremos en los que aún no he pensado.

En resumen, es posible que desee considerar si este enfoque satisface sus necesidades reales o si un enfoque completamente diferente, como monitorear la ausencia de usuarios conectados o alguna otra alternativa, es una mejor opción. Su kilometraje definitivamente variará.

CodeGnome
fuente