GNU makeの前提条件としてHTTPからのファイルをどのように使用できますか?


10

私のメイクファイルの前提条件として、World Wide Webからのファイルを使用したいと思います。

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

makeが正常に動作するのと同じように、リモートファイルがローカルファイルよりも新しい場合にのみ「変換」します。

example.gzのキャッシュコピーを保持したくありません。ファイルが大きく、生データは必要ありません。できれば、ファイルをダウンロードしないようにします。目標は、makeフラグを使用してこれらのいくつかを並行して処理することです。-j

これを解決するきれいな方法は何ですか?いくつかの方法が考えられます。

  • 空のダミーファイルを保管しておき、ターゲットが再作成されるたびに更新する
  • 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であるため、インデントはスペースではなくタブです。もちろん\、継続行の後にスペースがないことも重要です-または、バックスラッシュエスケープを削除して1つ長くします。ほとんど読めない行)

このGNU makeレシピでは、最初にというファイルがexample.gz存在することを確認し(-zinで使用するためcurl)、touch存在しない場合はで作成します。タッチは00:00(当日の午前12時)のタイムスタンプで作成します。

次に、curl-z--time-cond)オプションを使用しexample.gzて、前回のダウンロード以降に変更されている場合にのみダウンロードします。 -z実際の日付式またはファイル名を指定できます。ファイル名を指定すると、ファイルの変更時刻が時間条件として使用されます。

その後、local.dat存在しない場合は、それよりも古いtouchことが保証されたタイムスタンプを使用して、で作成します。次のコマンドがmtimeタイムスタンプを取得するために使用する必要があるため、これは必要です。example.gzlocal.datstat

次に、example.gzタイムスタンプがよりも新しい場合local.dat、パイプexample.gzを使用transmogrifyして出力をにリダイレクトしますlocal.dat

最後に、簿記とクリーンアップを行います。

  • それは切り捨てexample.gz(あなただけのタイムスタンプではなく、ファイル全体を維持する必要があるため)
  • touches 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ソフトウェアをコンパイルするための優れたツールであることは誰もが知っています... IMOは、システム管理およびスクリプトタスクのための非常に過小評価されているツールでもあります。


1
-zもちろん、このフラグは、リモートサーバーがIf-Modified-Sinceヘッダーを使用することを前提としています。これは必ずしもそうであるとは限りません。サーバーの設定によっては、代わりにを使用しETagたり、Cache-Controlヘッダーをチェックしたり、別のチェックサムファイルをチェックしたりする必要があります(サーバーがを提供している場合などsha1sum)。
ボブ

はい、そうです。それなしで、OPは(彼は一時ファイルに巨大なファイルをダウンロードして喜んでない限り何を望んでやってのすべての方法はありません、すべての彼は走る時間をmake、使用cmp新旧のファイルを比較したり、気にいらを、そしてmv newfile oldfile彼らだ異なる場合は) 。ところで、キャッシュ制御ヘッダーは、ファイルが特定の時間より新しいかどうかを通知しません。これらは、サーバー管理者が特定のファイルをキャッシュしておく期間を示します。また、マーケティング統計では、ウェブ統計を「改善」するためのキャッシュ無効化手法としてよく使用されます。
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に基づくソリューションを実装する回答を自由に書いてください。よかったら賛成します。そして誰かがやって来て、すべてのWebサーバーがEtagヘッダーを提供するわけではないことを指摘します:)。
cas

1

別の代替方法は、依存関係のチェックサムを使用して再構築をトリガーするかどうかを決定する構築システムを使用することです。私は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のマンページでは次を使用することをお勧めし-Iます: "(-X)はHTTPリクエストで使用される実際の単語を変更するだけで、curlの動作を変更しません。たとえば、-X HEADを使用して適切なHEADリクエストを作成する場合十分ではありません。-I、-headオプションを使用する必要があります。」
LightStruk
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.