Como desligar um servidor Linux depois de executar por 60 minutos?

18

Eu tenho um servidor que normalmente está desligado por razões de segurança. Quando quero trabalhar nele, eu o ligo, executo minhas tarefas e o desligo novamente. Minhas tarefas geralmente não levam mais de 15 minutos. Gostaria de implementar um mecanismo para desligá-lo automaticamente após 60 minutos.

Eu pesquisei como fazer isso com o cron, mas não acho que seja o caminho correto, porque o cron não leva em consideração quando o servidor foi ativado pela última vez. Só posso definir padrões periódicos, mas eles não levam esses dados em consideração.

Como eu poderia fazer essa implementação?

jmhostalet
fonte
4
Dê uma olhada at(execução única).
dirkt 02/10
14
Eu não fiz isso, mas seu script de login pode iniciar um sudo shutdown -h +60que iniciaria um contador de 60 minutos para o processo de desligamento (-halt). Se você queria cancelá-lo, você poderia sudo shutdown -c (isso não utilizar cron embora)
guiverc
7
Dependendo da natureza de suas tarefas, talvez valha a pena executá-las dentro de um contêiner de docker, para que você não precise se preocupar em desligar um servidor. O contêiner é criado, executa suas tarefas e é destruído depois disso.
Vicente Olivert Riera
6
Não espere nenhum benefício real de segurança com isso. A maioria das vulnerabilidades pode ser explorada em menos de um segundo, portanto, desligar após uma hora não impedirá a exploração. E um invasor que encontrou uma vulnerabilidade pode esperar que você ligue a máquina para realizar o ataque.
kasperd
2
Re: Comentário do @kasperd, eu o reformularia dizendo que você precisa exatamente da mesma quantidade de segurança em seu servidor, independentemente de quanto ela esteja realmente online. Observe que é um servidor conectado a alguma coisa e isso significa que algo saberá quando for ativado - varreduras automatizadas não são com o que você se preocupa, são conexões de qualquer tipo e você não pode evitar isso, portanto, segurança máxima é o tempo todo o único jeito.
StephenG

Respostas:

23

Se você executar suas tarefas como o mesmo usuário sempre, poderá simplesmente adicionar o comando shutdown, opcionalmente com a opção -P, ao seu perfil. O número representa a quantidade de minutos em que o comando shutdown está atrasado. Verifique se o usuário tem a capacidade de executar o comando shutdown via sudo sem uma senha.

echo "sudo shutdown -P +60" >> ~/.profile
Dirk Krijgsman
fonte
11
O tempo é em minutos, não segundos. Tente shutdown -k -P 3600vs shutdown -k -P 60( -kmensagem de impressões parede, mas não tem outro efeito)
sebasth
12
Mas tente o comando uma vez primeiro, você não deseja que um desligamento instantâneo seja vinculado ao seu perfil!
Fabian Röling
17
Eu imagino que todo login ssh causaria uma nova chamada de desligamento. O contador seria reiniciado então?
JOL
4
Também vale a pena mencionar que logins não serão permitidos nos últimos 5 minutos, conforme mencionado na página de manual do desligamento.
21318 JoL
6
Observe que 60 minutos após o login não é o mesmo que 60 minutos após a inicialização. E se você inicializar a máquina e depois esquecer de fazer login?
Hagen von Eitzen
69

Existem várias opções.

  • Forneça tempo diretamente para shutdown -P:

    shutdown -P +60
    

    Observe que a shutdown página do manual também aponta:

    Se o argumento time for usado, 5 minutos antes do sistema cair, o arquivo / run / nologin será criado para garantir que logins adicionais não sejam permitidos.

  • Use o atcomando

  • Crie um arquivo de unidade systemd ou um script init que seja executado shutdown -P 60na inicialização.

  • Use cron @rebootpara executar o comando após a inicialização.

    Adicione ao crontab (raiz):

    @reboot shutdown -P +60
    

Para os dois últimos métodos, você também pode usar o sleep 3600 && shutdown -P nowargumento time para shutdownnão atrasar o desligamento por 60 minutos. Dessa forma, os logins são possíveis até o último momento antes da emissão do desligamento.

sebasth
fonte
2
Eu acho que com o sleepcomando, você ainda precisa especificar um tempo para shutdown- nós queremos usar nowesse argumento se já tivermos feito a espera (mas observe que você não receberá muitos avisos para salvar seu trabalho antes dele) desaparece debaixo de você!).
quer
1
Embora shutdown -P 60funcione, não é assim que o comando deve ser chamado. De acordo com a página do manual, você deve usar shutdown -P +60. --- O desligamento também sem um argumento de tempo (no exemplo sleep 3600 && shutdown -P) será atrasado em um minuto (como shutdown -P +1). Como Toby Speight escreveu, você provavelmente gostaria de usar shutdown -P now.
Pabouk # 4/18
34

Isso parece um problema XY .

Minhas tarefas geralmente não levam mais de 15 minutos. Gostaria de implementar um mecanismo para desligá-lo automaticamente após 60 minutos.

Se você desligar após 60 minutos, corre o risco de estar executando um problema particularmente complicado e precisar de mais tempo. Muitas das soluções anteriores não facilitariam o atraso do desligamento.

