Параллельно GNU: удаление строки из журнала заданий прерывает ее параллельное обновление - PullRequest
0 голосов
/ 15 ноября 2018

Если вы запускаете GNU параллельно с --joblog path/to/logfile, а затем удаляете строку из указанного файла журнала , в то время как параллель работает , параллельная версия GNU больше не сможет добавлять к ней будущие завершенные задания.

Выполнить это MWE:

#!/usr/bin/bash

parallel -j1 -n0 --joblog log sleep 1 ::: $(seq 10) &

sleep 5 && sed -i '$ d' log

Если вы tail -f log до выполнения, вы можете видеть, что параллель продолжает запись в этот файл. Однако, если вы cat log через 10 секунд, вы увидите, что ничего не было записано в настоящий файл на диске после третьей записи или около того.

В чем причина этого? Есть ли способ удалить что-то из файла и иметь возможность параллельно писать в него GNU?

Некоторые предыстории того, почему это произошло:

Используя GNU параллельно, я запустил несколько заданий на удаленных машинах с --sshloginfile. Затем мне нужно было pkill выполнить несколько заданий на одной из машин, потому что коллеге нужно было ее использовать (и я впоследствии удалил машину из файла sshloginfile, чтобы параллель не использовала ее повторно для новых запусков). Если вы pkill запустили эти процессы на удаленной машине, они получат Exitval 0 (похоже, что они завершились без проблем; вы не можете сказать, что они были убиты). Я хотел немедленно удалить их из журнала заданий, чтобы при перезапуске parallel --resume позднее параллель мог взглянуть на журнал заданий и определить, чего не хватает.

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

1 Ответ

0 голосов
/ 21 ноября 2018

Хотя @MarkSetchell абсолютно прав в своем комментарии, проблема с корнем здесь из-за man sed лжи:

-i[SUFFIX], --in-place[=SUFFIX]
          edit files in place (makes backup if SUFFIX supplied)

sed -i не редактирует файлы на месте.

Чтоэто делает создание временного файла в том же каталоге, копирование входного файла во временный файл во время редактирования и, наконец, переименование временного файла в имя входного файла.Похоже на это:

sed '$ d' log > sedXxO11P
mv sedXxO11P log

Понятно, что исходный журнал и sedXxO11P имеют разные inode - назовем их ino1 и ino2.В GNU Parallel открыт ino1, и он действительно не знает о существовании ino2.GNU Parallel с радостью присоединится к ino1, совершенно не подозревая, что когда он закроет файл, файл исчезнет, ​​потому что он уже не был связан.

Таким образом, вам нужно изменить содержимое файла, не изменяя индекс:

#!/usr/bin/bash                                                                               

seq 10 | parallel -j1 -n0 --joblog log sleep 1 &

sleep 5

# Obvious race condition here:                                                                
# Anything appended to log before sed is done is lost.                                        
# This can be avoided by suspending parallel while running this
tmp=$RANDOM$$
cp log $tmp
(rm $tmp; sed '$ d' >log) < $tmp

wait
cat log

Это работает прямо сейчас.Но не ожидайте, что это будет поддерживаемая функция - когда-либо.

...