Python запрашивает/urllib3 NewConnectionError только тогда, когда скрипт запускается на cronjob из офиса

Странная проблема, не могу понять.

У меня есть скрипт, который использует библиотеку запросов Python и запускается на cronjob. Когда я дома через VPN, все работает нормально.

Если я нахожусь в офисе, cronjob возвращает ошибку соединения, точнее NewConnectionError [ошибка 60: время ожидания соединения] (которое вызывается urllib3). Странно то, что если я запускаю скрипт вручную из командной строки, у него нет проблем.

У меня есть только хорошее понимание того, как работают запросы/urllib3/cron. Я предполагаю, что соединение каким-то образом кэшируется, но я не уверен. Кто-нибудь знает, что может быть причиной этого?

Сам скрипт представляет собой утилиту синхронизации, которая создает соединение с API битбакета. Для этого я создал API-оболочку, которая, по сути, является просто объектом для построения запросов. Вот фрагмент из обертки:

def __init__(self, username, password):
    s = requests.Session()
    s.auth = (username, password)
    self._bitbucket_session = s

def _get_context(self, url, paging):
    try:
        r = self._bitbucket_session.get(url)
        if r.status_code == 403:
            raise self.BitbucketAPIError('BitbucketAPIError: {}'.format(r.reason))
        if 'error' in r.json():
            raise self.BitbucketAPIError('BitbucketAPIError: {}'.format(r.json()['error']['message']))
    except HTTPError as e:
        print("HTTP Error: {}".format(e))
    except ConnectTimeout as e:
        print("The request timed out while trying to connect to the remote server: {}".format(e))
    except ConnectionError as e:
        print("Connection Error: {}".format(e))
    except Timeout as e:
        print("Connection Timed out: {}".format(e))
    except RequestException as e:
        print("Unhandled exception: {}".format(e))

А вот и упрощенная версия клиента синхронизации, который «кронится»:

bapi = BitbucketApi(username, password)
# blah blah blah 
update_members()
update_repository()

bapi.close()

Вот метод закрытия:

def close(self):
    self._bitbucket_session.close()

person Andrew Schmitt    schedule 06.01.2016    source источник
comment
Работает ли эта работа cron на ноутбуке, который вы носите с собой из дома в офис?   -  person John Gordon    schedule 07.01.2016
comment
@ Хью, ты в этом уверен? Когда я настраиваю задания cron от своего имени, они запускаются от моего имени. В противном случае это была бы гигантская дыра в безопасности, не так ли?   -  person John Gordon    schedule 07.01.2016
comment
@JohnGordon: ты прав; Я думал о системных заданиях cron, которые по умолчанию имеют root, если вы не укажете пользователя для запуска.   -  person Hugh Bothwell    schedule 07.01.2016


Ответы (1)


Вероятно, здесь задействован прокси.

Когда скрипт запускается из вашего дома, прокси отсутствует или прокси настроен правильно, поэтому проблем нет.

При запуске из командной строки в вашем офисе среда оболочки правильно настроена для установки прокси-сервера HTTP/S через переменные среды:

export http_proxy="http://proxy.com:3128"
export https_proxy="https://proxy.com:3128"

(переменные в верхнем регистре также эффективны, т.е. HTTP_PROXY, HTTPS_PROXY)

Однако, когда сценарий запускается из cron, в среде не установлены прокси-переменные, и время ожидания запроса на подключение истекает. Вы создаете оболочку для сценария, а затем выполняете сценарий оболочки из cron. например

#!/bin/sh
export HTTP_PROXY="http://proxy:1234"
export HTTPS_PROXY="https://proxy:1234"
python your_script.py
person mhawke    schedule 06.01.2016
comment
Это имеет смысл, я устанавливаю эти переменные только через .bash_profile. Холодные бобы. Вечером настрою, а завтра проверю, когда вернусь и отчитаюсь. Спасибо, сэр. - person Andrew Schmitt; 07.01.2016