Em sistemas operacionais, um daemon é um programa que é executado em background, em oposição aos programas que interagem diretamente com o usuário. Como exemplos, em sistemas UNIX, temos o syslogd (responsável por logs do sistema) e o sshd (responsável por receber conexões remotas do protocolo SSH) – observe que ambos os processos são terminados na letra d para indicar o seu modo de execução. Geralmente são processos que executam serviços de tempo de vida indeterminado e autônomos em sua execução e que, portanto, não precisam estar em evidência para o usuário.
No meu post onde demonstrei como implementar um bot para coleta de pontos no Gokano com o Mechanize, sugeri ao final daemonizar o algoritmo implementado. Para esse tipo de aplicação, ganha-se a facilidade de não necessitar ficar com o terminal aberto durante a execução do programa, uma vez que o algoritmo consiste de uma rotina em loop por tempo indeterminado e exigiria a linha de comando do console durante todo o andamento. Seria ainda mais vantajoso executar esse script daemonizado em um servidor em nuvem (como uma máquina da EC2 da Amazon, por exemplo) através de uma conexão remota SSH. Dessa forma, o script é executado em uma máquina de disponibilidade maior do que um computador pessoal, sem a necessidade de manter a conexão remota aberta.
Em Python, existem algumas opções de biblioteca para auxiliar nessa tarefa de executar o script em background. Em meus testes, a que se mostrou mais eficaz foi o daemonize, que exige poucas linhas de código para sua configuração e execução. O daemonize pode ser facilmente obtido através do PIP:
1 |
sudo pip install daemonize |
Após a instalação do pacote, algumas linhas de código precisam ser acrescentadas ao código original:
O CÓDIGO-FONTE
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
#!/usr/bin/env python # -*- coding: utf-8 -*- from daemonize import Daemonize import mechanize import cookielib import re from time import sleep pid = "/tmp/gokano_botd.pid" #Criando o Browser e definindo o acesso br = mechanize.Browser() url = 'http://www.gokano.com' email = '' password = '' #Tempo de atraso para tentar novamente em caso de falha delay_time = 60 def main(): while True: try: #Preparando os cookies cj = cookielib.LWPCookieJar() br.set_cookiejar(cj) #Opções do browser br.set_handle_equiv(True) br.set_handle_gzip(False) br.set_handle_redirect(True) br.set_handle_referer(True) br.set_handle_robots(False) br.set_handle_refresh(mechanize._http.HTTPRefreshProcessor(), max_time=1) #Simulando um navegador como firefox br.addheaders = [('User-agent', 'Mozilla/5.0 (X11;\ U; Linux i686; en-US; rv:1.9.0.1) Gecko/2008071615\ Fedora/3.0.1-1.fc9 Firefox/3.0.1')] br.open(url) # Para abrir o primeiro formulário, você pode selecionar com: #0 br.select_form(nr=0) # Preencher o formulário com os dados de login e submetendo br.form['email'] = email br.form['password'] = password br.submit() #Lendo a página e procurando pelo link com texto "Collect daily" html = br.response().read() link = br.find_link(text_regex=re.compile("Collect daily"),nr=0) br.follow_link(link) print "Coletado com sucesso!" #tempo de sleep para próxima tentativa(em segundos): 24h*60m*60s sleep(24*60*60) except Exception, e: print "Não foi possível coletar. Tentando novamente em", delay_time/60 ,"minuto(s)." sleep(delay_time) daemon = Daemonize(app="gokano_botd", pid=pid, action=main) daemon.start() |
Para executar o programa como daemon, é necessário que o algoritmo esteja englobado em uma rotina principal. A função de daemonize toma então três argumentos: o nome da aplicação, o ID do processo (definido no início do algoritmo na pasta temporária do UNIX) e o método que vai ser executado (main). Você pode executar o algoritmo normalmente como qualquer script python. Para verificar sua execução, você pode checar através da lista de processos:
1 |
ps ax | grep nome_do_programa |
Assim, se desejar finalizar sua execução, pode executar o comando para terminar processo, juntamente com o número de processo do daemon do script:
1 |
sudo kill -9 pid_processo |
Além do script de coleta de pontos do Gokano, outro exemplo de aplicação semelhante seria daemonizar um coletor de tweets que roda como um serviço e persiste esses tweets em um banco de dados, por exemplo. A ideia pode ser estendida a qualquer algoritmo com essa característica autônoma de execução, sem interação com o usuário. Quaisquer dúvidas ou sugestões, utilize o campo de comentários ou entre em contato!
3 Comentários
Sannytet
11 de dezembro de 2018 at 21:41Nice posts! 🙂
___
Sanny
Paulo Vaz
8 de Março de 2020 at 01:34Primeiramente parabéns, gostaria de saber alguma forma se o script parou de funcionar por algum motivo reinicie novamente. tem como? ou deveria fazer por outro script?
Ronan Lopes
9 de Março de 2020 at 12:04Bom dia, Paulo! Muito obrigado. Para esse caso, sugiro fazer um script bash que verifica se o script está rodando e, caso não esteja, executar. Tendo esse script, você adiciona um job ao crontab que executa a cada x minutos esse script bash de verificação. Deixo esse link aqui de recomendação: https://stackoverflow.com/questions/2366693/run-cron-job-only-if-it-isnt-already-running. Boa sorte!