Se a tarefa não é interativa, mas sim uma tarefa com script que é automaticamente acionada de outra máquina, o @sdkks ofereceu uma ótima solução para isso; você realmente deve apenas encarregar a máquina de executar o desligamento assim que o script e todas as suas tarefas terminarem.

No entanto, se sua tarefa for interativa, sugiro que faça a detecção de inatividade.

Se você executar sua tarefa em uma GUI (X11), poderá detectar as sessões da GUI inativa usando a abordagem descrita aqui: Execute um comando quando o sistema estiver inativo e quando estiver ativo novamente

Se você executar a tarefa através de um terminal, poderá detectar usuários conectados usando o whocomando Você pode configurar um cronjob que desligue a máquina se whoretornar um resultado vazio. Observe que essa será uma abordagem bastante conservadora; ele não desligará o sistema se você deixar o console conectado, mas ocioso.

Se você quiser ser um pouco mais agressivo e desconectar sessões de terminal ociosas, bem, você pode combinar a abordagem anterior com desligar automaticamente sessões SSH ociosos ClientAliveInterval e ClientAliveCountMax. Outra abordagem para isso, se você não tiver SSH, mas tiver uma sessão de terminal local, é usar o tempo ocioso do terminal, conforme retornado pelo wcomando.

Lie Ryan
fonte
2
Este é um ponto muito importante. Tudo o que você implementar - é do seu interesse garantir que você também possa cancelar o desligamento.
Shadow
1
Algo deu errado se ainda estiver funcionando a 60m, então talvez comece novamente. Isso pode ser muito caro em termos de nuvem. Não garantir uma paralisação em uma ocasião me custou mais de US $ 4.000.
Mckenzm
8

Embora todas as respostas anteriores aqui atendam aos requisitos de perfeição, você também pode desligar a máquina assim que as tarefas forem concluídas.

bashOs scripts podem ser trapped, o que significa que certos sinais podem ser interceptados e determinadas tarefas podem ser executadas quando necessário. EXITé um dos sinais que podem ser capturados.

Você seria capaz de:

  1. Defina a trappara EXITseus scripts de shell automatizados, significando o encerramento de suas tarefas automatizadas
  2. Defina um trappara o seu .bashrc EXIT, ou seja, sempre que você sair dessa máquina, desligue-a.

A opção 1 seria o caso ideal, desde que suas tarefas não exijam inspeção adhoc e julgamento manual.

A opção 2 abrangeria os casos em que você esqueceria de sair do terminal sem desligar. Há uma ressalva; se você tiver vários terminais na mesma máquina abertos e sair de um deles, ele ainda desligará a máquina da mesma forma. (Ele pode ser script para evitar isso, mas não vou complicar a solução.)

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

Isso pode estar no final da .bashrcopção 2, em algum lugar na parte superior do seu script para a opção 1.

Por que não usar poweroffno final do script?

Eu prefiro usar set -eo pipefailno topo dos meus scripts. Se ocorrer algum erro, ele não falhará silenciosamente; parará de executar mais comandos. trapO EXITsinal deve cobrir os casos em que o script termina prematuramente devido a erros.

No entanto, para suas tarefas, isso também pode significar que a máquina será desligada antes de serem concluídas.

Eu tenho um bashmodelo simples que eu uso para facilitar a depuração de scripts; talvez possa ser de alguma utilidade. Por favor, veja esta essência .

sdkks
fonte
Concordou, e para ter certeza, talvez uma hora do dia desligada do cron. Este é o freio de um morto.
Mckenzm 04/10
@ Abigail para script, tem que estar acima, pois .bashrceu preferiria a parte inferior, caso outra coisa a substituísse. Sua preocupação não parece clara. Você pode compartilhar um trecho de exemplo em repl.it, talvez?
Sdkks
@mckenzm Eu não entendo. Você pode compartilhar código de amostra ou mais explicações?
Sdkks
5

Elaborando sobre comentário @dirkt, você pode inserir um atcomando em seu .bashrcou .profileou qualquer arquivo de seus usos do escudo em Login para agendar um desligamento automático 60 minutos após o seu login.

Algo como:

at now + 60 minutes -f /sbin/halt
Mr Shunz
fonte
Esta tarefa é exatamente o atbeco. Você também pode ver as attarefas em/var/spool/
sdkks
5
Eu recomendaria não usar atneste contexto porque ele sobrevive às reinicializações. Se o OP fizesse logon, desligasse manualmente e depois novamente no espaço de uma hora, ele seria iniciado antes de passar uma hora após o último login, quando o primeiro processo de desligamento programado.
Aaron
@ Aaron isso é verdade. Ainda não pensei nisso. A persistência de inicialização é uma ressalva para esta solução.
Sdkks #
5

O seguinte é executado commandcom parâmetros e, se for concluído com êxito, a caixa será desativada imediatamente, supondo que o usuário possa executar poweroff. Pode ser necessário usar sudo poweroff.

command --parameters && poweroff

Considerando que o seguinte simplesmente roda poweroffimediatamente quando o comando termina:

command --parameters ; poweroff

