У меня есть небольшой скрипт, который ежедневно вызывается crontab с помощью следующей команды:
/homedir/MyScript &> some_log.log
Проблема с этим методом заключается в том, что some_log.log создается только после завершения MyScript. Я хотел бы сбрасывать вывод программы в файл во время ее работы, чтобы я мог делать такие вещи, как
tail -f some_log.log
и следить за прогрессом и т. д.
sys.stdout.flush()
.Ответы:
Сам bash никогда не будет записывать какие-либо данные в ваш файл журнала. Вместо этого команды, которые он вызывает как часть сценария, будут по отдельности записывать выходные данные и сбрасываться всякий раз, когда им это нравится. Итак, ваш вопрос на самом деле заключается в том, как заставить команды в сценарии bash сбрасываться, и это зависит от того, что они собой представляют.
источник
Я нашел решение здесь . Используя пример OP, вы в основном запускаете
а затем буфер очищается после каждой строки вывода. Я часто совмещаю это с
nohup
выполнением длительных заданий на удаленной машине.Таким образом, ваш процесс не будет отменен при выходе из системы.
источник
stdbuf
? Основываясь на этом комментарии, похоже, что он недоступен в некоторых дистрибутивах. Не могли бы вы уточнить?stdbuf
является частью GNU coreutils, документацию можно найти на gnu.orgexport -f my_function
а затем,stdbuf -oL bash -c "my_function -args"
если вам нужно запустить функцию вместо скриптаКлюч -f. Цитата из сценария человека:
-f, --flush Flush output after each write. This is nice for telecooperation: one person does 'mkfifo foo; script -f foo', and another can supervise real-time what is being done using 'cat foo'.
Работать в фоновом режиме:
источник
busybox
! (моя оболочка потом замерзает, но все равно)Вы можете использовать
tee
для записи в файл без необходимости промывки.источник
Это не функция
bash
, поскольку все, что делает оболочка, - это открывает файл, о котором идет речь, а затем передает дескриптор файла в качестве стандартного вывода скрипта. Что вам нужно сделать, так это убедиться, что вывод из вашего скрипта сбрасывается чаще, чем вы сейчас.Например, в Perl это можно сделать, установив:
См. Perlvar для получения дополнительной информации об этом.
источник
Буферизация вывода зависит от того, как ваша программа
/homedir/MyScript
реализована. Если вы обнаружите, что вывод буферизируется, вы должны принудительно использовать его в своей реализации. Например, используйте sys.stdout.flush (), если это программа на Python, или используйте fflush (stdout), если это программа C.источник
Это поможет?
tail -f access.log | stdbuf -oL cut -d ' ' -f1 | uniq
Это немедленно отобразит уникальные записи из access.log с помощью утилиты stdbuf .
источник
stdbuf
доступ к Ubuntu на данный момент, не знаю, где я его взял.stdbuf
является частьюcoreutilus
(обнаруживается с помощьюapt-file search /usr/bin/stdbuf
).Как только что заметили здесь проблему, вам нужно подождать, пока программы, которые вы запускаете из своего скрипта, завершат свою работу.
Если в вашем скрипте вы запускаете программу в фоновом режиме, вы можете попробовать что-то еще.
В общем, вызов
sync
перед выходом позволяет очистить буферы файловой системы и может немного помочь.Если в сценарии вы запускаете некоторые программы в фоновом режиме (
&
), вы можете дождаться их завершения, прежде чем выходить из сценария. Чтобы получить представление о том, как он может работать, вы можете увидеть ниже#!/bin/bash #... some stuffs ... program_1 & # here you start a program 1 in background PID_PROGRAM_1=${!} # here you remember its PID #... some other stuffs ... program_2 & # here you start a program 2 in background wait ${!} # You wait it finish not really useful here #... some other stuffs ... daemon_1 & # We will not wait it will finish program_3 & # here you start a program 1 in background PID_PROGRAM_3=${!} # here you remember its PID #... last other stuffs ... sync wait $PID_PROGRAM_1 wait $PID_PROGRAM_3 # program 2 is just ended # ...
Поскольку
wait
работает как с заданиями, так и сPID
числами, ленивое решение следует поместить в конец скрипта.for job in `jobs -p` do wait $job done
Сложнее ситуация, если вы запускаете что-то, что запускает что-то еще в фоновом режиме, потому что вам нужно искать и ждать (если это так) конца всего дочернего процесса: например, если вы запускаете демон, вероятно, это не так ждать его окончания :-).
Заметка:
wait $ {!} означает «дождаться завершения последнего фонового процесса», где
$!
PID последнего фонового процесса. Таким образом, установкаwait ${!}
сразу после этогоprogram_2 &
эквивалентна выполнению напрямуюprogram_2
без отправки в фоновом режиме с помощью&
С помощью
wait
:Syntax wait [n ...] Key n A process ID or a job specification
источник
Спасибо
@user3258569
, возможно, скрипт - единственное, что работаетbusybox
!А вот после этого снаряд у меня замерз. В поисках причины я обнаружил эти большие красные предупреждения «не используйте в неинтерактивных оболочках» на странице руководства по скрипту :
Правда.
script -c "make_hay" -f /dev/null | grep "needle"
замораживал для меня оболочку.В соответствии с предупреждением, я подумал, что
echo "make_hay" | script
ПРОЙДЕТ EOF, поэтому я попыталсяecho "make_hay; exit" | script -f /dev/null | grep 'needle'
и это сработало!
Обратите внимание на предупреждения на странице руководства. Это может не сработать для вас.
источник
Альтернативой stdbuf является то, что
awk '{print} END {fflush()}'
я бы хотел, чтобы для этого был встроенный bash. Обычно в этом нет необходимости, но в более старых версиях могут быть ошибки синхронизации bash в файловых дескрипторах.источник
Не знаю, сработает ли это, но как насчет звонка
sync
?источник
sync
является операцией низкоуровневой файловой системы и не имеет отношения к буферизованному выводу на уровне приложения.sync
при необходимости записывает все грязные буферы файловой системы в физическое хранилище. Это внутреннее для ОС; приложения, работающие поверх ОС, всегда видят целостное представление о файловой системе независимо от того, записаны ли блоки диска в физическое хранилище. Что касается исходного вопроса, приложение (сценарий), вероятно, буферизует вывод во внутреннем буфере приложения, и ОС даже не узнает (пока), что вывод фактически предназначен для записи в стандартный вывод. Таким образом, гипотетическая операция типа «синхронизация» не сможет «проникнуть в» скрипт и извлечь данные.У меня была эта проблема с фоновым процессом в Mac OS X с использованием
StartupItems
. Вот как я это решаю:Если я сделаю,
sudo ps aux
я увижу, чтоmytool
запускается.Я обнаружил, что (из-за буферизации) при выключении Mac OS X
mytool
никогда не передает вывод вsed
команду. Однако, если я выполняюsudo killall mytool
, тоmytool
передаю выводsed
команде. Следовательно, я добавил кstop
случаю,StartupItems
который выполняется при выключении Mac OS X:start) if [ -x /sw/sbin/mytool ]; then # run the daemon ConsoleMessage "Starting mytool" (mytool | sed .... >> myfile.txt) & fi ;; stop) ConsoleMessage "Killing mytool" killall mytool ;;
источник
ну нравится это или нет, вот как работает перенаправление.
В вашем случае вывод (то есть ваш сценарий завершен) вашего сценария перенаправлен в этот файл.
Что вы хотите сделать, так это добавить эти перенаправления в свой сценарий.
источник