Bash выполняет цикл for, когда время находится вне рабочих часов

# -*- coding: utf-8 -*-

"""
Mail sender
"""

from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

import smtplib
import pystache
import codecs
import time

import sys
reload(sys)
sys.setdefaultencoding('utf-8')


HOST = 'smtp.exmail.qq.com'
PORT = 587
USER = 'your@mail.com'
PASS = 'yourpass'
FROM = 'your@mail.com'

SUBJECT = 'subject'
HTML_NAME = 'tpl.html'
CSV_NAME = 'list.txt'
FAILED_LIST = []


def send(mail_receiver, mail_to):
    # text = mail_text
    html = render(mail_receiver)

    # msg = MIMEMultipart('alternative')
    msg = MIMEMultipart('mixed')
    msg['From'] = FROM
    msg['To'] = mail_to.encode()
    msg['Subject'] = SUBJECT.encode()

    # msg.attach(MIMEText(text, 'plain', 'utf-8'))
    msg.attach(MIMEText(html, 'html', 'utf-8'))

    try:
        _sender = smtplib.SMTP(
            HOST,
            PORT
        )
        _sender.starttls()
        _sender.login(USER, PASS)
        _sender.sendmail(FROM, mail_to, msg.as_string())
        _sender.quit()
        print "Success"
    except smtplib.SMTPException, e:
        print e
        FAILED_LIST.append(mail_receiver + ',' + mail_to)


def render(name):
    _tpl = codecs.open(
        './html/' + HTML_NAME,
        'r',
        'utf-8'
    )
    _html_string = _tpl.read()
    return pystache.render(_html_string, {
        'receiver': name
    })


def main():
    ls = open('./csv/' + CSV_NAME, 'r')
    mail_list = ls.read().split('\r')

    for _receiver in mail_list:
        _tmp = _receiver.split(',')
        print 'Mail: ' + _tmp[0] + ',' + _tmp[1]
        time.sleep(20)
        send(_tmp[0], _tmp[1])

    print FAILED_LIST


main()
0
задан Mihaimyh 19 March 2019 в 08:57
поделиться

2 ответа

Шебанг содержит нежелательное пространство. На моем Ubuntu bash находится в /bin/bash.

Ваш, находится там:

type bash

В моем тесте разрывается цикл while, замените путь #!/bin/bash на результат предыдущей команды:

#!/bin/bash --
#set -x

while : ; do
 currenttime=$(date +%H:%M)
 if [[ "$currenttime" > "17:00" ]] || [[ "$currenttime" < "07:00" ]]; then
   for path in /backup_local/ARCHIVES/EAR_*; do
     [ -d "${path}" ] || continue # if not a directory, skip
     dirname="$(basename "${path}")"
     nohup /Restore -a /backup_local/ARCHIVES -c -I 0 -force -v > /backup_local/$dirname.txt &
     wait $!
     if [ $? -eq 0 ]; then
         rm -rf $path
         rm /backup_local/$dirname.txt
         echo $dirname >> /backup_local/completed.txt
     fi
   done &
 else
   echo "Restore can be ran only outside working hours!"
   break
 fi
done &
0
ответ дан Jay jargot 19 March 2019 в 08:57
поделиться

Ваш скрипт выглядит так в псевдокоде:

START
IF outside workinghours
    EXIT
ELSE
    RUN /Restore FOR EACH backupdir
GOTO START

Скрипт проверяет время только один раз, прежде чем запустить restore прогон (который будет вызывать /Restore для каждого каталога, который нужно восстановить в цикл for) Он продолжит запуск цикла for, пока не начнется рабочее время. Затем он выйдет.

например. если у вас есть 3 папки для восстановления, каждая занимает 2 часа; и вы запускаете сценарий в полночь; затем скрипт проверит, не в нерабочее ли оно время (и есть), и начнет восстановление для первой папки (в 0:00), после двух часов работы он начнет восстановление 2-й папки (в 2:00) еще через два часа начнется восстановление 3-й папки (на 4:00). Как только третья папка будет восстановлена, она снова проверит рабочее время. Поскольку теперь это только 6:00, то есть: вне рабочих часов, он начнет восстановление для первой папки (в 6:00), после двух часов работы он начнет восстановление 2-й папки (в 8:00 ), еще через два часа начнется восстановление 3-й папки (на 10:00). Это полдень, когда он делает следующую проверку рабочего времени; поскольку 12:00 находится в пределах 7:00 .. 17:00, сценарий теперь остановится. С сообщением об ошибке.

Возможно, вы хотите, чтобы восстановление запускалось только один раз для каждой папки, и перестаньте переходить к следующей папке, если начнется рабочее время.

#!/bin/bash
for path in /backup_local/ARCHIVES/EAR_*/; do
  currenttime=$(date +%H:%M)
  if [[ "$currenttime" > "7:00" ]] && [[ "$currenttime" < "17:00" ]]; then
      echo "Not restoring inside working hours!" 1>&2
      break
  fi
  dirname="$(basename "${path}")"
  /Restore -a /backup_local/ARCHIVES -c -I 0 -force -v > /backup_local/$dirname.txt
  # handle exit code
done

обновление

Я только что заметил ваш либеральный разброс & для фоновых заданий. Предположительно это позволяет запускать скрипт из удаленной оболочки. не

Что это действительно будет делать:

  1. будет выполнять все итерации по каталогам восстановления параллельно. Это может создать узкое место в вашем хранилище (если каталоги для восстановления на / с совместно используют одно и то же оборудование)
  2. это будет фоновый весь цикл восстановления и немедленно вернется к проверке вне часов. если проверка прошла успешно, она создаст другой цикл для восстановления (и фон его). затем он вернется к проверке в нерабочее время и вызовет другой фоновый цикл для восстановления. До рассвета у вас, вероятно, несколько тысяч фоновых потоков для восстановления каталогов. Скорее всего, вы превысили свои ресурсы и процесс был убит.

В моем примере скрипта, приведенном выше, пропущены все фоновые изображения (и nohup).

Если вы хотите запустить скрипт из удаленной оболочки (и выйти из оболочки после его запуска), просто запустите его с

nohup restore-script.sh &

В качестве альтернативы вы можете использовать

echo "restore-script.sh" | at now

или использовать cron-job (если применимо)

0
ответ дан umläute 19 March 2019 в 08:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: