Bashスクリプトの算術演算の問題無効な算術演算子

Bashスクリプトの算術演算の問題無効な算術演算子

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

からインスピレーションを受ける:https://stackoverflow.com/questions/37885503/check-if-curl-incremental-continue-at-download-is-successful/37885681?

誰でもここで何が問題なのか、解決策を教えてもらえますか?

事前にありがとう

PS:Ubuntu(WSL)でテストしていますが、スクリプトは最終的に組み込みプラットフォームのLinuxに含まれます。欠落している情報があれば教えてください。

答え1

$ curl -sI https://google.com | sed -n '/content-length/l'
content-length: 220\r$

行末のキャリッジリターン文字(別名CR、、、\r)を参照してください(行末を表す方法)。 HTTPヘッダ^M$sedCRLFで区切る、Unix行の区切り文字はLFです。

返品Bashや他のKorn様シェルの算術式から削除されていないデータを使用することは、コマンドインジェクションの脆弱性です。、ここには別の問題があります。つまり、-kaka--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ロケールから一致するもののみを返すことで、10進数のremote_sizeASCII番号のみを含めることで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>

ヘッダ値を抽出する1つの方法は、formailRFC822ヘッダを処理するように特別に設計されたツールを使用することです。

remote_size=$(curl... | formail -zcx content-length -U content-length)

の場合、ヘッダが複数ある-U content-length場合はContent-Length 最後のヘッダが返されます。上記のように最初の項目を返すように-U変更します。-ugrep -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値を持つコンテンツの長さは拒否されます。

関連情報