bashだけを使用し、他のものを使用せずに(curl、wget、perlなどを使用せずに)ファイルをダウンロードする方法

bashだけを使用し、他のものを使用せずに(curl、wget、perlなどを使用せずに)ファイルをダウンロードする方法

最小限のヘッドレス* nixがあります。含まないファイルをダウンロードするためのコマンドラインユーティリティ(カールなし、wgetなど)のバッシュのみがあります。

ファイルをどのようにダウンロードできますか?

理想的には、広範囲の* nixで動作するソリューションが欲しいです。

答え1

Bash 2.04以降があり、/dev/tcp疑似デバイスが有効になっている場合は、Bash自体からファイルをダウンロードできます。

次のコードを bash シェルに直接貼り付けます(実行のためにコードをファイルに保存する必要はありません)。

function __wget() {
    : ${DEBUG:=0}
    local URL=$1
    local tag="Connection: close"
    local mark=0

    if [ -z "${URL}" ]; then
        printf "Usage: %s \"URL\" [e.g.: %s http://www.google.com/]" \
               "${FUNCNAME[0]}" "${FUNCNAME[0]}"
        return 1;
    fi
    read proto server path <<<$(echo ${URL//// })
    DOC=/${path// //}
    HOST=${server//:*}
    PORT=${server//*:}
    [[ x"${HOST}" == x"${PORT}" ]] && PORT=80
    [[ $DEBUG -eq 1 ]] && echo "HOST=$HOST"
    [[ $DEBUG -eq 1 ]] && echo "PORT=$PORT"
    [[ $DEBUG -eq 1 ]] && echo "DOC =$DOC"

    exec 3<>/dev/tcp/${HOST}/$PORT
    echo -en "GET ${DOC} HTTP/1.1\r\nHost: ${HOST}\r\n${tag}\r\n\r\n" >&3
    while read line; do
        [[ $mark -eq 1 ]] && echo $line
        if [[ "${line}" =~ "${tag}" ]]; then
            mark=1
        fi
    done <&3
    exec 3>&-
}

その後、次のようにシェルで実行できます。

__wget http://example.iana.org/

源泉:モレキ回答cygwinコマンドラインでパッケージをアップグレードしてインストールしますか?

修正する: コメントで述べたように、上記のアプローチは簡単です。

  • readバックスラッシュと先行スペースは削除されます。
  • Bash は NUL バイトをうまく処理できないため、バイナリは廃止されました。
  • 引用符をオフにするとグローバルに$lineなります。

答え2

ボブキャットをご利用ください。

これはほとんどのUnix / Linuxで一般的です。

lynx -dump http://www.google.com

-dump:最初のファイルを標準出力にダンプして終了します。

man lynx

またはネットキャット:

/usr/bin/printf 'GET / \n' | nc www.google.com 80

またはリモートでログインしてください。

(echo 'GET /'; echo ""; sleep 1; ) | telnet www.google.com 80

答え3

から適応クリス・スノーの答え。これはバイナリファイルも処理できます。

function __curl() {
  read -r proto server path <<<"$(printf '%s' "${1//// }")"
  if [ "$proto" != "http:" ]; then
    printf >&2 "sorry, %s supports only http\n" "${FUNCNAME[0]}"
    return 1
  fi
  DOC=/${path// //}
  HOST=${server//:*}
  PORT=${server//*:}
  [ "${HOST}" = "${PORT}" ] && PORT=80

  exec 3<>"/dev/tcp/${HOST}/$PORT"
  printf 'GET %s HTTP/1.0\r\nHost: %s\r\n\r\n' "${DOC}" "${HOST}" >&3
  (while read -r line; do
   [ "$line" = $'\r' ] && break
  done && cat) <&3
  exec 3>&-
}
  • 私  break && cat から出たいですread
  • 私はHTTP 1.0を使用しているので、接続:閉じるのを待つか送信する必要はありません。

次のようにバイナリをテストできます。

$ __curl http://www.google.com/favicon.ico >   mine.ico
$ curl   http://www.google.com/favicon.ico > theirs.ico
$ md5sum mine.ico theirs.ico
f3418a443e7d841097c714d69ec4bcb8  mine.ico
f3418a443e7d841097c714d69ec4bcb8  theirs.ico

答え4

ローカルコンピュータでSSHを使用してアップロード

「Minimal headless *nix」ボックスは、SSH経由で接続できることを意味します。したがって、SSHを使用することもできます。アップロードそれに。これは機能的に(パッケージなど)ダウンロードと同じです。とは別にもちろん、ヘッドレスサーバーのスクリプトにダウンロードコマンドを含めたい場合です。

図からわかるようにこの回答、あなたがすること地元のリモートヘッドレスサーバーシステムにファイルを配置します。

wget -O - http://example.com/file.zip | ssh user@host 'cat >/path/to/file.zip'

3台目のコンピュータでSSH経由でアップロードする方が高速です。

上記の解決策の欠点は、ダウンロードに比べて転送速度が低いことです。ローカルコンピュータへの接続は、通常、ヘッドレスサーバーと他のサーバー間の接続より帯域幅が低いためです。

この問題を解決するには、適切な帯域幅を持つ他のサーバーで上記のコマンドを実行できます。これをより快適にするために(3台目のコンピュータで手動でログインするのを避けるため)、次は実行するコマンドです。ローカルコンピュータで

安全のため、このコマンドをコピーして貼り付けてください。先行スペース文字を含む ' '。その理由については、以下の説明を参照してください。

 ssh user@intermediate-host "sshpass -f <(printf '%s\n' yourpassword) \
   ssh -T -e none \
     -o StrictHostKeyChecking=no \
     < <(wget -O - http://example.com/input-file.zip) \
     user@target-host \
     'cat >/path/to/output-file.zip' \
"

説明する:

  • このコマンドは、3 台目のマシンで SSH を接続し、intermediate-hostSSH 経由でファイルのダウンロードを開始し、wgetSSH 経由でアップロードを開始します。target-hostダウンロードとアップロードは帯域幅を使用intermediate-hostして同時に発生するため(Bashパイプ同等​​性のため)、進行速度が速くなります。

  • user@*-hostこの機能を使用するときは、2つのサーバーログイン名()、宛先ホストパスワード(yourpassword)、ダウンロードURL(http://example.com/…)、および宛先ホストの出力パス(/path/to/output-file.zip)を適切な値に置き換える必要があります。

  • -T -e noneSSHを使用してファイルを転送する場合のオプションについては、以下を参照してください。この詳細な説明は

  • このコマンドは、SSH公開鍵認証メカニズムが利用できない状況のためのものです。これは、一部の共有ホスティングプロバイダでも引き続き発生します。特に開催国ヨーロッパ。プロセスを自動化するには、sshpassコマンドにパスワードを提供できる必要があります。sshpass中間ホスト(Ubuntuの下)にインストールする必要がありますsudo apt-get install sshpass

  • 私たちはそれを安全な方法で使用しようとしますsshpassが、それでもSSH公開鍵メカニズム(例えば)ほど安全ではありませんman sshpass。特に、SSHパスワードをコマンドライン引数として提供するのではなく、ファイルを介して提供します。ファイルは、ディスクに存在しないように bash プロセスに置き換えられます。これはprintf組み込みのbashです。コードのこの部分がpsパスワードを公開する可能性があるため、出力が別のコマンドでポップアップしないことを確認してください。源泉]。私考えるsshpassこの使用法は、bashが内部的に対応するファイル記述子にマップするので、推奨されるバリアントほど安全です。一時ファイルを使用しない[sshpass -d<file-descriptor>man sshpass/dev/fd/*源泉]。しかし、保証することはできません。たぶん私が見落としている部分があるかもしれません。

  • 繰り返しますが、安全な使用を保証するには、sshpassこのコマンドがローカルコンピュータのbash履歴に書き込まれないようにする必要があります。これを行うには、コマンド全体の前にスペース文字を追加してこの効果を得ます。

  • この-o StrictHostKeyChecking=noセクションは、ターゲットホストが接続されていない場合にコマンドが失敗するのを防ぎます。 (通常、SSHは接続の試みを確認するためにユーザー入力を待ちます.

  • sshpasssshorscpコマンドを最後の引数と見なします。したがって、wget -O - … | ssh …説明されているように、bashパイプを持たない形式で一般的なコマンドを再構築する必要があります。ここ

関連情報