Como tempo limite de horas no Bash (e manter o tempo limite mesmo se a sessão foi fechada)?

6

Eu criei o seguinte script para instalar e desinstalar o PHPmyadmin no Ubuntu 16.04 ...

Meu objetivo é usar esse script toda vez que eu quiser usar o PHPmyadmin e, depois de algum tempo como 2 horas , excluí-lo. Este método install-use-uninstall é usado por razões de segurança (mantendo o MySQL inacessível possível e acessado apenas localmente por períodos curtos de tempo).

bash /dev/fd/15 15<< 'EOF0'    

#!/bin/bash -x

# Install commands:

sudo apt-get install phpmyadmin
sudo phpenmod mcrypt
sudo phpenmod mbstring
cat << EOF1 >> /etc/apache2/apache2.conf

Include /etc/phpmyadmin/apache.conf
EOF1
sudo service apache2 restart

# Unnstall commands:

sleep 2h    
sudo phpdismod mcrypt mbstring
sudo apt-get purge phpmyadmin
sudo service apache2 restart
sed -i 's/Include \/etc\/phpmyadmin\/apache.conf/ /g /etc/apache2/apache2.conf

EOF0

Como observado nos comentários de Jeff (e como eu editei o exemplo de código) eu pude usar o comando sleep , mas sleep , em sua forma clássica requer que a sessão continue aberta, e a janela pode fechar às vezes, por qualquer motivo, é necessária uma resposta canônica que mostre como dar essa suspensão de 2 horas, mas de forma que, mesmo que eu feche a janela por engano / intencionalmente ou reinicie meu PC por qualquer motivo, ou houve uma queda de energia --- A suspensão e todos os comandos depois dela continuarão funcionando no VPS, sem qualquer interferência do meu fim.

Então, como eu poderia executar os comandos de desinstalação 2 horas após os comandos de instalação, mas de maneira independente da sessão?

    
por JohnDoea 23.12.2016 / 05:01

9 respostas

0

Consegui combinar tempo limite ( sleep ), heredoc externo, heredoc (s) interno (s), nohup , processamento em nível de segundo plano e tty-stdout no script a seguir.

É bom que você precise de uma maneira rápida de instalar algo e depois excluí-lo automaticamente depois de algum tempo:

bash /dev/fd/5 5<< 'EOF0'
#!/bin/bash -x

apt-get install SOME_UTILITY1 -y

cat << EOF1 > ~/utility.sh
sleep 1h
apt-get purge SOME_UTILITY1 -y
EOF1

chmod 755 ~/utility.sh &
nohup ~/utility.sh &

EOF0