Se você acha que o comando precisa de tempo de descanso após a conclusão, execute

command --parameters ; sleep 3600 ; poweroff

Se você acha que o comando pode executar horas extras, pode restringi-lo a uma hora:

timeout 1h command --parameters ; poweroff

timeoutfaz parte do coreutilspacote, então você provavelmente já o possui.

Criggie
fonte
3

Se você está realmente preocupado com a segurança, use um timer de tomada mecânica na fonte de alimentação. Basta configurá-lo para a hora que você deseja que seja desligado. Dessa forma, ninguém pode fazer login remotamente e desativar o desligamento. Você precisaria de acesso físico.

gogators
fonte
2
Corrupção do sistema de arquivos?
Xen2050
@ Xen2050 não é um problema em nenhum sistema de arquivos moderno (diário).
Tom
1
@ Tom Você tem uma fonte para montantes forçados nunca causará corrupção no sistema de arquivos se houver registro no diário? Parece novo para mim, eu gostaria de ler sobre isso. No mínimo, ele deve marcar o sistema de arquivos como sujo, forçando um fsck, certo?
Xen2050
1
Na maioria dos casos, ele deve apenas repetir o diário e terminar com ele. Um desligamento não deve causar corrupção no sistema de arquivos em um sistema de arquivos com registro em diário, embora não haja garantias, a menos que você use um sistema de arquivos como o ZFS, projetado especificamente para este caso.
Tom
1
A reprodução do diário pode falhar - eu tive uma sessão fsck muito difícil algumas semanas atrás, após um corte de energia de ½ segundo em uma máquina sem no-break. Isso estava usando ext4 com um diário; não é completamente invencível!
precisa
2

Se você estiver em uma systemdmáquina, poderá usar um timer monotônico

A unidade do temporizador /etc/systemd/system/shutdown_after_an_hour.timer

[Unit]
Description=shutdown after an hour

[Timer]
OnBootSec=1h

[Install]
WantedBy=timers.target

A unidade do temporizador /etc/systemd/system/shutdown_after_an_hour.service:

[Unit]
Description=shutdown after an hour

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

É ativado via

# systemctl enable shutdown_after_an_hour.timer

Seu status (particularmente quanto tempo resta antes do desligamento) está disponível via

# systemctl list-timers shutdown_after_an_hour.timer

Ele funcionará na próxima reinicialização; não será útil systemctl startdurante a sessão em que for criado, pois não funcionará (porque não foi acionado durante a reinicialização) ou desligará a máquina imediatamente após uma hora. Na verdade, não sei qual vai acontecer, nunca testei esse caso específico.

WoJ
fonte
1

Tente colocar o script ( sudo shutdown -P 3600) no /etc/init.ddiretório para executá-lo automaticamente na inicialização.

Ou tente usar anacron, adicionando o comando no /etc/anacrontabarquivo Também sugiro usar nohupna frente do comando para garantir que o comando ainda esteja funcionando após o logout.

Saveriofr
fonte
1
Dependendo distro, não pode se executada por apenas estar em init.d
sdkks
@sdkks, você está certo. Anacron também pode ser considerado. colocando o script em / etc / anacrontab, também usado com 'nohup' no caso de logout.
Saveriofr 02/10/1918
1
@Saveriofr Você pode editar sua resposta para melhorar sua qualidade (melhor do que postar informações adicionais como comentário).
Anthony G - justice para Monica
1

Aproveite o arquivo de logout do seu shell

Se você precisar apenas do servidor para tarefas interativas ou não interativas iniciadas pelo seu UID, considere colocar seus comandos de desligamento no arquivo ~ / .bash_logout . O Manual do GNU Bash diz:

Quando um shell de login interativo sai ou um shell de login não interativo executa o comando exit interno, o Bash lê e executa comandos do arquivo ~ / .bash_logout, se existir.

Portanto, adicionar "sudo poweroff" ou semelhante ao seu arquivo de logout desligaria o servidor assim que você sair da sessão atual ou quando uma sessão Bash não interativa chamar exit. Você também pode optar por usar a ou passar um tempo de atraso para o desligamento se você prefere adiar o desligamento.

Para uma abordagem mais interativa, você pode colocar os seguintes Bashisms em seu arquivo de 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

Ressalvas

Há algumas advertências que você deve ter em mente sobre esta solução:

  • Provavelmente, isso funcionará mesmo em um terminal iniciado pelo X Windows, mas provavelmente não funcionaria em uma sessão do X11 que não foi iniciada startxou similar.
  • Se você tiver scripts não interativos que chamam exit, poderá ocorrer encerramentos que não esperava.
  • Seu arquivo sudoers pode solicitar uma senha se você não especificou NOPASSWDos comandos shutdown ou se não ligou sudo -vantes de executar o comando shutdown.
  • Provavelmente existem outros casos extremos nos quais ainda não pensei.

Em resumo, convém considerar se essa abordagem atende às suas necessidades reais ou se uma abordagem completamente diferente, como monitorar a ausência de usuários conectados ou alguma outra alternativa, é uma aposta melhor. Sua milhagem definitivamente varia.

CodeGnome
fonte