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'

세 번째 컴퓨터에서 SSH를 통해 업로드하는 것이 더 빠릅니다.

위 솔루션의 단점은 다운로드에 비해 전송 속도가 낮다는 것입니다. 로컬 컴퓨터에 대한 연결은 일반적으로 헤드리스 서버와 다른 서버 간의 연결보다 대역폭이 낮기 때문입니다.

이 문제를 해결하려면 적절한 대역폭을 갖춘 다른 서버에서 위 명령을 실행할 수 있습니다. 이를 보다 편안하게 만들기 위해(세 번째 컴퓨터에서 수동으로 로그인하는 것을 피함) 다음은 실행하는 명령입니다.로컬 컴퓨터에서.

안전을 위해 이 명령을 복사하여 붙여넣으세요.선행 공백 문자 포함 ' '. 그 이유는 아래 설명을 참조하시기 바랍니다.

 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' \
"

설명하다:

  • 이 명령은 세 번째 머신으로 SSH를 연결하고 intermediate-hostSSH를 통해 파일 다운로드를 시작하며 wgetSSH를 통해 업로드를 시작합니다. target-host다운로드와 업로드는 대역폭을 사용 intermediate-host하고 동시에 발생하므로(Bash 파이프 동등성으로 인해) 진행 속도가 빠릅니다.

  • user@*-host이 기능을 사용할 때 두 개의 서버 로그인 이름( ), 대상 호스트 비밀번호( 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는 연결 시도를 확인하기 위해 사용자 입력을 기다립니다. 중간 호스트에 대한 명령이 무기한 중단되는 것을 피하기 위해 어쨌든 진행하도록 둡니다.)

  • sshpasssshor scp명령을 마지막 인수로 예상합니다 . 따라서 wget -O - … | ssh …설명된 대로 bash 파이프가 없는 형식으로 일반적인 명령을 다시 작성해야 합니다.여기.

관련 정보