Bash 스크립트에서 call을 사용하여 서버에서 파일을 다운로드합니다 curl
. 이제 파일이 완전히 다운로드되었는지 확인하고 싶습니다. 이를 위해 다운로드 파일과 헤더 크기를 비교했습니다 Content-Length
. 둘 다 동일하지만 다음 오류가 발생합니다.
")syntax error: invalid arithmetic operator (error token is "
Bash 스크립트의 일부:
remote_size=$(curl -kI "${HEADERS[@]}" "$url" | grep -i content-length | awk '{print $2}')
local_size=$(stat --format=%s "$dest/$file")
if (( remote_size == local_size )); then
echo "File is complete" >&2
elif (( remote_size > local_size )); then
echo "Download is incomplete" >&2
elif (( remote_size < local_size )); then
echo "Remote file shrunk -- probably should delete local and start over" >&2
fi
누구든지 여기에 문제가 무엇인지, 해결 방법을 말해 줄 수 있습니까?
미리 감사드립니다
추신: 우분투(WSL)에서 테스트 중이지만 스크립트는 결국 임베디드 플랫폼의 Linux에 포함될 것입니다. 누락된 정보가 있으면 알려주세요.
답변1
$ curl -sI https://google.com | sed -n '/content-length/l'
content-length: 220\r$
줄 끝에 있는 캐리지 리턴 문자(일명 CR
, \r
, )를 참조하세요(줄 끝을 나타내는 방법). HTTP 헤더^M
$
sed
CRLF로 구분, Unix 줄 구분 기호는 LF입니다.
반품Bash 및 기타 Korn 유사 셸의 산술 표현식에서 삭제되지 않은 데이터를 사용하는 것은 명령 주입 취약점입니다., 여기에는 또 다른 문제가 있습니다. 즉, -k
aka --insecure
옵션을 사용하면 MitM 공격자가 응답에 임의의 헤더를 삽입할 수 있습니다.
GNU 시스템에서는 다음을 사용할 수 있습니다.
local_size=$(stat -Lc %s -- "$dest/$file") || die
remote_size=$(curl -sI -- "$url" | LC_ALL=C grep -Piom1 '^content-length:\s*\K\d+') ||
die "No content-length"
case $((local_size - remote_size)) in
(0) echo same;;
(-*) echo remote bigger;;
(*) echo local bigger;;
esac
\d+
C 로케일에서 일치하는 항목 만 반환함으로써 remote_size
십진수 ASCII 숫자만 포함되도록 하여 ACE 취약성을 제거합니다.
이 GNU 명령에 해당하는 표준은 grep
다음과 같습니다.
LC_ALL=C sed '/^[Cc][Oo][Nn][Tt][Ee][Nn][Tt]-[Ll][Ee][Nn][Gg][Tt][Hh]:[[:space:]]*\([0-9]\{1,\}\).*/!d;s//\1/;q'
헤더를 찾을 수 없으면 반환되지 않습니다.잘못된종료 상태는 grep
이와 같은 작업을 수행하므로 추가로 확인해야 합니다 [ -n "$remote_size" ]
.
die
위의 내용은 다음과 같습니다.
die() {
[ "$#" -eq 0 ] || printf>&2 '%s\n' "$@"
exit 1
}
(사용하려는 로깅 메커니즘에 맞게 조정하세요).
또한 실제로는 이런 일이 발생할 가능성이 낮지만 헤더가 접힐 수 있다는 점에 유의하세요. 예를 들어 콘텐츠 길이 헤더는 다음과 같이 반환될 수 있습니다.
Content-Length:<CR>
123456<CR>
헤더 값을 추출하는 한 가지 방법은 formail
RFC822 헤더를 처리하도록 특별히 설계된 도구를 사용하는 것입니다.
remote_size=$(curl... | formail -zcx content-length -U content-length)
의 경우 헤더가 -U content-length
여러 개인 경우 Content-Length
마지막 헤더가 반환됩니다. 위와 같이 첫 번째 항목을 반환 -U
하도록 변경합니다 .-u
grep -m1
ACE 취약점을 방지 하려면 결과를 삭제하거나 대신 [
's( [[...]]
's! 아님) -lt
// -eq
연산자를 사용해야 합니다.-gt
((...))
버전 7.84.0 이상을 사용 하면 다음을 사용하여 이 헤더의 값을 직접 제공 curl
할 수도 있습니다 .curl
remote_size=$(curl -w '%header{content-length}' -sIo /dev/null -- "$url") || die
테스트를 통해 알아낸 것은
- 헤더가 여러 번 나타나는 경우 첫 번째 헤더의 값만 반환됩니다.
- 값이 숫자로 시작하지 않으면(선택적으로 a로 시작) 불평
+
하지만 그 뒤에 전달된 모든 문자를 삭제해야 합니다. - 헤더 축소를 지원하지만 첫 번째 행에 null 값이 있는 콘텐츠 길이는 거부됩니다.