[unix] GNU make에서 HTTP의 파일을 전제 조건으로 사용하려면 어떻게해야합니까?

나는 파일을 사용하고자하는 월드 와이드 웹 내 메이크의 전제 조건으로 :

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

make가 정상적으로 작동하는 것처럼 원격 파일이 로컬 파일보다 최신 버전 인 경우에만 “변환”하고 싶습니다 .

나는 할 수 없습니다 의 캐시 된 복사본을 유지하려는 example.gz를 파일이 크고, 나는 원시 데이터를 필요로하지 않습니다 -. 바람직하게는 파일 다운로드를 전혀 피하고 싶습니다. 목표는 -jmake 플래그를 사용하여 이들 중 몇 가지를 병렬로 처리하는 것입니다.

이것을 해결하는 확실한 방법은 무엇입니까? 몇 가지 방법을 생각할 수 있습니다.

  • 빈 더미 파일을 보관하고 대상을 다시 만들 때마다 업데이트하십시오.
  • GNU make의 새로운 플러그인 시스템을 사용하는 일부 플러그인 (아무것도 모른다)
  • 로컬 파일 시스템에 HTTP 서버를 마운트하는 독립적 인 방법

더 파고 들기 전에 몇 가지 조언, 바람직하게는 구체적인 예를 원합니다!



답변

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-cond만 다운로드) 옵션을 example.gz그것을 다운로드 한 마지막 시간 이후 수정 된 경우. -z실제 날짜 표현 또는 파일 이름을 지정할 수 있습니다. 파일 이름이 제공되면 파일의 수정 시간을 시간 조건으로 사용합니다.

그런 다음 local.dat존재하지 않는 경우 시간 보다 오래된touch 타임 스탬프를 사용하여로 만듭니다 . 이것은 mtime 타임 스탬프를 얻기 위해 다음 명령을 사용 하기 위해 필요하기 때문에 필요 합니다 .example.gzlocal.datstat

그런 다음 example.gz보다 최신 타임 스탬프가있는 경우 local.dat파이프 example.gztransmogrify출력을로 리디렉션합니다 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는 또한 시스템 관리 및 스크립팅 작업을위한 매우 과소 평가 된 도구입니다.


답변

또 다른 대안은 종속성 체크섬을 사용하는 빌드 시스템을 사용하여 재구성을 트리거할지 여부를 결정하는 것입니다. 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


답변