GNU make의 전제 조건으로 HTTP의 파일을 사용하는 방법은 무엇입니까?

GNU make의 전제 조건으로 HTTP의 파일을 사용하는 방법은 무엇입니까?

다음에서 사용하고 싶습니다.월드 와이드 웹내 makefile의 전제 조건으로 :

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

원격 파일이 로컬 파일보다 최신인 경우 "변환"하고 싶습니다.만들다정상 작동.

그래요아니요캐시된 사본을 보관하고 싶습니다.example.gz- 파일이 커서 원시 데이터가 필요하지 않습니다. 가급적이면 파일을 모두 다운로드하지 않는 것이 좋습니다. 목표는 make 플래그를 사용하여 일부를 병렬로 처리하는 것입니다 -j.

이 문제를 해결하는 깨끗한 방법은 무엇입니까? 여러 가지 방법을 생각해 볼 수 있습니다.

  • 빈 더미 파일을 유지하고 대상이 다시 생성될 때마다 업데이트합니다.
  • GNU make를 사용하는 일부 플러그인새로운 플러그인 시스템(나는 이것에 대해 아무것도 모른다)
  • 로컬 파일 시스템에 HTTP 서버를 설치하는 불가지론적인 방법

더 자세히 알아보기 전에 몇 가지 조언, 바람직하게는 구체적인 예를 듣고 싶습니다!

답변1

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이므로 들여쓰기는 공백이 아니라 탭입니다. 물론 연속된 줄에 후행 공백이 없거나 \백슬래시 이스케이프를 제거하고 거의 읽을 수 없는 긴 줄로 만드는 것도 중요합니다.)

이 GNU make레시피는 먼저 이름이 지정된 파일이 example.gz존재하는지 확인하고( 에서 사용할 것이므로 ) -z존재하지 않으면 curl파일을 생성합니다 . touch터치로 생성된 타임스탬프는 00:00(당일 오전 12시)입니다.

그런 다음 ( ) curl옵션을 사용하여 마지막 다운로드 이후 수정된 콘텐츠만 다운로드합니다. 실제 날짜 표현이나 파일 이름이 주어질 수 있습니다. 파일 이름이 주어지면 파일의 수정 시간을 시간 조건으로 사용합니다. -z--time-condexample.gz-z

나중에 존재하지 않는 경우 보장된 타임스탬프를 사용 local.dat하여 생성됩니다.touch나이가 많은보다 example.gz. mtime 타임스탬프를 얻으 local.dat려면 다음 명령이 존재해야 하기 때문에 이는 필요합니다 stat.

그런 다음 example.gz타임스탬프가 local.dat그보다 최신이면 출력을 example.gz파이프를 통해 리디렉션합니다 .transmogrifylocal.dat

마지막으로 장부 및 정리 작업을 수행합니다.

  • 잘립니다 example.gz(전체 파일이 아닌 타임스탬프만 유지하면 되므로).
  • touchexample.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이것이 소프트웨어 컴파일을 위한 훌륭한 도구라는 것은 모두가 알고 있습니다 . 제 생각에는 시스템 관리 및 스크립팅 작업을 위한 도구로서 심각하게 과소평가된 도구이기도 합니다.

답변2

또 다른 대안은 종속성 체크섬을 사용하여 재구축을 트리거할지 여부를 결정하는 빌드 시스템을 사용하는 것입니다. 나는 종종 Gnu Make의 "터치" 트릭을 사용하지만 동적 종속성을 지정할 수 있고 변경되지 않는 파일이 재빌드를 트리거하지 않으면 훨씬 더 간단합니다. 다음은 사용 예입니다.하오메이케:

#! /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

관련 정보