Почему Crontab не выполняется в нужную минуту - PullRequest
1 голос
/ 14 апреля 2019

Я устанавливаю задачу crontab, которая выполняется каждые 5 минут на моем сервере Ubuntu 18.04. Эта задача (написанная с python3) должна запросить некоторую цену на криптовалюту на cryptomarketcap.com и отправить мне письмо. Однако задача не выполняется так, как я хочу.

Я проверил журнал crontab и добавил команду logging в мой код на python. Но результат очень странный. Похоже, что в cron.log задача просто выполняется в идеальное время

Apr 14 04:30:01 lemp-s-1vcpu-1gb-sgp1-01 CRON[14979]: (root) CMD (/bin/sh /root/request_price/mail_price.sh)
Apr 14 04:35:01 lemp-s-1vcpu-1gb-sgp1-01 CRON[15004]: (root) CMD (/bin/sh /root/request_price/mail_price.sh)
Apr 14 04:39:01 lemp-s-1vcpu-1gb-sgp1-01 CRON[15088]: (root) CMD (  [ -x /usr/lib/php/sessionclean ] && if [ ! -d /run/systemd/system ]; then /usr/lib/php/sessionclean; fi)
Apr 14 04:40:01 lemp-s-1vcpu-1gb-sgp1-01 CRON[15090]: (root) CMD (/bin/sh /root/request_price/mail_price.sh)
Apr 14 04:45:01 lemp-s-1vcpu-1gb-sgp1-01 CRON[15102]: (root) CMD (/bin/sh /root/request_price/mail_price.sh)
Apr 14 04:50:01 lemp-s-1vcpu-1gb-sgp1-01 CRON[15112]: (root) CMD (/bin/sh /root/request_price/mail_price.sh)
Apr 14 04:55:01 lemp-s-1vcpu-1gb-sgp1-01 CRON[15150]: (root) CMD (/bin/sh /root/request_price/mail_price.sh)
Apr 14 05:00:01 lemp-s-1vcpu-1gb-sgp1-01 CRON[15174]: (root) CMD (/bin/sh /root/request_price/mail_price.sh)

Однако в журнале, записанном Python, все обстоит иначе

start program  2019-04-14 04:30:01.932384
start request  2019-04-14 04:30:01.932869
end request  2019-04-14 04:30:02.690205
start mailing  2019-04-14 04:30:02.694734
end mailing  2019-04-14 04:30:06.602899
start program  2019-04-14 04:43:31.499914
start request  2019-04-14 04:43:31.500368
start program  2019-04-14 04:43:31.512064
start request  2019-04-14 04:43:31.514192
end request  2019-04-14 04:43:31.853871
start mailing  2019-04-14 04:43:31.859186
end request  2019-04-14 04:43:31.877854
start mailing  2019-04-14 04:43:31.881670
end mailing  2019-04-14 04:43:33.438788
end mailing  2019-04-14 04:43:33.477752
start program  2019-04-14 04:45:02.085442
start request  2019-04-14 04:45:02.085969
end request  2019-04-14 04:45:02.434488
start mailing  2019-04-14 04:45:02.439000
end mailing  2019-04-14 04:45:03.724816
start program  2019-04-14 04:50:02.236511
start request  2019-04-14 04:50:02.237008
end request  2019-04-14 04:50:02.938542
start mailing  2019-04-14 04:50:02.943317
end mailing  2019-04-14 04:50:04.690106
start program  2019-04-14 04:57:59.706844
start request  2019-04-14 04:57:59.707152
end request  2019-04-14 04:58:00.065410
start mailing  2019-04-14 04:58:00.069808
end mailing  2019-04-14 04:58:02.075729
start program  2019-04-14 05:00:01.557796
start request  2019-04-14 05:00:01.558173
end request  2019-04-14 05:00:02.180507
start mailing  2019-04-14 05:00:02.185072
end mailing  2019-04-14 05:00:03.440213

Видно, что в 04:35 и 04:40 программа не запускалась, но в 04:43 она запускалась дважды. Аналогичные вещи в 04:57.

КОД: Командный файл crontab

*/5 * * * * /bin/sh /root/request_price/mail_price.sh

mail_price.sh

/root/anaconda3/bin/python3 /root/request_price/main.py

main.py

import get_price as gp
from send_mail import send_mail
import json
from pytz import timezone
from datetime import datetime,timedelta

with open('log.txt','a') as log:
    log.write('start program  '+str(datetime.now())+'\n')

raw_response = gp.request_api()

with open('log.txt', 'a') as log:
    log.write('end request  ' + str(datetime.now()) + '\n')

status = raw_response['status']
time_utc = datetime.strptime(status['timestamp'][0:-5], '%Y-%m-%dT%H:%M:%S')
time_beijing = time_utc+timedelta(hours=8)

data = raw_response['data']
btc_price = gp.get_currency_price(data, 'BTC')
bch_price = gp.get_currency_price(data, 'BCH')

print(datetime.strftime(time_beijing, '%Y-%m-%d %H:%M:%S'))

subject = 'Price'
content = 'BTC:'+"{0:.2f}".format(btc_price)+'\n BCH:'+"{0:.2f}".format(bch_price)+'\nTime:'\
    + datetime.strftime(time_beijing, '%Y-%m-%d %H:%M:%S')
receiver = "HIDE"

with open('log.txt', 'a') as log:
    log.write('start mailing  ' + str(datetime.now()) + '\n')

send_mail(receiver, subject, content)

with open('log.txt', 'a') as log:
    log.write('end mailing  ' + str(datetime.now()) + '\n')

get_price.py

from requests import Request, Session
from requests.exceptions import ConnectionError, Timeout, TooManyRedirects
import json
from datetime import datetime


def request_api():
    url = 'https://pro-api.coinmarketcap.com/v1/cryptocurrency/listings/latest'
    parameters = {
        'start': '1',
        'limit': '100',
        'convert': 'USD',
    }
    headers = {
        'Accepts': 'application/json',
        'X-CMC_PRO_API_KEY': 'HIDE',
    }

    session = Session()
    session.headers.update(headers)

    with open('log.txt', 'a') as log:
        log.write('start request  ' + str(datetime.now()) + '\n')

    try:
        response = session.get(url, params=parameters)
        data = json.loads(response.text)
        return data
    except (ConnectionError, Timeout, TooManyRedirects) as e:
        print(e)


def get_currency_price(data, symbol):
    for currency in data:
        if currency['symbol'] == symbol:
            return currency['quote']['USD']['price']
    return -1

send_mail.py

import smtplib
from email.mime.text import MIMEText
from email.header import Header
from email.utils import formataddr

def send_mail(receiver, subject, content):
    mail_host = "HIDE"
    mail_user = "HIDE"
    mail_pass = "HIDE"

    sender = 'HIDE'

    message = MIMEText(content, 'plain', 'utf-8')
    message['From'] = formataddr(["RapidSub Notification", sender]) 
    message['To'] = formataddr([receiver.split('@')[0], receiver])  

    message['Subject'] = Header(subject, 'utf-8')

    try:
        smtpObj = smtplib.SMTP_SSL(host=mail_host)
        smtpObj.connect(mail_host, 465)   
        smtpObj.login(mail_user, mail_pass)
        smtpObj.sendmail(sender, receiver, message.as_string())
        print("Success")
        smtpObj.quit()
    except smtplib.SMTPException:
        print("Error: Fail")
        smtpObj.quit()
...