编写Makefile实现服务器到本地增量同步文件遇错求助
问题分析与解决方案
原错误原因解析
第一个错误:No rule to make target '*.csv'
FILES = *.csv采用的是make的延迟展开语法,解析规则时不会自动展开通配符,make会将*.csv当作一个具体的目标文件,但本地不存在这个文件,因此报错。改用$(wildcard *.csv)虽然能展开本地已有的csv文件,但后续scp命令逻辑错误,导致新问题。
第二个错误:results3.csv: Not a directory
scp的语法是scp [源路径] [目标路径],你的原命令把服务器路径id@server:~/Results作为源,本地csv文件作为目标,这会让scp尝试将服务器上的目录复制到本地文件中(而非目录),自然报错。
正确解决方案
方案一:修正Makefile逻辑(纯make实现)
核心思路是通过ssh获取远程文件的修改时间,对比本地文件和同步标记的时间,仅同步更新的文件:
#!/usr/bin/make -f REMOTE_USER_SERVER = id@server REMOTE_PATH = ~/Results LOCAL_PATH = ./ LAST_SYNC = .last_sync # 获取远程服务器上的csv文件列表 REMOTE_CSV_FILES := $(shell ssh $(REMOTE_USER_SERVER) ls -1 $(REMOTE_PATH)/*.csv | xargs basename) .PHONY: sync sync: @for file in $(REMOTE_CSV_FILES); do \ # 获取远程文件的修改时间戳 REMOTE_TIMESTAMP=$$(ssh $(REMOTE_USER_SERVER) stat -c "%Y" "$(REMOTE_PATH)/$$file"); \ # 获取本地文件的修改时间戳(不存在则设为0) LOCAL_TIMESTAMP=$$(if [ -f "$(LOCAL_PATH)/$$file" ]; then stat -c "%Y" "$(LOCAL_PATH)/$$file"; else 0; fi); \ # 获取上次同步的时间戳(不存在则设为0) LAST_SYNC_TIMESTAMP=$$(if [ -f $(LAST_SYNC) ]; then cat $(LAST_SYNC); else 0; fi); \ # 仅同步远程比本地新、且比上次同步时间新的文件 if [ $$REMOTE_TIMESTAMP -gt $$LOCAL_TIMESTAMP ] && [ $$REMOTE_TIMESTAMP -gt $$LAST_SYNC_TIMESTAMP ]; then \ echo "同步文件: $$file"; \ scp $(REMOTE_USER_SERVER):$(REMOTE_PATH)/$$file $(LOCAL_PATH); \ fi; \ done # 更新同步时间戳 @date +%s > $(LAST_SYNC)
方案二:改用rsync(更简单可靠)
rsync原生支持增量同步,无需手动处理时间对比,是这类场景的最优解:
#!/usr/bin/make -f REMOTE_DIR = id@server:~/Results/ LOCAL_DIR = ./ LAST_SYNC = .last_sync .PHONY: sync sync: # --update:仅复制比本地新的文件;--include/--exclude:只同步csv文件 rsync -av --update --include='*.csv' --exclude='*' $(REMOTE_DIR) $(LOCAL_DIR) touch $(LAST_SYNC)
参数说明:
-a:归档模式,保留文件权限、所有者等属性-v:显示同步过程细节--update:跳过本地比远程新的文件,仅同步更新的内容--include='*.csv' --exclude='*':精准筛选仅同步csv文件,排除其他文件
内容的提问来源于stack exchange,提问作者oscarcapote
相关产品推荐
相关产品推荐

