LINUX.ORG.RU

Медленное выполнение скрипта при запуске через Cron

 , ,


0

3

Добрый день! Есть скрипт, задача которого взять текстовый «файл 1», каждую его строку обрезать под совпадение по регулярному выражению и результат добавить в «файл 2». Если скрипт запускать руками, то он выполняется секунд 20-30. Если процесс запускается через cron или systemd, то время выполнения скрипта растягивается до 10 минут. С правами все хорошо, когда скрипт запускается через cron или systemd, то «файл 2» создается, но его размер набегает крайне медленно. Не могу понять почему. Подскажите, куда хотя бы покопать для анализа такой «фишки»?


Поднять локальную почту, включить отправку stdout/stderr в cron, добавить echo/printf в скрипт и смотреть на результат, прилетающий на почту.

Не помню, шлёт ли systemd.timer что-то в журнал, но systemd.service точно шлёт, потому при использовании systemd.timer ты можешь смотреть journald <непомнюкакаяопция> <твойсервис>.

mord0d ★★★★★
()
Ответ на: комментарий от eternal_sorrow

Возможно, спорить не стану, не помню. У меня нет под рукой Linux, не говоря уже про systemd, так бы я ман прочитал.

mord0d ★★★★★
()
Ответ на: комментарий от legolegs

Разве вам libastral.so не завезли? ☺

Скорее всего пользовательский скрипт/юнит исполняется с повышенным niceness. Но если нет нагрузки, то может я и не прав. ☺

mord0d ★★★★★
()
Ответ на: комментарий от legolegs

Кусок, непосредственно который тупит при запуске через планировщики:

strings=$(cat $SAMPLETEMP)
for string in ${strings[*]}
do
echo «$string» | sed -E ‘s;(.+)([\t]+)/(.*)[\t]+(.+);\1 \3 \5;’ >> $SAMPLE
done

файл xx.service:
[Unit] Description=

[Service]
Type=oneshot
ExecStart=/bin/bash /path/script.sh

Или crontab:
SHELL=/bin/bash
*/10 * * * * timeout 590s /path/script.sh

PS пробовал */10 * * * * nice timeout 590s /path/script.sh - результат не поменялся

kes83
() автор топика

У разных реализаций крона есть свои особенности запуска задач. Например, такая штука как RANDOM_DELAY в минутах в /etc/anacrontab.

Как ты замеряешь время выполнения скрипта? Отмечаешь время начала и время окончания внутри скрипта (и именно этот интервал в твоём случае длится до 10 минут вместо 20-30 сек), или только по времени окончания?

Есть подозрение, что он у тебя просто стартует, согласно конфигурации, через 10 минут после запланированного тобой времени.

blexey ★★★★★
()
Ответ на: комментарий от blexey

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

Все те же вещи наблюдаются, если запустить скрипт руками, только время на обработку будет уже секунды, а не минуты.

kes83
() автор топика
Ответ на: комментарий от kes83

начни с оптимизации скрипта. нет никакого смысла в твоем случае вызывать sed на каждую строку отдельно. это отдельный вызов system(). это дорого.

anonymous
()
Ответ на: комментарий от kes83

strings=$(cat $SAMPLETEMP)
for string in ${strings[*]}
do
echo «$string» | sed -E ‘s;(.+)([\t]+)/(.*)[\t]+(.+);\1 \3 \5;’ >> $SAMPLE
done

Что за дичь?!

sed -E ‘s;(.+)([\t]+)/(.*)[\t]+(.+);\1 \3 \5;’ "$SAMPLETEMP" > $SAMPLE

Ну и да, прочитай про разметку. Ссылки над кнопкой [Поместить] и внизу (каждой) страницы.

mord0d ★★★★★
()
Ответ на: комментарий от anonymous

А может быть такое, что при ручном запуске скрипта system() вызывается последовательно для каждого sed, но не дожидаясь окончания обработки предыдущей строки? А когда через планировщик - то каждый последующий sed дергается только после завершения предыдущего?

kes83
() автор топика
Ответ на: комментарий от kes83

нет, будет всегда последовательно.

anonymous
()
Ответ на: комментарий от suspend

При копировании сюда намудрил с переносом строк и почикал часть текста. Регулярка длиннее

kes83
() автор топика

locale может влиять. возможно не твой случай, но к примеру

LANG=C grep -i …

работает быстрее чем

LANG=en_US.UTF-8 grep -i …

futurama ★★★★★
()
Ответ на: комментарий от kes83

Зачем пихать выхлоп cat в энву, после циклом перебирать, выводить и пайпом обрабатывать?

Нужно посторчно файл прочитать и разбить между табами в энвы, вот на баше как-то так:

while IFS=$'\t' read -r s1 s2 s3 s4 s5; do
    printf '%s\n' "$s1 $s3 $s5" >> $SAMPLE
done < "$SAMPLETEMP"

А вобще sed умеет всё это из коробки:

# Поправит файл $SAMPLETEMP
sed -E 's|^(.+)([\t]+)/(.*)[\t]+(.+)$|\1 \3 \5|g' -i $SAMPLETEMP
# Поправит запишет в файл $SAMPLE
sed -E 's|^(.+)([\t]+)/(.*)[\t]+(.+)$|\1 \3 \5|g' $SAMPLETEMP > $SAMPLE
WoozyMasta
()
Ответ на: комментарий от kes83

Тебе уже правильно написали, что скрипт у тебя лучше переписать. Но всё равно непонятно, почему даже твой кривой скрипт так тормозит. Он должен работать со скоростью диска. Разве что ты запускаешь его под виндой и на каждый >> срабатывает проверка антивирусом.

legolegs ★★★★★
()
Ответ на: комментарий от legolegs

Про неоптимальный код скрипта дело ясное. Была задача максимально быстро парсить лог. Над производительностью скрипта обязательно поработаю. Вопрос поста, действительно, лишь в том, почему через планировщик он выполняется гораздо медленнее. Выполняется все на одной и той же машине с Ubuntu 18.04.

kes83
() автор топика
Ответ на: комментарий от kes83

сделай профайлинг. запускай скрипт и смотри «perf top» в соседней консоле. Увидишь какая функция жрет больше всего цпу. После чего сравни. Так же убедись, что файл, который пишет твой скрипт, в обоих случаях пишется на однин носитель.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.