Подтвердить что ты не робот

Безопасно ли передавать данные из нескольких параллельных процессов в один файл с помощью >>?

Я очищаю данные из Интернета, и у меня есть несколько процессов моего скребка, работающего параллельно.

Я хочу, чтобы выходные данные каждого из этих процессов попадали в один и тот же файл. Пока строки текста остаются неповрежденными и не смешиваются друг с другом, порядок строк не имеет значения. В UNIX я могу просто передать вывод каждого процесса в тот же файл с помощью оператора → ?

4b9b3361

Ответ 1

Нет. Не гарантируется, что линии останутся неповрежденными. Они могут смешиваться.

Из поиска на основе ответа liori я нашел this:

Запросы на запись в байтах {PIPE_BUF} не должны чередоваться с данными других процессов, выполняющих записи на одном и том же канале. Записи, превышающие байты {PIPE_BUF}, могут чередоваться на произвольных границах с записью другими процессами, независимо от того, установлен ли флаг O_NONBLOCK для флагов состояния файла.

Таким образом, строки, длина которых не превышает {PIPE_BUF}, не остаются неизменными.

Ответ 2

Возможно, вам интереснее использовать gnu parallel: http://www.gnu.org/s/parallel/ Например, если вы занимались поиском сайтов:

stackoverflow.com, stackexchange.com, fogcreek.com 

вы могли бы сделать что-то вроде этого

(echo stackoverflow.com; echo stackexchange.com; echo fogcreek.com) | parallel -k your_spider_script

а вывод буферизуется параллельным и из-за опции -k, возвращенной вам в порядке списка выше. Реальный пример (в основном скопированный со второго параллельного скринкаста):

 ~ $ (echo stackoverflow.com; echo stackexchange.com; echo fogcreek.com) | parallel -k ping -c 1 {}


PING stackoverflow.com (64.34.119.12): 56 data bytes

--- stackoverflow.com ping statistics ---
1 packets transmitted, 0 packets received, 100.0% packet loss
PING stackexchange.com (64.34.119.12): 56 data bytes

--- stackexchange.com ping statistics ---
1 packets transmitted, 0 packets received, 100.0% packet loss
PING fogcreek.com (64.34.80.170): 56 data bytes
64 bytes from 64.34.80.170: icmp_seq=0 ttl=250 time=23.961 ms

--- fogcreek.com ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 23.961/23.961/23.961/0.000 ms

В любом случае, ymmv

Ответ 3

Как правило, нет.

В Linux это возможно, если выполняются два условия: каждая строка записывается в одну операцию, а строка не больше, чем PIPE_SIZE (обычно такая же, как PAGE_SIZE, обычно 4096). Но... я бы не рассчитывал на это; это может измениться.

Лучше использовать какой-то реальный механизм ведения журнала, например syslog.

Ответ 4

Вам нужно убедиться, что вы пишете целые строки в операциях с одиночной записью (поэтому, если вы используете какую-либо форму stdio, вам нужно установить ее для буферизации строк, по крайней мере, для самой длинной линии, которую вы можете вывести.) Поскольку оболочка использует O_APPEND для → перенаправления, тогда все ваши записи будут автоматически добавляться к файлу без каких-либо дальнейших действий с вашей стороны.

Ответ 5

Используйте временные файлы и объединяйте их вместе. Это единственный безопасный способ сделать то, что вы хотите сделать, и там (вероятно) будет незначительная потеря производительности таким образом. Если производительность действительно является проблемой, попробуйте убедиться, что ваш каталог /tmp является файловой системой на основе RAM и помещает туда временные файлы. Таким образом, временные файлы хранятся в ОЗУ вместо жесткого диска, поэтому чтение/запись их почти мгновенно.

Ответ 6

Определенно нет, у меня было управление журналом script, где я предполагал, что это сработало, и это действительно сработало, пока я не переместил его на сервер обработки под нагрузкой. Не хороший день... Но в основном вы в конечном итоге иногда перепутали строки.

Если я пытаюсь захватить из нескольких источников, гораздо проще (и проще отлаживать) наличие нескольких файлов "бумажных трасс", и если мне нужен общий файл журнала, объединитесь на основе метки времени (вы используют временные метки, правильно?) или, как сказал liori, syslog.

Ответ 7

Вкратце, нет. >> не учитывает несколько процессов.

Ответ 8

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

Подумайте об Apache2 с протоколированием каналов (с чем-то вроде распространения на другом конце трубы, если вы чувствуете амбициозность). Это подход, который требуется, с несколькими потоками/процессами, использующими один процесс ведения журнала.

Ответ 9

Как уже упоминалось выше, он довольно взломан, но работает довольно хорошо =)

( ping stackoverflow.com & ping stackexchange.com & ping fogcreek.com ) | cat

то же самое с ' → ':

( ping stackoverflow.com & ping stackexchange.com & ping fogcreek.com ) >> log

и с exec на последнем вы сохраняете один процесс:

( ping stackoverflow.com & ping stackexchange.com & exec ping fogcreek.com ) | cat