【发布时间】:2018-09-07 09:12:16
【问题描述】:
我知道 crons 在与命令行不同的环境中运行,但我到处都使用绝对路径,我不明白为什么我的脚本表现不同。我相信它与我的 cron_supervisor 有关,它在子进程中运行 django“manage.py”。
Cron:
0 * * * * /home/p1/.virtualenvs/prod/bin/python /home/p1/p1/manage.py cron_supervisor --command="/home/p1/.virtualenvs/prod/bin/python /home/p1/p1/manage.py envoyer_argent"
这将调用 cron_supervisor,它会调用脚本,但脚本不会像我运行时那样执行:
/home/p1/.virtualenvs/prod/bin/python /home/p1/p1/manage.py envoyer_argent
在通过另一个脚本运行脚本时,是否需要做一些特别的事情才能正确调用该脚本?
这里是主管,主要用于错误处理,并确保在 cron 脚本本身出现问题时得到警告。
import logging
import os
from subprocess import PIPE, Popen
from django.core.management.base import BaseCommand
from command_utils import email_admin_error, isomorphic_logging
from utils.send_slack_message import send_slack_message
CURRENT_DIR = os.path.dirname(os.path.abspath(__file__))
PROJECT_DIR = CURRENT_DIR + '/../../../'
logging.basicConfig(
level=logging.INFO,
filename=PROJECT_DIR + 'cron-supervisor.log',
format='%(asctime)s %(levelname)s: %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
class Command(BaseCommand):
help = "Control a subprocess"
def add_arguments(self, parser):
parser.add_argument(
'--command',
dest='command',
help="Command to execute",
)
parser.add_argument(
'--mute_on_success',
dest='mute_on_success',
action='store_true',
help="Don't post any massage on success",
)
def handle(self, *args, **options):
try:
isomorphic_logging(logging, "Starting cron supervisor with command \"" + options['command'] + "\"")
if options['command']:
self.command = options['command']
else:
error_message = "Empty required parameter --command"
# log error
isomorphic_logging(logging, error_message, "error")
# send slack message
send_slack_message("Cron Supervisor Error: " + error_message)
# send email to admin
email_admin_error("Cron Supervisor Error", error_message)
raise ValueError(error_message)
if options['mute_on_success']:
self.mute_on_success = True
else:
self.mute_on_success = False
# running process
process = Popen([self.command], stdout=PIPE, stderr=PIPE, shell=True)
output, error = process.communicate()
if output:
isomorphic_logging(logging, "Output from cron:" + output)
# check for any subprocess error
if process.returncode != 0:
error_message = 'Command \"{command}\" - Error \nReturn code: {code}\n```{error}```'.format(
code=process.returncode,
error=error,
command=self.command,
)
self.handle_error(error_message)
else:
message = "Command \"{command}\" ended without error".format(command=self.command)
isomorphic_logging(logging, message)
# post message on slack if process isn't muted_on_success
if not self.mute_on_success:
send_slack_message(message)
except Exception as e:
error_message = 'Command \"{command}\" - Error \n```{error}```'.format(
error=e,
command=self.command,
)
self.handle_error(error_message)
def handle_error(self, error_message):
# log the error in local file
isomorphic_logging(logging, error_message)
# post message in slack
send_slack_message(error_message)
# email admin
email_admin_error("Cron Supervisor Error", error_message)
通过 cron_supervisor 被 cron 调用时脚本未正确执行的示例:
# -*- coding: utf-8 -*-
import json
import logging
import os
from django.conf import settings
from django.core.management.base import BaseCommand
from utils.lock import handle_lock
logging.basicConfig(
level=logging.INFO,
filename=os.path.join(settings.BASE_DIR, 'crons.log'),
format='%(asctime)s %(levelname)s: %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
class Command(BaseCommand):
help = "Envoi de l'argent en attente"
@handle_lock
def handle(self, *args, **options):
logging.info("some logs that won't be log (not called)")
logging.info("Those logs will be correcly logged")
此外,我还有一个我也不太了解的日志记录问题,我指定将日志存储在 cron-supervisor.log 中,但它们没有存储在那里,我不知道为什么。 (但这与我的主要问题无关,只是对调试没有帮助)
【问题讨论】:
-
根据
.virtualenvs/prod/bin/python的创建方式,它可能只是系统 Python 的符号链接。您需要做更多的工作才能真正激活virtualenv。此外,cron和交互式使用之间还有许多其他因素不同;请参阅the Stack Overflowcrontag info page,也许还有这个常见问题解答:stackoverflow.com/questions/22743548/cronjob-not-running -
另外,你似乎在重塑
subprocess.call()。如果你有一个相当最新的 Python,你可能应该看看subprocess.run()。另请参阅stackoverflow.com/questions/4256107/…,尤其是我的回答。 -
我已经使用
process = subprocess.Popen(bash_command, stdout=subprocess.PIPE, shell=True)来运行实际的脚本。我查看了您的链接,但找不到与我的问题相关的任何内容。.virtualenvs文件夹是使用 virtualenv_wrapper 创建的。