Pressione Enter (Enter) quando receber a seguinte mensagem, para continuar trabalhando normalmente no Bash (a mensagem aparecerá no momento em que o script atingir nohup :

nohup: appending output to ‘/USER_LOCATION/nohup.out’

    
por 30.12.2016 / 04:59
9

Você pode conseguir isso com o utilitário at .

Para um único comando, faça:

at 'now + 2 hours' -f /path/to/uninstall.sh

Para vários comandos, sirva seu script no shell via cat heredocument:

cat << EOF | at 'now + 2 hours'
command1
command2
........
EOF

Como alternativa, você pode conseguir isso com uma solução systemd (novamente, se você tiver instalado)

systemd-run --on-active=2h -- /bin/bash /path/to/uninstall.sh
    
por 27.12.2016 / 13:16
2

Como posso ver, você tem sudo access e pode iniciar serviços. Então você pode usar o comando atd service e at para agendar sua tarefa:

echo 'touch $HOME/'date -j +%s'.txt' | at + 2 minutes

E para mais de um comando, você tem duas opções:

  1. Combine os comandos echo :

    (echo "command1"
     echo "command2"
     echo "command3" ) | at + 2 hours
    
  2. Use o arquivo temporário para a lista de comandos:

     tmp_file=$(mktemp --tmpdir uninstall_commands.XXXX)
     echo "command1" >> ${tmp_file}
     echo "command2" >> ${tmp_file}
     echo "command3" >> ${tmp_file}
     at -f ${tmp_file} + 2 hours
     rm -f -- ${tmp_file}
    
por 27.12.2016 / 13:09
1

Assumindo dois scripts ( Faça uma coisa; faça bem ):

install.sh

#!/bin/sh -eu
sudo apt-get install phpmyadmin
sudo phpenmod mcrypt mbstring
printf 'Include /etc/phpmyadmin/apache.conf' >> /etc/apache2/apache2.conf
sudo service apache2 restart

uninstall.sh

#!/bin/sh -eu
sudo phpdismod mcrypt mbstring
sudo apt-get purge phpmyadmin
sudo service apache2 restart
sed -i 's/Include \/etc\/phpmyadmin\/apache.conf/ /g /etc/apache2/apache2.conf

A resposta mais simples que consigo fazer é exatamente o que você quer é

./install.sh && sleep 2h && ./uninstall.sh >>/var/log/mylog.log 2>&1

onde cada script inclui adicionalmente um comando ssh para conectar-se ao seu servidor. Essa abordagem é resiliente ao ciclo de energia do servidor - mas não à sua máquina terminal.

Como alternativa, eu simplificaria esta resposta principalmente por causa do comportamento bizarro de onde atd coloca sua saída e ao invés disso usa

nohup sleep 2h && ./uninstall.sh >>/var/log/mylog.log 2>&1 &

Uma vez executado, você tem aproximadamente 2 horas para fazer o que quiser e, depois que o tempo acabar, o processo de desinstalação acontecerá. Essa abordagem não é resiliente ao ciclo de energia do servidor.

Esta resposta evita dependências e permite diagnosticar / depurar capturando e registrando sensivelmente a saída relevante.

    
por 28.12.2016 / 00:00
1

Primeiro, você deve estruturar seu código em dois scripts, ou pelo menos em duas funções separadas dentro do mesmo script: a primeira para a instalação, a segunda para a limpeza. Então você pode executar qualquer script / função quando necessário. Ambos os scripts / funções também devem ser idempotentes, ou seja, devem pular a instalação / limpeza caso já esteja pronto.

Em seguida, você pode simplesmente criar um cronjob para chamar o script de limpeza a cada 2h ou criar um cronjob mais periódico que chame o script de limpeza se-e-somente-se a instalação tiver pelo menos 2h de idade. Isso sobreviveria a uma reinicialização do servidor, portanto, o pacote sempre será removido.

    
por 28.12.2016 / 18:38
0

Não tenho certeza se essa solução pode atender às suas necessidades, mas você pode tentar.

Se por um momento esquecer o desligamento / reinicialização do PC, o seguinte funciona no bash sem terminal de trapping (você pode testá-lo como um comando de linha para teste):

sleep 10 && yad --text="10 seconds passed" && exit &

Acima do comando, embora eu não esperava, funciona mesmo se eu fechar a janela do meu terminal.

PS: Se você combiná-lo com nohup manterá o comando em execução, mesmo que você efetue logout.

Como solução alternativa, você pode dividir seu script inicial em dois scripts menores; um script para instalação de um script para remoção, algo assim:

#script_to_install.sh  
sudo apt-get install phpmyadmin
sudo phpenmod mcrypt mbstring
printf 'Include /etc/phpmyadmin/apache.conf' >> /etc/apache2/apache2.conf
sudo service apache2 restart
sleep 7200 && path/to/script_to_remove.sh &
exit #exit the first script to free terminal (or even close the terminal)
#end of script_to_install.sh

#script_to_remove.sh
#Optionally you can use xterm -e (or similar) to bring up a terminal window automatically to see the output of the commands
sudo phpdismod mcrypt mbstring
sudo apt-get purge phpmyadmin
sudo service apache2 restart
sed -i 's/Include \/etc\/phpmyadmin\/apache.conf/ /g /etc/apache2/apache2.conf
exit
#end of script_to_remove.sh

Voltando à parte de reinicialização do PC, acho que isso pode ser resolvido gravando a hora de início em um arquivo de log temporário e, depois de reinicializar, você pode monitorar esse arquivo temporário (ou seja, usando ferramentas inotify) para determinar o período de tempo decorrido (não testado).

    
por 27.12.2016 / 16:40
0

No bash, adicione seu script com a instrução sleep ao seu arquivo ~/.bash_logout . Em csh, seria .logout.

Eu também gostei da sugestão de alguém de usar em. Você também pode querer considerar escrever um script que atue como uma função do tipo 'polícia' via cron.

Encontrei isto neste site, o que pode ser útil:    Como executar um script durante o logoff do Gnome

    
por 27.12.2016 / 23:56
0

IMHO, essa abordagem de instalar temporariamente e remover o phpmyadmin é um hack feio. Você poderia simplesmente ssh -L3307:localhost:3306 , ou seja, criar um ouvinte em uma porta local ( -L3307 ) que se conecta a uma porta remota ( localhost:3306 ). Então, se você quiser conversar com o banco de dados MySQL remoto, basta usar localhost:3307 na máquina local. Você não precisaria instalar nada remotamente, o túnel morreria imediatamente ao desconectar, e você poderia usar qualquer ferramenta do MySQL localmente (por exemplo, MySQL Workbench ou SQirreL).

    
por 28.12.2016 / 18:39
0

Existem maneiras melhores.

  1. Instale o phpMyAdmin em a host virtual dedicado com uma porta que você conhece apenas (digamos 56887 ).

  2. Configure knockd para abrir essa porta a seu pedido, apenas para seu IP.

    [phpMyAdmin]
      sequence      = 2000,3000,4000
      seq_timeout   = 15
      start_command = /usr/sbin/iptables -A INPUT -s %IP% -p tcp --dport 56887 -j ACCEPT
      cmd_timeout   = 7200
      stop_command  = /usr/sbin/iptables -D INPUT -s %IP% -p tcp --dport 56887 -j ACCEPT
    
  3. Use o knock para abrir a porta:

    knock myserver.example.com 2000 3000 4000 
    

Isso é tudo! Nenhuma reinstalação é necessária. Nenhum arquivo foi movido.

A segurança usual por meio de avisos de obscuridade se aplica. O phpMyAdmin configurado de forma insegura pode não estar suficientemente protegido por qualquer invasão. Você deve configurá-lo corretamente, não importa o quê. Mas se você fizer isso, esses hacks se tornam desnecessários.

    
por 30.12.2016 / 04:17