Python 脚本未从 Cron 执行
Python script not executed from Cron
我正在尝试 运行 来自 Cron 的 Python 脚本,但它不起作用。我已经尝试了我在多个 Whosebug questions.The 机器上看到的所有东西是 Raspberry 运行ning Raspbian。下面这段代码是crontab
的版本:
PATH=/usr/sbin:/usr/bin:/sbin/bin:/sbin:/bin:/home/pi/miniconda/bin:/usr/local/bin:/usr/local/sbin
*/5 * * * * rsync -az --timeout=10 --progress pritms@bigdata.trainhealthmanagement.com:Upload/*.csv /home/pi/PAD-S100/PAD-S100-Bloque_Motor/from_repo/ | /bin/sh /home/pi/PAD-S100/PAD-S100-Bloque_Motor/adddate_to_logs.sh >> /home/pi/PAD-S100/PAD-S100-Bloque_Motor/log.log 2>&1
*/5 * * * * /bin/sh /home/pi/PAD-S100/PAD-S100-Bloque_Motor/from_repo/launcher.sh | /bin/sh /home/pi/PAD-S100/PAD-S100-Bloque_Motor/adddate_to_logs.sh >> /home/pi/PAD-S100/PAD-S100-Bloque_Motor/log.log 2>&1
*/30 * * * * rm /home/pi/PAD-S100/PAD-S100-Bloque_Motor/log.log
* * * * * /usr/bin/python /home/pi/PAD-S100/PAD-S100-Bloque_Motor/from_repo/event_management.py | /bin/sh /home/pi/PAD-S100/PAD-S100-Bloque_Motor/adddate_to_logs.sh >> home/pi/PAD-S100/PAD-S100-Bloque_Motor/log.log 2>&1
0 0 * * * rm /home/pi/PAD-S100/PAD-S100-Bloque_Motor/from_repo/*.csv | /bin/sh /home/pi/PAD-S100/PAD-S100-Bloque_Motor/adddate_to_logs.sh >> /home/pi/PAD-S100/PAD-S100-Bloque_Motor/log.log 2>&1
Crontab
观察:
- 包括从
echo $PATH
获得的路径。
launcher.sh
、addddate_to_logs.sh
和
event_management
是使用命令 sudo chmod a+x <file_name>
. 的可执行文件
log.log
文件没有显示任何异常。
系统日志文件 /var/log/syslog
有以下日志:
Feb 27 15:11:08 raspberrypi cron[21814]: sendmail: Cannot open :25
Feb 27 15:12:01 raspberrypi rsyslogd-2007: action 'action 17' suspended, next retry is Mon Feb 27 15:13:31 2017 [try http://www.rsyslog.com/e/2007 ]
Feb 27 15:12:01 raspberrypi CRON[22209]: (pi) CMD (/usr/bin/python /home/pi/PAD-S100/PAD-S100-Bloque_Motor/from_repo/event_management.py | /bin/sh /home/pi/PAD-S100/PAD-S100-Bloque_Motor/adddate_to_logs.sh >> home/pi/PAD-S100/PAD-S100-Bloque_Motor/log.log 2>&1)
Feb 27 15:12:09 raspberrypi sSMTP[22212]: Unable to set UsesSTARTTILS=""
Feb 27 15:12:09 raspberrypi sSMTP[22212]: Unable to locate
Feb 27 15:12:09 raspberrypi cron[21814]: sendmail: Cannot open :25
Feb 27 15:12:09 raspberrypi sSMTP[22212]: Cannot open :25
Feb 27 15:12:09 raspberrypi CRON[22205]: (pi) MAIL (mailed 178 bytes of output but got status 0x0001 from MTA#012)
我们可以观察到失败的 crontab 行很可能是 python 脚本之一。由于我不是 Linux 方面的专家,我相信这可能与 sSMTP
有关。每次调用 cron python 脚本后都会出现相同类型的错误日志。但是我不知道如何修复它或配置本地电子邮件。
这是 event_management.py
文件的一段代码:
#!/usr/bin/python
# -*- coding: utf-8 -*-
import imaplib
import email
import csv
import datetime
EMAIL = <email_user>
FROM_PWD = <password>
SMTP_SERVER = 'mail.o365.alstom.com'
datum = dict()
translate = {'#09': 1, '#0A': 2, '#0B': 3, '#0C': 4}
def connect_imap():
mail = imaplib.IMAP4_SSL(SMTP_SERVER)
mail.login(EMAIL, FROM_PWD)
return mail
def read_email_from_gmail(writer, mail):
mail.select('BRMS')
kind, data = mail.search(None, 'ALL')
mail_ids = data[0]
id_list = mail_ids.split()
first_email_id = int(id_list[0])
latest_email_id = int(id_list[-1])
for i in range(latest_email_id, first_email_id, -1):
typ, data = mail.fetch(i, '(RFC822)')
for response_part in data:
if isinstance(response_part, tuple):
msg = email.message_from_string(response_part[1])
for part in msg.walk():
if part.get_content_type() == 'text/html':
content = part.get_payload()
manage_email_content(content, writer)
return 0
def manage_email_content(content, writer):
content = content.split('\n')
for i, line in enumerate(content):
if 'Alert description' in line:
line = line.split()
datum['Event code'] = line[-1][4:]
if line[-1][:3] in translate:
datum['Motor block num'] = translate[line[-1][:3]]
else:
datum['Motor block num'] = 'Defecto ajeno al bloque motor'
elif 'Alert condition' in line:
line = line.split()
datum['Code description'] = ' '.join(line[4:])
elif 'Unit id' in line:
line = line.split()
datum['Train num'] = line[3][3:]
elif 'Alert raised' in line:
line = line.split()
datum['Date'] = line[4][:10]
datum['Time'] = line[4][11:]
writer.writerow(datum)
print datum
return 0
def move_to_trash_before_date(mail, folder, days_before):
# required to perform search, m.list() for all lables, '[Gmail]/Sent Mail'
no_of_msgs = int(mail.select(folder)[1][0])
print("- Found a total of {1} messages in '{0}'.".format(folder, no_of_msgs))
before_date = (datetime.date.today() - datetime.timedelta(days_before)).strftime("%d-%b-%Y")
typ, data = mail.search(None, '(BEFORE {0})'.format(before_date)) # search pointer for msgs before before_date
if data != ['']: # if not empty list means messages exist
no_msgs_del = data[0].split()[-1] # last msg id in the list
print("- Marked {0} messages for removal with dates before {1} in '{2}'.".format(no_msgs_del, before_date, folder))
mail.store("1:{0}".format(no_msgs_del), '+X-GM-LABELS', '\Trash') # move to trash
empty_folder(mail, 'Elementos eliminados', do_expunge=True) # can send do_expunge=False, default True
else:
print("- Nothing to remove.")
return 0
def empty_folder(mail, folder, do_expunge=True):
mail.select(folder) # select all trash
mail.store("1:*", '+FLAGS', '\Deleted') # Flag all Trash as Deleted
if do_expunge: # See Gmail Settings -> Forwarding and POP/IMAP -> Auto-Expunge
mail.expunge() # not need if auto-expunge enabled
else:
print("Expunge was skipped.")
return 0
def disconnect_imap(mail):
mail.close()
mail.logout()
return 0
def main():
with open('email_data.csv', 'w') as f:
writer = csv.DictWriter(f, fieldnames=['Time', 'Date', 'Train num', 'Motor block num',
'Event code', 'Code description'], delimiter=';')
try:
m = connect_imap()
writer.writeheader()
read_email_from_gmail(writer, m)
move_to_trash_before_date(m, 'BRMS', 15) # inbox cleanup, before 15 days
disconnect_imap(m)
except Exception, e:
print str(e)
if __name__ == "__main__":
main()
event_management
文件连接到 Outlook 电子邮件文件夹,读取电子邮件并使用从电子邮件内容中提取的数据构建 CSV 文件。这个文件可以正常工作,已经过测试;手动执行时效果很好(不使用 Cron)。所以我不确定它是否与系统日志中出现的 sSMTP
问题有关。
我会感谢各种帮助或建议!
经过测试和阅读其他用户的回答,我发现了问题所在。它是两个不直接相关的不同问题的组合,但一起使这个问题调试起来很麻烦。
第一个问题:
log.log
文件包含来自三个不同可执行文件的日志和错误,因此我没有注意到 evet_management
文件没有正确的权限。我没有很好地应用chmod
命令,我没有注意到它,因为它包含很多数据。
结论1:一个cronjob
,一个log
个文件。
结论 2: /var/log/syslog
包含来自各种资源的大量数据,因此在尝试调试时可能会使您感到困惑。最好分开生成日志文件。
第二个问题:
我的机器上安装了两个 Python 发行版。当我手动执行脚本时,会使用一个。当 Cron 执行脚本时,会使用另一个脚本。此外,当第一个问题得到解决时,我注意到了这一点。当 运行 Python 脚本中的 log
文件中的 运行 时,我收到模块未找到的错误,但在手动执行时完美运行。因此我看到当使用 pip install <module-name>
时,它只适用于一个发行版。要检查我使用的 Python 的哪个版本:
which Python
结论:要聪明,不要像我一样,不要乱搞多个Python发行版。
奖励:始终使用完整路径以保持清晰。 Cron
与你的 env
不同。
我正在尝试 运行 来自 Cron 的 Python 脚本,但它不起作用。我已经尝试了我在多个 Whosebug questions.The 机器上看到的所有东西是 Raspberry 运行ning Raspbian。下面这段代码是crontab
的版本:
PATH=/usr/sbin:/usr/bin:/sbin/bin:/sbin:/bin:/home/pi/miniconda/bin:/usr/local/bin:/usr/local/sbin
*/5 * * * * rsync -az --timeout=10 --progress pritms@bigdata.trainhealthmanagement.com:Upload/*.csv /home/pi/PAD-S100/PAD-S100-Bloque_Motor/from_repo/ | /bin/sh /home/pi/PAD-S100/PAD-S100-Bloque_Motor/adddate_to_logs.sh >> /home/pi/PAD-S100/PAD-S100-Bloque_Motor/log.log 2>&1
*/5 * * * * /bin/sh /home/pi/PAD-S100/PAD-S100-Bloque_Motor/from_repo/launcher.sh | /bin/sh /home/pi/PAD-S100/PAD-S100-Bloque_Motor/adddate_to_logs.sh >> /home/pi/PAD-S100/PAD-S100-Bloque_Motor/log.log 2>&1
*/30 * * * * rm /home/pi/PAD-S100/PAD-S100-Bloque_Motor/log.log
* * * * * /usr/bin/python /home/pi/PAD-S100/PAD-S100-Bloque_Motor/from_repo/event_management.py | /bin/sh /home/pi/PAD-S100/PAD-S100-Bloque_Motor/adddate_to_logs.sh >> home/pi/PAD-S100/PAD-S100-Bloque_Motor/log.log 2>&1
0 0 * * * rm /home/pi/PAD-S100/PAD-S100-Bloque_Motor/from_repo/*.csv | /bin/sh /home/pi/PAD-S100/PAD-S100-Bloque_Motor/adddate_to_logs.sh >> /home/pi/PAD-S100/PAD-S100-Bloque_Motor/log.log 2>&1
Crontab
观察:
- 包括从
echo $PATH
获得的路径。 launcher.sh
、addddate_to_logs.sh
和event_management
是使用命令sudo chmod a+x <file_name>
. 的可执行文件
log.log
文件没有显示任何异常。
系统日志文件 /var/log/syslog
有以下日志:
Feb 27 15:11:08 raspberrypi cron[21814]: sendmail: Cannot open :25
Feb 27 15:12:01 raspberrypi rsyslogd-2007: action 'action 17' suspended, next retry is Mon Feb 27 15:13:31 2017 [try http://www.rsyslog.com/e/2007 ]
Feb 27 15:12:01 raspberrypi CRON[22209]: (pi) CMD (/usr/bin/python /home/pi/PAD-S100/PAD-S100-Bloque_Motor/from_repo/event_management.py | /bin/sh /home/pi/PAD-S100/PAD-S100-Bloque_Motor/adddate_to_logs.sh >> home/pi/PAD-S100/PAD-S100-Bloque_Motor/log.log 2>&1)
Feb 27 15:12:09 raspberrypi sSMTP[22212]: Unable to set UsesSTARTTILS=""
Feb 27 15:12:09 raspberrypi sSMTP[22212]: Unable to locate
Feb 27 15:12:09 raspberrypi cron[21814]: sendmail: Cannot open :25
Feb 27 15:12:09 raspberrypi sSMTP[22212]: Cannot open :25
Feb 27 15:12:09 raspberrypi CRON[22205]: (pi) MAIL (mailed 178 bytes of output but got status 0x0001 from MTA#012)
我们可以观察到失败的 crontab 行很可能是 python 脚本之一。由于我不是 Linux 方面的专家,我相信这可能与 sSMTP
有关。每次调用 cron python 脚本后都会出现相同类型的错误日志。但是我不知道如何修复它或配置本地电子邮件。
这是 event_management.py
文件的一段代码:
#!/usr/bin/python
# -*- coding: utf-8 -*-
import imaplib
import email
import csv
import datetime
EMAIL = <email_user>
FROM_PWD = <password>
SMTP_SERVER = 'mail.o365.alstom.com'
datum = dict()
translate = {'#09': 1, '#0A': 2, '#0B': 3, '#0C': 4}
def connect_imap():
mail = imaplib.IMAP4_SSL(SMTP_SERVER)
mail.login(EMAIL, FROM_PWD)
return mail
def read_email_from_gmail(writer, mail):
mail.select('BRMS')
kind, data = mail.search(None, 'ALL')
mail_ids = data[0]
id_list = mail_ids.split()
first_email_id = int(id_list[0])
latest_email_id = int(id_list[-1])
for i in range(latest_email_id, first_email_id, -1):
typ, data = mail.fetch(i, '(RFC822)')
for response_part in data:
if isinstance(response_part, tuple):
msg = email.message_from_string(response_part[1])
for part in msg.walk():
if part.get_content_type() == 'text/html':
content = part.get_payload()
manage_email_content(content, writer)
return 0
def manage_email_content(content, writer):
content = content.split('\n')
for i, line in enumerate(content):
if 'Alert description' in line:
line = line.split()
datum['Event code'] = line[-1][4:]
if line[-1][:3] in translate:
datum['Motor block num'] = translate[line[-1][:3]]
else:
datum['Motor block num'] = 'Defecto ajeno al bloque motor'
elif 'Alert condition' in line:
line = line.split()
datum['Code description'] = ' '.join(line[4:])
elif 'Unit id' in line:
line = line.split()
datum['Train num'] = line[3][3:]
elif 'Alert raised' in line:
line = line.split()
datum['Date'] = line[4][:10]
datum['Time'] = line[4][11:]
writer.writerow(datum)
print datum
return 0
def move_to_trash_before_date(mail, folder, days_before):
# required to perform search, m.list() for all lables, '[Gmail]/Sent Mail'
no_of_msgs = int(mail.select(folder)[1][0])
print("- Found a total of {1} messages in '{0}'.".format(folder, no_of_msgs))
before_date = (datetime.date.today() - datetime.timedelta(days_before)).strftime("%d-%b-%Y")
typ, data = mail.search(None, '(BEFORE {0})'.format(before_date)) # search pointer for msgs before before_date
if data != ['']: # if not empty list means messages exist
no_msgs_del = data[0].split()[-1] # last msg id in the list
print("- Marked {0} messages for removal with dates before {1} in '{2}'.".format(no_msgs_del, before_date, folder))
mail.store("1:{0}".format(no_msgs_del), '+X-GM-LABELS', '\Trash') # move to trash
empty_folder(mail, 'Elementos eliminados', do_expunge=True) # can send do_expunge=False, default True
else:
print("- Nothing to remove.")
return 0
def empty_folder(mail, folder, do_expunge=True):
mail.select(folder) # select all trash
mail.store("1:*", '+FLAGS', '\Deleted') # Flag all Trash as Deleted
if do_expunge: # See Gmail Settings -> Forwarding and POP/IMAP -> Auto-Expunge
mail.expunge() # not need if auto-expunge enabled
else:
print("Expunge was skipped.")
return 0
def disconnect_imap(mail):
mail.close()
mail.logout()
return 0
def main():
with open('email_data.csv', 'w') as f:
writer = csv.DictWriter(f, fieldnames=['Time', 'Date', 'Train num', 'Motor block num',
'Event code', 'Code description'], delimiter=';')
try:
m = connect_imap()
writer.writeheader()
read_email_from_gmail(writer, m)
move_to_trash_before_date(m, 'BRMS', 15) # inbox cleanup, before 15 days
disconnect_imap(m)
except Exception, e:
print str(e)
if __name__ == "__main__":
main()
event_management
文件连接到 Outlook 电子邮件文件夹,读取电子邮件并使用从电子邮件内容中提取的数据构建 CSV 文件。这个文件可以正常工作,已经过测试;手动执行时效果很好(不使用 Cron)。所以我不确定它是否与系统日志中出现的 sSMTP
问题有关。
我会感谢各种帮助或建议!
经过测试和阅读其他用户的回答,我发现了问题所在。它是两个不直接相关的不同问题的组合,但一起使这个问题调试起来很麻烦。
第一个问题:
log.log
文件包含来自三个不同可执行文件的日志和错误,因此我没有注意到 evet_management
文件没有正确的权限。我没有很好地应用chmod
命令,我没有注意到它,因为它包含很多数据。
结论1:一个cronjob
,一个log
个文件。
结论 2: /var/log/syslog
包含来自各种资源的大量数据,因此在尝试调试时可能会使您感到困惑。最好分开生成日志文件。
第二个问题:
我的机器上安装了两个 Python 发行版。当我手动执行脚本时,会使用一个。当 Cron 执行脚本时,会使用另一个脚本。此外,当第一个问题得到解决时,我注意到了这一点。当 运行 Python 脚本中的 log
文件中的 运行 时,我收到模块未找到的错误,但在手动执行时完美运行。因此我看到当使用 pip install <module-name>
时,它只适用于一个发行版。要检查我使用的 Python 的哪个版本:
which Python
结论:要聪明,不要像我一样,不要乱搞多个Python发行版。
奖励:始终使用完整路径以保持清晰。 Cron
与你的 env
不同。