Як я можу використовувати файли з HTTP як передумови в GNU?


10

Я хочу використовувати файли із всесвітньої павутини як необхідні умови в моїх файлах:

local.dat: http://example.org/example.gz
    curl -s $< | gzip -d | transmogrify >$@

Я тільки хочу , щоб «перетворювати» , якщо віддалений файл новіше , ніж локальний файл, так само , як роблять зазвичай працює.

Я не хочу зберігати кешовану копію example.gz - файли великі, і мені не потрібні необроблені дані. Переважно, я хотів би взагалі не уникати завантаження файлу. Мета - паралельно обробити декілька з них, використовуючи -jпрапор make.

Який чистий спосіб вирішити це? Я можу придумати кілька способів:

  • Зберігайте порожній макетний файл, прихований та оновлюваний щоразу, коли ціль відтворюється
  • Деякі плагіни, що використовують нову систему плагінів GNU make (про яку я нічого не знаю)
  • Доречний спосіб, який монтує HTTP-сервери у локальній файловій системі

Перш ніж копати далі, я хотів би поради, бажано конкретних прикладів!

Відповіді:


15

Спробуйте щось подібне у своєму Makefile:

.PHONY: local.dat

local.dat:
    [ -e example.gz ] || touch -d '00:00' example.gz
    curl -z example.gz -s http://example.org/example.gz -o example.gz
    [ -e $@ ] || touch -d 'yesterday 00:00' $@
    if [     "$(shell stat --printf '%Y' example.gz)" \
         -gt "$(shell stat --printf '%Y' $@)"         ] ; then \
      zcat example.gz | transmogrify >$@ ; \
    fi
    truncate -s 0 example.gz
    touch -r $@ example.gz

(зауважте: це Makefile, тому відступи - це вкладки, а не пробіли. Звичайно, важливо також, щоб після \рядків продовження не було пробілів - альтернативно позбудьтеся від зворотної косої лінії та зробіть її довгою, майже нечитабельна лінія)

Цей makeрецепт GNU спочатку перевіряє наявність файлу, який називається example.gz, (оскільки ми будемо використовувати його разом із -zin curl), і створює його, touchякщо цього немає. Дотик створює його з позначкою часу 00:00 (12 ранку поточного дня).

Тоді він використовує опцію curls -z( --time-cond) для завантаження, лише example.gzякщо вона була змінена з моменту останнього завантаження. -zможе надати фактичний вираз дати чи ім'я файлу. Якщо вказано ім'я файлу, воно використовуватиме час модифікації файлу як умову часу.

Після цього, якщо local.datйого немає, він створює його touch, використовуючи часову позначку, гарантовано старшу за мету example.gz. Це необхідно, тому що local.datмає існувати для наступної команди, яка використовується statдля отримання часової позначки mtime.

Потім, якщо example.gzє відмітка часу новіше local.dat, це труби example.gzв transmogrifyі перенаправляє висновок local.dat.

Нарешті, це робить речі з бухгалтерії та прибирання:

  • він скорочується example.gz(тому що потрібно зберігати лише часову позначку, а не весь файл)
  • touchес example.gzтак , що він має ту ж мітку часу , якlocal.dat

Ціль .PHONY забезпечує виконання local.datцілі завжди, навіть якщо файл цього імені вже існує.

Завдяки @Toby Speight за те, що в коментарях вказав, що моя оригінальна версія не працюватиме, і чому.

Крім того, якщо ви хочете передати файл безпосередньо в нього, transmogrifyне завантажуючи його у файлову систему спочатку:

.PHONY: local.dat

local.dat:
    [ -e example.gz ] || touch -d '00:00' example.gz
    [ -e $@ ] || touch -d 'yesterday 00:00' $@
    if [     "$(shell stat --printf '%Y' example.gz)" \
         -gt "$(shell stat --printf '%Y' $@)"         ] ; then \
      curl -z example.gz -s http://example.org/example.gz | transmogrify >$@ ; \
    fi
    touch -r $@ example.gz

