다음은 한 디렉터리에서 다른 디렉터리로 파일을 복사하는 Ubuntu 18.04의 스크립트입니다. 현재 디렉터리()의 파일이 /media/rmerriam/Backup/rsync_backup
대상에 복사된다는 점을 제외하면 모든 것이 잘 작동합니다. 소스 경로에 전혀 없었으므로 전혀 복사해서는 안 됩니다.
수동 실행(유무와 상관없음 -s
):
rmerriam@mysticlakelinux:/media/rmerriam/test/rsync_backup$ rsync -auv -s ../src/ ../dest
sending incremental file list
sent 59 bytes received 12 bytes 142.00 bytes/sec
total size is 0 speedup is 0.00
rmerriam@mysticlakelinux:/media/rmerriam/test/rsync_backup$ ls ../dest
실행된 스크립트에는 다음이 없습니다 -s
.
===========================
./merge.sh
../src/
../dest
rsync -auv ../src/ ../dest
sending incremental file list
./ <====== added why???
merge.sh
merge_all.sh
merge_backups.sh
sent 3,124 bytes received 76 bytes 6,400.00 bytes/sec
total size is 2,835 speedup is 0.89
rmerriam@mysticlakelinux:/media/rmerriam/test/rsync_backup$ ls ../dest
merge_all.sh merge_backups.sh merge.sh
옵션을 사용하여 스크립트를 실행합니다 -s
.
rmerriam@mysticlakelinux:/media/rmerriam/test/rsync_backup$ ./merge.sh ../src/ ../dest -s
===========================
./merge.sh
-s
../src/
../dest
rsync -auv -s ../src/ ../dest
sending incremental file list
./
sent 66 bytes received 19 bytes 170.00 bytes/sec
total size is 0 speedup is 0.00
rmerriam@mysticlakelinux:/media/rmerriam/test/rsync_backup$ ls ../dest
결과:수동 실행 및 옵션으로 파일이 -s
이동되지 않았습니다 . 스크립트 $PWD
가 없으면 -s
파일이 복사됩니다.
스크립트는 -s
이 ./
디렉터리를 소스 디렉터리로 추가하지 않습니다. 왜?
명령줄은 다음 echo
과 같이 표시되며 동일합니다. 스크립트에 다른 동작이 있는 이유는 무엇입니까?
스크립트는 다음과 같습니다.
#!/bin/bash
# base script for copying files to the common directory.
# only copies newer files
printf '===========================\n'
printf "$0\n $3\n $1\n $2\n"
echo rsync -auv "$3" "$1" "$2"
rsync -auv "$3" "$1" "$2"
참고로:rsync version 3.1.2 protocol version 31
답변1
스크립트에 버그가 있습니다. 틀림없이 rsync에도 버그가 있습니다. 왜냐하면 이상한 데이터를 전달하면 조용히 놀라운 일을 하고, 그냥 잘못되도록 두는 것이 더 낫기 때문입니다. 그러나 어느 쪽이든 스크립트가 작동하지 않습니다.
문제가 있는 줄은 다음과 같습니다.
rsync -auv "$3" "$1" "$2"
이는 script( ) "$3"
의 세 번째 인수가 a로 시작하는 경우 -
rsync에 대한 옵션입니다 . 그러나 세 번째 인수가 a로 시작하지 않는 경우 -
(스크립트에 인수가 두 개(또는 그 이하)만 있는 경우 포함)는 옵션이 아닌 인수입니다. Rsync는 여러 소스 디렉터리를 허용하므로 "$3"
a로 시작하지 않으면 복사 를 -
요청하는 것 입니다 ."$3"
"$1"
"$2"
./merge.sh ../src/ ../dest
../src/
rsync 에게 빈 문자열을 ../dest
.
대부분의 응용 프로그램은 파일 이름을 찾을 때 빈 문자열을 거부합니다. 그러나 빈 문자열이 파일 이름으로 허용될 때마다 이는 현재 디렉터리를 나타냅니다. 이는 상대 경로가 절대 경로로 변환되는 방식과 일치합니다. 경로가 상대 경로인 경우( 로 시작하지 않음 /
) 현재 작업 디렉터리의 절대 경로 앞에 슬래시를 추가하면 동등한 절대 경로를 얻게 됩니다. 이것을 빈 문자열(슬래시로 시작하지 않기 때문에 상대 경로임)에 적용하면 끝에 슬래시가 있는 현재 작업 디렉터리, 즉 현재 작업 디렉터리를 얻게 됩니다.
Rsync는 빈 문자열을 현재 디렉터리로 허용합니다. 그래서 당신이 말한 것과 정확히 일치합니다.
빈 문자열을 매개변수로 전달하는 것은 의도적인 것보다 버그일 가능성이 더 높습니다. 현재 디렉토리를 지정하는 가장 짧고 널리 사용되는 방법은 .
(점)입니다. 따라서 rsync는 매개변수가 유효하지 않아 오류가 발생했다는 오류 메시지를 인쇄해야 한다고 말할 수 있습니다.
스크립트에서 선택적인 추가 옵션을 허용하기를 원하지만 이를 구현하는 방식에 따르면 해당 추가 옵션은 필수입니다. 선택사항으로 만들려면 스크립트에 세 번째 매개변수가 있는지 확인하세요.
if [ $# -lt 2 ]; then
echo >&2 "$0: too few arguments (SRC and DEST are required)"
exit 120
elif [ $# -eq 2 ]; then
rsync -auv "$1" "$2"
elif [ $# -eq 3 ]; then
rsync -auv "$3" "$1" "$2"
else
echo >&2 "$0: too many arguments (only one OPTIONS argument is permitted)"
exit 120
fi
하지만 인터페이스는 이상합니다. 왜 최대 하나의 옵션만 허용합니까? 다양한 옵션을 수락할 수도 있습니다(왜 통과할 수 없나요 -q --dry-run
?). 이는 사용자가 이해하기 쉽고 구현하기도 더 쉽습니다. 게다가 관례는 옵션을 전달하는 것입니다.앞으로옵션이 아닌 인수, 이후가 아닙니다. 인터페이스가 단순화되어 다양한 옵션을 수용할 수 있게 되면 코드를 단순화하여 다음과 같이 할 수 있습니다.
rsync -auv "$@"
답변2
가서 문제를 확인 rsync
하고 알아보세요"빈 따옴표는 SRC 디렉토리에 cwd를 추가합니다.". $3
추가 옵션을 추가하는 스크립트에 문제가 있습니다 . 보통은 비어 있어서 그게 범인이죠. Added는 -s
매개변수를 null이 아닌 것으로 만들어 이 문제를 방지합니다.
이 수동 실행을 통해 문제가 확인되었습니다.
rsync "" -auv ../src/ ../dest
sending incremental file list
created directory ../dest
./
merge.sh
merge_all.sh
merge_backups.sh
sent 3,124 bytes received 106 bytes 6,460.00 bytes/sec
total size is 2,835 speedup is 0.88