Безопасно ли передавать данные из нескольких параллельных процессов в один файл с помощью >>?
Я очищаю данные из Интернета, и у меня есть несколько процессов моего скребка, работающего параллельно.
Я хочу, чтобы выходные данные каждого из этих процессов попадали в один и тот же файл. Пока строки текста остаются неповрежденными и не смешиваются друг с другом, порядок строк не имеет значения. В UNIX я могу просто передать вывод каждого процесса в тот же файл с помощью оператора → ?
Ответы
Ответ 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