Làm cách nào tôi có thể sử dụng các tệp từ HTTP làm điều kiện tiên quyết trong GNU?


10

Tôi muốn sử dụng các tệp từ World Wide Web làm điều kiện tiên quyết trong tệp tạo tệp của mình:

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

Tôi chỉ muốn "truyền tín hiệu" nếu tệp từ xa mới hơn tệp cục bộ, giống như làm cho hoạt động bình thường.

Tôi không muốn giữ một bản sao của cache.gz được lưu trong bộ nhớ cache - các tệp rất lớn và tôi không cần dữ liệu thô. Tốt nhất là tôi muốn tránh tải xuống tập tin. Mục tiêu là xử lý song song một vài trong số này bằng cách sử dụng -jcờ make.

Một cách sạch sẽ để giải quyết điều này là gì? Tôi có thể nghĩ ra một vài cách để đi:

  • Giữ một tập tin giả rỗng bỏ đi, cập nhật mỗi khi mục tiêu được tạo lại
  • Một số plugin sử dụng hệ thống plugin mới của GNU (mà tôi không biết gì về)
  • Một cách thức không thể tin được gắn kết các máy chủ HTTP trong hệ thống tệp cục bộ

Trước khi đào sâu hơn, tôi muốn một số lời khuyên, tốt nhất là các ví dụ cụ thể!

Câu trả lời:


15

Hãy thử một cái gì đó như thế này trong Makefile của bạn:

.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

.. (lưu ý: đây là một Makefile, vì vậy indents các tab, không gian dĩ nhiên Nó cũng quan trọng là không có dấu cách sau \trên dòng tiếp nối - cách khác thoát khỏi dấu chéo ngược-thoát và làm cho nó trở thành một dài, dòng gần như không thể đọc được)

Đây GNU makethức kiểm tra đầu tiên mà một tập tin gọi là example.gztồn tại (vì chúng ta sẽ sử dụng nó với -ztrong curl), và tạo ra nó với touchnếu nó không. Cảm ứng tạo ra nó với dấu thời gian là 00:00 (12 giờ sáng của ngày hiện tại).

Sau đó, nó sử dụng curl's -z( --time-cond) tùy chọn để chỉ tải example.gznếu nó đã được sửa đổi kể từ lần cuối cùng nó được tải xuống. -zcó thể được cung cấp một biểu thức ngày thực tế, hoặc một tên tệp. Nếu được đặt tên tệp, nó sẽ sử dụng thời gian sửa đổi của tệp làm điều kiện thời gian.

Sau đó, nếu local.datkhông tồn tại, nó tạo ra nó bằng touchcách sử dụng dấu thời gian được đảm bảo hơn so với example.gz. Điều này là cần thiết bởi vì local.datphải tồn tại cho lệnh tiếp theo được sử dụng statđể lấy dấu thời gian mtime của nó.

Sau đó, nếu example.gzcó dấu thời gian mới hơn local.dat, nó sẽ dẫn example.gzvào transmogrifyvà chuyển hướng đầu ra local.dat.

Cuối cùng, nó thực hiện công việc kế toán và dọn dẹp:

  • nó cắt ngắn example.gz(vì bạn chỉ cần giữ dấu thời gian chứ không phải toàn bộ tệp)
  • touches example.gzđể nó có cùng dấu thời gian nhưlocal.dat

Mục tiêu .PHONY đảm bảo rằng local.datmục tiêu luôn được thực thi, ngay cả khi tệp của tên đó đã tồn tại.

Cảm ơn @Toby Speight đã chỉ ra trong các nhận xét rằng phiên bản gốc của tôi sẽ không hoạt động, và tại sao.

Ngoài ra, nếu bạn muốn dẫn tập tin trực tiếp vào transmogrifymà không tải nó xuống hệ thống tập tin trước:

.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

LƯU Ý: điều này chủ yếu chưa được kiểm tra nên có thể yêu cầu một số thay đổi nhỏ để có được cú pháp chính xác. Điều quan trọng ở đây là phương pháp, không phải là giải pháp sùng bái hàng hóa sao chép.

Tôi đã sử dụng các biến thể của phương pháp này (tức là - touchmột tệp dấu thời gian) maketrong nhiều thập kỷ. Nó hoạt động và thường cho phép tôi tránh phải viết mã độ phân giải phụ thuộc của riêng mình vào sh (mặc dù tôi đã phải làm một cái gì đó tương tự stat --printf %Yở đây).

