UNIX с именем PIPE конец файла - PullRequest
       13

UNIX с именем PIPE конец файла

3 голосов
/ 24 сентября 2011

Я пытаюсь использовать unix именованный канал для вывода статистики работающей службы.Я намереваюсь предоставить интерфейс, подобный /proc, где можно увидеть живую статистику, перебирая файл.

Я использую код, подобный этому, в моем коде Python:

while True:
  f = open('/tmp/readstatshere', 'w')
  f.write('some interesting stats\n')
  f.close()

/tmp/readstatshere - это именованный канал, созданный mknod.

Затем я вижу его, чтобы посмотреть статистику:

$ cat /tmp/readstatshere
some interesting stats

В большинстве случаев он работает нормально.Тем не менее, если я выполняю запись несколько раз подряд, иногда я получаю несколько строк some interesting stats вместо одной.Один или два раза он даже бесконечно печатал эту строку, пока я не убил ее.Единственное исправление, которое у меня есть, это установка задержки, скажем, 500 мс после f.close(), чтобы предотвратить эту проблему.

Я хотел бы знать, почему именно это происходит, и если есть лучшееспособ справиться с этим.

Заранее спасибо

Ответы [ 5 ]

1 голос
/ 08 августа 2012

Я думаю, вы должны использовать предохранитель.он имеет привязки Python, см. http://pypi.python.org/pypi/fuse-python/, это позволяет вам составлять ответы на вопросы, сформулированные как системные вызовы файловой системы posix

1 голос
/ 29 июня 2012

А как насчет сокета UNIX вместо канала?

В этом случае вы можете реагировать на каждое соединение, своевременно предоставляя свежие данные.

Единственным недостатком является то, что вы не можетеcat данные;вам нужно будет создать новый дескриптор сокета и connect() к файлу сокета.

MYSOCKETFILE = '/tmp/mysocket'
import socket
import os
try:
    os.unlink(MYSOCKETFILE)
except OSError: pass
s = socket.socket(socket.AF_UNIX)
s.bind(MYSOCKETFILE)
s.listen(10)
while True:
    s2, peeraddr = s.accept()
    s2.send('These are my actual data')
    s2.close()

Программа, запрашивающая этот сокет:

MYSOCKETFILE = '/tmp/mysocket'
import socket
import os
s = socket.socket(socket.AF_UNIX)
s.connect(MYSOCKETFILE)
while True:
    d = s.recv(100)
    if not d: break
    print d
s.close()
1 голос
/ 24 сентября 2011

Труба здесь просто неправильное решение.Если вы хотите представить непротиворечивый снимок внутреннего состояния вашего процесса, запишите его в временный файл, а затем переименуйте его в «общедоступное» имя.Это предотвратит все проблемы, которые могут возникнуть из-за того, что другие процессы читают состояние во время его обновления.Кроме того, НЕ делайте этого в занятом цикле, но в идеале в потоке, который спит не менее одной секунды между обновлениями.

0 голосов
/ 25 июня 2012

Вам нужно unlink трубу после того, как вы выполните close. Я думаю, это потому, что существует состояние гонки, при котором канал может быть открыт для чтения снова до завершения cat, и поэтому он видит больше данных и считывает их, что приводит к кратным числам «некоторых интересных характеристик».

В основном вы хотите что-то вроде:

while True:
    os.mkfifo(the_pipe)
    f = open(the_pipe, 'w')
    f.write('some interesting stats')
    f.close()
    os.unlink(the_pipe)

Обновление 1: вызов mkfifo

Обновление 2: как отмечается в комментариях, в этом коде также есть условие гонки с несколькими потребителями.

0 голосов
/ 24 сентября 2011

Не записывать в реальный файл. Это не то, что делает /proc. Procfs представляет виртуальную (не поддерживаемую диском) файловую систему, которая производит требуемую информацию по запросу. Вы можете сделать то же самое, но будет проще, если он не привязан к файловой системе. Вместо этого просто запустите веб-сервис внутри вашей программы Python и сохраните статистику в памяти. Когда приходит запрос на статистику, сформулируйте их в красивую строку и верните их. Большую часть времени вам не нужно тратить циклы обновления файла, который может даже не читаться до следующего обновления.

...