"filedescriptor вне диапазона в select ()" при использовании подпроцесса python с rsync - PullRequest
5 голосов
/ 08 октября 2011

код ниже используется для синхронизации загруженного изображения в другое место.это работает, но по прошествии некоторого времени (около 10 дней) служба не работает, выдает ошибку: «filedescriptor вне диапазона в select ()», но перезапуск службы решает проблему.

# sync.py

def sync_file(source_pic, hashval, retry_num=3):

    pic_path = os.path.join(gen_dir(hashval), os.path.split(source_pic)[1])
    filename = tempfile.mkstemp()[1]
    with open(filename, 'w') as f:
        f.write(pic_path)

    for sync_path in options.sync_paths:
        try_num = 0
        rsync_cmd = ['rsync','-au', '--files-from='+filename, options.pic_path, sync_path]

        while try_num < retry_num:
            proc = subprocess.Popen(rsync_cmd,stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            stdout_value, stderr_value = proc.communicate()

            if len(stderr_value) != 0:
                logger.error('sync failed: %s' % stderr_value)
                try_num = try_num + 1
                #raise UploadException('sync failed')
            else:
                break

    os.remove(filename)

информация журнала:

File "/path/to/sync.py", line 25, in sync_file
    stdout_value, stderr_value = proc.communicate()
File "/usr/lib/python2.6/subprocess.py", line 691, in communicate
    return self._communicate(input)
File "/usr/lib/python2.6/subprocess.py", line 1211, in _communicate
    rlist, wlist, xlist = select.select(read_set, write_set, [])
    ValueError: filedescriptor out of range in select()

есть ли открытые дескрипторы файлов, которые вызывают ошибку?кажется, что подпроцесс не закрывает дескриптор файла, поэтому, когда он запускается 1024 раза, дескриптор файла выходит за пределы допустимого диапазона.(мы используем python 2.6, подпроцесс вынужден использовать select.select (), который имеет ограничение в 1024 дескриптора файла, даже если доступен epoll)

Ответы [ 2 ]

2 голосов
/ 08 октября 2011

Вы можете вручную закрыть дескрипторы файлов.После звонка communicate, позвоните proc.stderr.close() и proc.stdout.close().

0 голосов
/ 06 января 2017

https://bugzilla.redhat.com/show_bug.cgi?id=609020

До Python 2.7 программы, которые использовали ulimit -n для обеспечения связи с большим количеством подпроцессов, могли одновременно отслеживать только 1024 файловых дескриптора, что вызывало исключение:

ValueError: filedescriptor out of range in select()

Это произошло из-за того, что модуль подпроцесса использовал системный вызов select.Теперь модуль использует системный вызов poll, устраняя это ограничение.

возможное исправление: используйте python 2.7+ или перенесите код с помощью poll.

...