복사된 디렉토리가 대상에서 더 커지는 것 같습니다.

복사된 디렉토리가 대상에서 더 커지는 것 같습니다.

쉘 스크립트의 일부로 다음 코드가 있습니다.

while [ $(ps -ef | awk '{print $2}' | grep -F "$CPPID") ]; do
    sleep 10
    awk -v "usbsize=$(/bin/df | grep -F $DEVICEMOUNTPOINTQ | awk '{print $3}')" -v "isosize=$(/bin/df | grep -F $ISOMOUNTPOINTQ | awk '{print $3}')" 'BEGIN { printf "%.1f", 100 * usbsize / isosize }' && echo "% copied..."
done

이는 cp다음 작업을 수행하는 모니터링입니다.

cp -a "$ISOMOUNTPOINT"/* "$DEVICEMOUNTPOINT"

그리고 이것은 대부분의 경우 잘 작동합니다.

90.5% copied...
94.2% copied...
97.8% copied...
101.6% copied...
102.7% copied...

이것이 소스 크기의 100%를 초과하는 이유는 무엇입니까? 복사본은 루프 탑재 ISO에서 USB 플래시 드라이브의 NTFS 형식 파티션으로 복사됩니다. 아마도 파일 시스템 문제인 것 같은데요?

크기를 일치시켜 cp완료 시 103%가 아닌 100% 복사되도록 하기 위해 내 예제에서 누락된 것은 무엇입니까?

감사해요.


답장: 바운티

다음 기준을 충족하는 위 코드와 유사한 솔루션을 최초로 생성한 사람에게 현상금을 수여하겠습니다.

  • 스크립트는 1:1 비율로 복사를 감지할 수 있어야 합니다.
  • 스크립트는 100% 복사된 값을 초과하는 값을 표시해서는 안 됩니다.하지만...
  • 스크립트는 이를 초과할 때 단순히 100% 복사된 표시로 제한해서는 안 됩니다.

데이터 크기라면하다실제로 어떤 이유로 소스와 대상이 다른 경우 이를 알아차리고 복사된 실제 비율을 계속 표시하는 스크립트가 필요합니다.

답변1

다음은 단순화되고 더 읽기 쉽게 만들어진 코드입니다.

while ps -p $CPPID > /dev/null
do
    sleep 10
    usbsize=$(/bin/df $DEVICEMOUNTPOINTQ | awk 'NR == 2 {print $3}')
    isosize=$(/bin/df $ISOMOUNTPOINTQ | awk 'NR == 2 {print $3}')
    awk -v "usbsize=$usbsize" -v "isosize=$isosize" 'BEGIN { printf "%.1f%% copied...\n", 100 * usbsize / isosize }'
done

마지막 awk줄은 다음 두 줄로 대체될 수 있습니다.

    percent=$(echo "$usbsize / $isosize * 100" | bc -l)
    printf "%.1f%% copied...\n" $percent

printf그러면 해당 명령문 직전에 다음과 같이 할 수 있습니다 .

if (( $(echo "$percent > 100" | bc) == 1 ))
then
    break
fi

wait $CPPID루프 가 끝난 직후에 추가하세요 while. 100%에 도달하면 인쇄 진행이 중지됩니다.

보다공정 관리PID의 신뢰성에 관해 (재활용됩니다).

당신이 보고 있는 문제는 아마도 대상 파일 시스템의 "사용된" 값을 사용했기 때문일 것입니다.차이점시작 값부터 현재 값으로.

루프 앞에 다음과 같은 줄을 추가해 보세요 while.

startsize=$(/bin/df $DEVICEMOUNTPOINTQ | awk 'NR == 2 {print $3}')

루프 내부의 줄을 다음과 같이 변경합니다.

usbsize=$(/bin/df $DEVICEMOUNTPOINTQ | awk -v "start=$startsize" 'NR == 2 {print $3 - start}')

물론 . rsync --progress대신 사용하면 이 모든 것을 피할 수 있습니다 cp.

편집하다:

또한 while위에 표시된 대로 루프에서 이를 시도하여 계산에 사용되는 숫자가 무엇인지 확인하세요. 이는 무슨 일이 일어나고 있는지에 대한 단서를 제공할 수 있습니다.

    awk -v "usbsize=$usbsize" -v "isosize=$isosize" 'BEGIN { printf "%d of %d, %.1f%% copied...\n", usbsize, isosize, 100 * usbsize / isosize }'

답변2

첫 번째는 소스 디렉토리의 파일 유형에 따라 크게 좌우된다는 것입니다. 나는 아마도 범인이 희소 파일이라고 생각합니다. 희소 파일은 stat.st_size != (stat.st_blksize * stat.st_blocks); 즉, 파일의 전체 크기가 파일의 inode와 연결된 데이터 블록 수보다 큽니다. 할당되지 않은 블록은 시스템 호출에 의해 0 블록으로 읽혀집니다. 따라서 스파스 파일에 cp(1)을 사용하면 대상 파일에는 소스 파일보다 더 많은 블록(0만 포함)이 포함됩니다. du(1) 및 df(1) 명령은 파일 크기가 아닌 블록 수를 확인합니다. 코어 파일은 메모리 매핑이 필요할 수 있으므로 스파스 파일로 생성되는 경우가 많습니다. 이 유형의 파일은 디스크 이미지를 생성하는 데 유용합니다(예: 15GB 크기의 가상 호스트 드라이브 생성). 블록을 생성할 때 모든 블록을 할당하는 것은 매우 낭비입니다. 크기(st_size)는 15GB일 수 있지만 실제 블록 수는 0부터 시작할 수 있습니다.

이는 복사 시 폭발할 수 있는 파일 유형 중 하나일 뿐입니다. 파일 시스템에 무엇이 있는지 알지 못하면 다른 작업이 무엇인지 말하기가 어렵습니다.

답변3

원본과 대상 모두 이름에 ':'가 없어 향상된 복사 명령처럼 작동하는 로컬 전용 모드에서 rsync를 사용할 수 있습니다. 진행률 매개변수를 사용하면 다음과 유사한 내용이 표시됩니다(원천) :

$ rsync -r -v --progress -e ssh root@remote-server:~/pictures /home/user/
receiving file list ...
366 files to consider
pictures/IMG_1142.jpg
 4400662 100%   32.21kB/s    0:02:13 (xfer#31, to-check=334/366)
pictures/IMG_1172.jpg
 2457600  71%   32.49kB/s    0:00:29

이는 총 백분율을 제공하지 않으므로 다른 해결 방법은 이 스크립트를 사용하는 것입니다(원천) :

#!/bin/sh
cp_p()
{
strace -q -ewrite cp -- "${1}" "${2}" 2>&1 \
  | awk '{
    count += $NF
        if (count % 10 == 0) {
           percent = count / total_size * 100
           printf "%3d%% [", percent
           for (i=0;i<=percent;i++)
              printf "="
           printf ">"
           for (i=percent;i<100;i++)
              printf " "
           printf "]\r"
        }
     }
     END { print "" }' total_size=$(stat -c '%s' "${1}") count=0
}

실행 중:

% cp_p /mnt/raid/pub/iso/debian/debian-2.2r4potato-i386-netinst.iso /dev/null
76% [===========================================>                    ]

당신은 또한 볼 수 있습니다진행 표시줄을 사용하여 파일 이동cp 및 mv에 -g 스위치를 추가하여 진행 상황을 표시하는 방법을 자세히 설명합니다.

관련 정보