ПРИМІТКА. Це здебільшого неперевірене, тому можуть знадобитися деякі незначні зміни, щоб точно визначити синтаксис. Тут важливим є метод, а не рішення про копіювання та вставку вантажу.

Я використовую варіанти цього методу (тобто - touchвведення файлу часової мітки) makeпротягом десятиліть. Це працює, і зазвичай дозволяє мені уникати того, щоб писати власний код вирішення залежності в sh (хоча мені тут доводилося робити щось подібне stat --printf %Y).

Всі знають make, що це чудовий інструмент для компіляції програмного забезпечення ... ІМО - це також дуже занижений інструмент для системного адміністратора та сценаріїв.


1
-zПрапор, звичайно, передбачає , що віддалений сервер використовує If-Modified-Sinceзаголовки. Це може бути не обов'язково. Залежно від налаштування сервера, замість цього вам може знадобитися щось робити ETag, або перевіряючи Cache-Controlзаголовки, або перевіряючи окремий файл контрольної суми (наприклад, якщо сервер надає sha1sum).
Боб

так. але без цього взагалі немає можливості робити те, що хоче ОП (якщо тільки він не бажає завантажувати величезний файл у тимчасовий файл щоразу, коли він запускається make, використовує cmpчи щось подібне для порівняння старих і нових файлів, і mv newfile oldfileякщо вони різні) . BTW, заголовки кеш-керування не говорять вам про те, чи є файл новішим за вказаний час. вони говорять вам, як довго адміністратори сервера хочуть, щоб ви кешували певний файл - і часто використовуються маркетинговими дроїдами як практика кешування кешу, щоб "покращити" свою веб-статистику.
cas

ETag це ще один спосіб зробити це, як і окремий файл контрольної суми. Все залежить від налаштування сервера. Наприклад, можна отримати cdimage.debian.org/debian-cd/current/amd64/iso-cd/SHA1SUMS і перевірити, чи змінився він, перш ніж вирішити отримати повний ISO. ETag робить те ж саме, використовуючи заголовок замість окремого файлу (і, як-от If-Modified-Since, покладається на HTTP-сервер, який його реалізує). Cache-Controlбуло б кращим варіантом завантаження файлу, якщо інші методи не підтримуються - це, звичайно, найменш точний, оскільки він намагається передбачити майбутнє.
Боб

Можливо, ETag/ If-None-Matchта інші контрольні суми є більш надійними, ніж If-Modified-Since. У будь-якому випадку, ці коментарі просто намагаються викласти припущення відповіді (а саме, що -zпередбачає підтримку сервера) - основний метод повинен бути досить легко адаптуватися до інших алгоритмів перевірки змін.
Боб

1
не соромтеся написати відповідь, реалізуючи рішення на основі ETag. Якщо це буде добре, я його схвалюю. і тоді хтось підійде і вкаже, що не всі веб-сервери надають заголовка Etag :).
cas

1

Іншою альтернативою є використання системи побудови, яка використовує контрольні суми залежності, щоб визначити, чи викликати відновлення. Я використовував трюк "touch" за допомогою Gnu Make много, але набагато простіше, коли ви можете вказати динамічні залежності і коли файли, які не змінюються, не викликають відновлення. Ось приклад використання GoodMake :

#! /usr/local/goodmake.py /bin/sh -se

#! *.date
    # Get the last-modified date
    curl -s -v -X HEAD http://${1%.date} 2>&1 | grep -i '^< Last-Modified:' >$1

#? local.dat
    site=http://example.org/example.gz
    $0 $site.date
    curl -s $site | gzip -d | transmogrify >$1

Замість цього -X HEAD, curl manpage рекомендує використовувати -I: "(-X) змінює лише фактичне слово, яке використовується у запиті HTTP, воно не змінює поводження curl. Так, наприклад, якщо ви хочете зробити правильний запит HEAD, використовуючи -X HEAD не вистачить. Вам потрібно скористатися опцією -I, - head. "
LightStruk
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.