Ошибочно думать, что правило преуспело из-за 0-размерного файла, сгенерированного перенаправлением вывода

В make-файле у меня есть несколько правил, которые выглядят так:

out.txt: foo.sh input.txt ./foo.sh -i input.txt > out.txt 

Если foo.sh не удается, то out.txt будет создан как файл размера 0. Если я снова запустил make , ошибочно предположим, что файл out.txt был успешно создан, и он снова не будет запускать правило.

Каков правильный способ справиться с подобным сценарием?

  • make install - как использовать wget, а не завивать
  • Как проверить, что aptitude что-то сделала?
  • Как запустить скрипт Python в Makefile
  • Есть ли какое-либо преимущество в использовании аргумента -j2 при создании Linux-систем в VirtualBox?
  • checkinstall зависает при «Копирование файлов во временный каталог ...» при создании vim8
  • Как написать скрипт bash в Makefile
  • Нет dpkg или apt, no make или gcc. Необходимо установить их все
  • компиляция PHP не приводит к ошибке libpcre
  • 4 Solutions collect form web for “Ошибочно думать, что правило преуспело из-за 0-размерного файла, сгенерированного перенаправлением вывода”

    Вы можете запросить удаление целевого файла, если это правило не удается, .DELETE_ON_ERROR специальную цель с именем .DELETE_ON_ERROR . Ему не нужно ничего делать или иметь какие-либо зависимости, поэтому просто добавьте это в свой make-файл:

     .DELETE_ON_ERROR: 

    Затем вы получаете следующее:

     $ cat Makefile .DELETE_ON_ERROR: foo: false > foo $ make false > foo make: *** [foo] Error 1 make: *** Deleting file `foo' zsh: exit 2 make $ stat foo stat: cannot stat `foo': No such file or directory 

    Из ошибок в рецептах :

    Обычно, когда строка рецепта терпит неудачу, если он вообще изменил целевой файл, файл поврежден и не может быть использован – или, по крайней мере, он не полностью обновлен. Тем не менее, временная метка файла говорит о том, что теперь она обновлена, поэтому в следующий раз make прогоны она не будет пытаться обновить этот файл. Ситуация такая же, как когда оболочка убита сигналом; см. Прерывания . Поэтому, как правило, правильная вещь – удалить целевой файл, если рецепт завершился неудачно после начала изменения файла. make сделает это, если .DELETE_ON_ERROR появляется как цель. Это почти всегда то, что вы хотите make , но это не историческая практика; поэтому для совместимости вы должны явно запросить его.

    Когда это возможно, правила makefile должны сначала создавать свою цель под временным именем, а затем перемещать ее на место. Таким образом, если процесс сборки прерывается по какой-либо причине, не будет полуписанного целевого файла, который нельзя отличить от полностью написанного файла.

     out.txt: foo.sh input.txt ./foo.sh -i input.txt >$@.tmp mv -f $@.tmp $@ 

    mv -f $@.tmp $@ – обычная идиома make-файла.

    Ответ Джулиано показывает вариант, где имя временного файла генерируется динамически. Генерация динамического имени требуется, если может быть несколько процессов, генерирующих одну и ту же цель, или если каталог может быть написан другими пользователями. Это очень редко относится к дереву сборки (если это были проблемы, многое из того, что происходит в типичном make-файле, будет ломаться), поэтому дополнительная сложность обычно не нужна.

    Поскольку кажется, что foo.sh – это то, что вы написали (или генерируется тем, что вы написали), я бы подумал о добавлении к нему флага -o , который принимает имя выходного файла. Тогда вам не нужно зависеть от поведения перенаправления ввода-вывода по умолчанию. Ваш скрипт может очищать частичные выходные файлы или, возможно, даже не создавать файл в первую очередь, если вы можете обнаружить ошибку достаточно рано.

    Я полагаю, что foo.sh правильно возвращает ненулевое значение при ошибке. Затем вы должны сделать временный и только перезаписать результат с успехом.

     tmp=$$(mktemp) && ./foo.sh input.txt > $$tmp && mv $$tmp $@ || rm -f $$tmp && false 
    Interesting Posts

    Как удалить разделитель поля, который закончился на каждой последней строке?

    как я могу заставить hdd дать плохие данные сектора URE / плохого сектора?

    Ограничить длину вывода команды «rss» в conky

    Имитировать файлы bitrot / corrupt (для BTRFS)

    Почему мои методы dict работают хорошо, не определяя дополнительный аргумент `dict`?

    ImageMagick (или другое) для текста в формате UTF-8

    Процесс выключения стартового и многоканального выключения

    «Трудносвязанные» части большого файла, в котором только небольшая часть изменилась

    Разгон Intel Nvidia для вычислений (CUDA)

    гостевая ОС kvm недоступна после перезагрузки системы

    Как я могу профилировать ядро?

    Неисправность изменения яркости подсветки (/ sys / class / backlight folder empty)

    Как отключить режим отладки на сервере Jboss на Linux-машине?

    Получать ошибки при обновлении aptitude

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

    Linux и Unix - лучшая ОС в мире.