Mọi người đều biết makelà một công cụ tuyệt vời để biên dịch phần mềm ... IMO nó cũng là một công cụ được đánh giá rất thấp cho quản trị hệ thống và các tác vụ kịch bản.


1
Các -zcờ, tất nhiên, giả định rằng các máy chủ từ xa sử dụng If-Modified-Sincetiêu đề. Điều này có thể không nhất thiết là trường hợp. Tùy thuộc vào thiết lập máy chủ, thay vào đó, bạn có thể cần phải làm gì đó ETaghoặc bằng cách kiểm tra Cache-Controlcác tiêu đề hoặc bằng cách kiểm tra một tệp tổng kiểm tra riêng (ví dụ: nếu máy chủ cung cấp a sha1sum).
Bob

vâng, nó làm nhưng không có điều đó, không có cách nào để OP thực hiện những gì OP muốn (trừ khi anh ta sẵn sàng tải tệp khổng lồ về tệp tạm thời mỗi khi anh ta chạy make, sử dụng cmphoặc làm gì đó để so sánh các tệp cũ và mới và mv newfile oldfilenếu chúng khác nhau) . BTW, các tiêu đề kiểm soát bộ đệm không cho bạn biết nếu tệp mới hơn một thời gian nhất định. chúng cho bạn biết quản trị viên máy chủ muốn bạn lưu trữ một tệp đã cho trong bao lâu - và thường được các droid tiếp thị sử dụng như một cách thực hành xóa bộ nhớ cache để "cải thiện" số liệu thống kê web của họ.
cas

ETag một cách khác để làm điều đó, như là một tập tin tổng kiểm tra riêng biệt. Tất cả phụ thuộc vào cách máy chủ được thiết lập. Ví dụ: người ta có thể tìm nạp cdimage.debian.org/debian-cd/civerse/amd64/iso-cd/SHA1SUMS và kiểm tra xem nó có thay đổi hay không trước khi quyết định lấy ISO đầy đủ. ETag cũng làm điều tương tự, sử dụng một tiêu đề thay vì một tệp riêng biệt (và, giống như If-Modified-Since, phụ thuộc vào máy chủ HTTP thực hiện nó). Cache-Controlsẽ là một lựa chọn cuối cùng trong quá trình tải xuống tệp nếu không có phương pháp nào khác được hỗ trợ - chắc chắn là ít chính xác nhất vì nó cố gắng dự đoán tương lai.
Bob

Có thể cho rằng, ETag/ If-None-Matchvà các tổng kiểm tra khác cũng đáng tin cậy hơn If-Modified-Since. Trong mọi trường hợp, những nhận xét này chỉ cố gắng đưa ra các giả định của câu trả lời (cụ thể là -zgiả định hỗ trợ máy chủ) - phương pháp cơ bản nên khá dễ dàng để thích ứng với các thuật toán kiểm tra thay đổi khác.
Bob

1
cảm thấy tự do để viết một câu trả lời thực hiện một giải pháp dựa trên ETag. Nếu nó tốt, tôi sẽ nâng cấp nó. và sau đó ai đó sẽ xuất hiện và chỉ ra rằng không phải tất cả các máy chủ web đều cung cấp tiêu đề Etag :).
cas

1

Một cách khác là sử dụng một hệ thống xây dựng sử dụng tổng kiểm tra phụ thuộc để xác định xem có nên kích hoạt xây dựng lại hay không. Tôi đã sử dụng thủ thuật "chạm" với Gnu Tạo rất nhiều, nhưng nó đơn giản hơn nhiều khi bạn có thể chỉ định các phụ thuộc động và khi các tệp không thay đổi sẽ không kích hoạt xây dựng lại. Đây là một ví dụ sử dụng 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

Thay vì -X HEAD, manpage của curl khuyên bạn nên sử dụng -I: "(-X) chỉ thay đổi từ thực tế được sử dụng trong yêu cầu HTTP, nó không thay đổi cách hành xử của curl. Vì vậy, ví dụ nếu bạn muốn tạo một yêu cầu CHÍNH đúng, sử dụng -X HEAD sẽ không đủ. Bạn cần sử dụng tùy chọn -I, - head. "
LightStruk
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.