Это сложилось, что я просто забыл флаг начальной загрузки относительно раздела.
Если некоторое задание должно быть запущено после того, как некоторый файл был скопирован, просто сделайте это частью фонового задания:
(cp this /there && start job that needs this in /there) &
(cp that /here && start job that needs that in /here) &
wait
(последнее &
не необходимо).
Теперь для более сложных зависимостей, Вы могли использовать GNU make -j
.
make -j2 -f /dev/fd/3 3<< 'EOF'
all: j1 j2 j3
.PHONY: cp1 cp2 cp3 j1 j2 j3 all
cp1:
cp this /there
cp2:
cp that /here
cp3:
cp this /here
j1: cp1
start job that needs this in /there
j2: cp2
start job that needs that in /here
j3: cp1 cp3
start job that needs this in /here and /there
EOF
-j2
дошел бы до 2 заданий в любой момент времени, и зависимости будут уважать.
Теперь, чтобы не искажать файлов журнала у Вас есть две основных опции
Для 1, самое легкое должно сохранить каждый вывод задания в отдельном файле и объединить их впоследствии:
(cp this /there && start job that needs this in /there) > j1.log 2>&1 &
(cp that /here && start job that needs that in /here) > j2.log 2>&1 &
wait
cat j1.log j2.log > jobs.log
Другая опция состоит в том, чтобы использовать каналы, чтобы собрать вывод каждого задания и иметь cat
объедините их. Замена процесса Shell как доступная в ksh
, zsh
или bash
может помочь нам с этим и даже заботиться о фоновой обработке:
j1() { cp this /there && start job that needs this in /there; }
j2() { cp that /here && start job that needs that in /here; }
cat <(j1 2>&1) <(j2 2>&1) > jobs.log
j1
, j2
и cat
будет запущен одновременно и предаст земле соединенный с каналами.
Однако отметьте это cat
только начнет читать из второго канала (который записан в j2
) после j1
закончился. Это означает это если j2
записи больше входа, чем размер канала (например, на Linux, обычно 64 кибибита) j2
будет заблокирован до j1
концы.
При помощи этого можно избежать sponge
от moreutils
, как:
cat <(j1 2>&1) <(j2 2>&1 | sponge) > jobs.log
Хотя это означало бы весь вывод j2
был бы сохранен в памяти, и кошка только начнет писать вывод j2
в jobs.log
после j2
закончился, в этом случае с помощью pv -qB 100M
например, может быть предпочтительным:
cat <(j1 2>&1) <(j2 2>&1 | pv -qB 100M) > jobs.log
Тот путь j2
только приостановить (если j1
еще не закончился), после 100M
(плюс два содержания канала) журналов были произведены, и pv
не ожидал бы j2
закончиться прежде, чем произвести к stdout.
Обратите внимание, что для всего вышеупомянутого, необходимо остерегаться этого, после того как Вы перенаправляете вывод большинства команд в файл или канал (что-либо кроме tty), поведение затронуто. Команды, или скорее stdio
API libc
они звонят (printf
, fputs
, fwrite
...) обнаруживает, что вывод не идет в терминал, и выполните оптимизацию путем вывода в больших блоках (несколько килобайтов), в то время как они не делают этого для стандартной погрешности. Это означает порядок выходных сигналов, и сообщения об ошибках будут затронуты. Если это - проблема в системах GNU или FreeBSD (по крайней мере), и для динамично связанных команд, можно использовать stdbuf
команда:
stdbuf -oL j1 > j1.log 2>&1
вместо:
j1 > j1.log 2>&1
гарантировать, что вывод stdio с буфером строки (каждая строка вывода будет записана отдельно, как только они завершены).
Для опции 2, пишет в канал меньше, чем PIPE_BUF
байты, который на Linux составляет 4 096 байтов, настолько больше, чем Ваша средняя строка журнала, как гарантируют, будут атомарными, это - то, если два процесса запишут в тот же канал одновременно, то их 2 записи, как гарантируют, не будут переплетены. Нет такой гарантии на регулярных файлах, но я серьезно сомневаюсь, что 2 записи меньше чем 4 кибибитов могли закончиться, переплелся на любой ОС или файловой системе.
Таким образом если бы не та буферизация, описанная выше и если бы строки журнала были произведены индивидуально в целом и отдельно, у Вас была бы гарантия, что строки вывода не будут иметь части строки этого задания и части строки того другого задания.
Однако ничто не предотвращает команду, чтобы сделать сброс промежуточные две части записанной строки (как printf("foo"); fflush(stdout); printf("bar\n");
) и на stderr нет никакой буферизации.
Другая проблема состоит в том, что, после того как строки всех заданий чередованы, будет трудным сказать, какая строка для который задание.
Можно решить обе проблемы путем выполнения чего-то как:
tag() { stdbuf -oL sed "s%^%$1: %"; }
{
j1 2>&1 | tag j1 &
j2 2>&1 | tag j2
} | cat > jobs.log
(обратите внимание, что нам не нужно wait
(и это не работало бы так или иначе в большинстве оболочек), потому что cat
не закончится, пока не будет никого пишущего в канал больше, таким образом, только в j1
и j2
завершились).
Выше мы используем | cat
иметь канал с его гарантией атомарности. Мы передаем вывод по каналу каждой команды к команде, которая отмечает каждую строку с именем задания. j1
и j2
может записать их вывод однако, они хотят, sed
(из-за stdbuf -oL
) произведет строки (с префиксом тега) в целом и отдельно, который гарантирует вывод, который не будет искажен.
То же примечание как выше все еще применяется: мы не подаем заявку stdbuf -oL
к командам в j1
и j2
таким образом, они, скорее всего, буферизуют свой вывод, который может поэтому быть записан еще долго после того, как он был произведен. Это еще хуже, чем в предыдущем случае, потому что, если Вы видите:
j1: doing A
j1: doing B
j2: doing C
Это действительно означает это j1
сделал прежде, чем сделать B, но не, что он сделал любого из них прежде j2
выполнение C. Так еще раз Вы, возможно, должны подать заявку stdbuf -oL
к большему количеству команд, если это - проблема.
Обратите внимание, что Вы не можете подать заявку stdbuf
окружать функции как j1
или j2
выше, но по крайней мере с GNU и FreeBSD stdbuf, можно использовать это для установки stdbuf
глобально или на основе на подоболочку:
stdbuf_LD_PRELOAD=$(stdbuf sh -c 'export -p LD_PRELOAD')
line_buffered_output() {
eval "$stdbuf_LD_PRELOAD"
export _STDBUF_O=L
}
j1() (line_buffered_output; cp this /there && start...)
Если каждая загруженная обработка потребности файла, сделайте:
cp whatever file; process file &
вместо этого.
Если Вы волнуетесь, что файлы журнала искажены, возможно, необходимо использовать syslog(3)
, возможно, через logger(1)
. Рассмотреть использование nohup(1)
если кто-то мог бы выйти из системы (и уничтожить фоновые процессы выполнения непреднамеренно).
PIPE_BUF
значения в общих системах Unix: ar.to/notes/posix#pipe-buf – Arto Bendiken 08.10.2014, 02:41