나는 파일을 사용하고자하는 월드 와이드 웹 내 메이크의 전제 조건으로 :
local.dat: http://example.org/example.gz
curl -s $< | gzip -d | transmogrify >$@
make가 정상적으로 작동하는 것처럼 원격 파일이 로컬 파일보다 최신 버전 인 경우에만 “변환”하고 싶습니다 .
나는 할 수 없습니다 의 캐시 된 복사본을 유지하려는 example.gz를 파일이 크고, 나는 원시 데이터를 필요로하지 않습니다 -. 바람직하게는 파일 다운로드를 전혀 피하고 싶습니다. 목표는 -j
make 플래그를 사용하여 이들 중 몇 가지를 병렬로 처리하는 것입니다.
이것을 해결하는 확실한 방법은 무엇입니까? 몇 가지 방법을 생각할 수 있습니다.
- 빈 더미 파일을 보관하고 대상을 다시 만들 때마다 업데이트하십시오.
- 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.gz
local.dat
stat
그런 다음 example.gz
보다 최신 타임 스탬프가있는 경우 local.dat
파이프 example.gz
에 transmogrify
출력을로 리디렉션합니다 local.dat
.
마지막으로 부기 및 정리 작업을 수행합니다.
example.gz
전체 파일이 아닌 타임 스탬프 만 유지하면되기 때문에 잘립니다.touch
esexample.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