Mam minimalny * nix bezgłowy, który nie ma żadnych narzędzi wiersza poleceń do pobierania plików (np. Bez curl, wget itp.). Mam tylko uderzenie.
Jak mogę pobrać plik?
Idealnie chciałbym mieć rozwiązanie, które działałoby w szerokim zakresie * nix.
bash
command-line
web
Chris Snow
źródło
źródło
gawk
Odpowiedzi:
Jeśli masz wersję bash 2.04 lub nowszą z
/dev/tcp
włączonym pseudo-urządzeniem, możesz pobrać plik z samej wersji bash.Wklej następujący kod bezpośrednio do powłoki bash (nie musisz zapisywać kodu w pliku do wykonania):
Następnie możesz wykonać go z poziomu powłoki w następujący sposób:
Źródło: odpowiedź Moreaki dotycząca aktualizacji i instalacji pakietów za pomocą wiersza poleceń cygwin?
Aktualizacja: jak wspomniano w komentarzu, podejście opisane powyżej jest uproszczone:
read
wola trashes backslashy i prowadząc spacje.$line
będzie glob.źródło
while read
tak, że kasuje ukośniki odwrotne i wiodące białe znaki, a Bash nie radzi sobie bardzo dobrze z bajtami NUL, więc pliki binarne są usuwane. I nie cytowany$line
będzie glob ... Nic z tego nie widzę wspomniane w odpowiedzi.Użyj rysia.
Jest to dość powszechne w większości systemów Unix / Linux.
-dump: zrzuć pierwszy plik na standardowe wyjście i wyjdź
Lub netcat:
Lub telnet:
źródło
lynx -source
jest bliższa wgetNa podstawie odpowiedzi Chrisa Snowa Może to również obsługiwać pliki binarne
Możesz testować takie pliki binarne
źródło
cat
. Nie jestem pewien, czy to oszustwo (ponieważ nie jest to wyłącznie powłoka), czy fajne rozwiązanie (ponieważcat
w końcu jest to standardowe narzędzie). Ale @ 131, możesz dodać notatkę o tym, dlaczego działa lepiej niż inne rozwiązania tutaj.Przyjmując ściśle „ tylko Bash i nic więcej ”, oto jedna adaptacja wcześniejszych odpowiedzi ( @ Chris's , @ 131's ), która nie wywołuje żadnych zewnętrznych narzędzi (nawet standardowych), ale działa również z plikami binarnymi:
Użyj z
download http://path/to/file > file
.Mamy do czynienia z bajtami NUL
read -d ''
. Czyta do bajtu NUL i zwraca true, jeśli go znalazł, a false, jeśli nie. Bash nie może obsłużyć bajtów NUL w ciągach, więc gdyread
zwraca true, dodajemy bajt NUL ręcznie podczas drukowania, a gdy zwraca false, wiemy, że nie ma już bajtów NUL i powinien to być ostatni kawałek danych .Testowane z Bash 4.4 na plikach z NUL w środku, a kończące się na zero, jeden lub dwa NUL, a także z
wget
icurl
binaria z Debiana.wget
Pobranie pliku binarnego o wielkości 373 kB zajęło około 5,7 sekundy. Prędkość około 65 kB / s lub nieco więcej niż 512 kb / s.Dla porównania, rozwiązanie dla kota @ 131 kończy się w mniej niż 0,1 s, czyli prawie sto razy szybciej. Naprawdę niezbyt zaskakujące.
Jest to oczywiście głupie, ponieważ bez korzystania z zewnętrznych narzędzi nie możemy wiele zrobić z pobranym plikiem, nawet nie można go uruchomić.
źródło
echo
iprintf
jako wbudowane (potrzebuje wbudowanegoprintf
do wdrożeniaprintf -v
)Jeśli masz ten pakiet libwww-perl
Możesz po prostu użyć:
źródło
lynx
rozwiązanie, ponieważ Perl jest z pewnością bardziej preinstalowany niż Lynx.Zamiast tego użyj przesyłania przez SSH z lokalnego komputera
„Minimalna liczba bezgłowych * nix” oznacza, że prawdopodobnie używasz SSH. Możesz więc użyć SSH, aby przesłać do niego. Co jest funkcjonalnie równoważne pobieraniu (pakietów oprogramowania itp.), Z wyjątkiem sytuacji, gdy chcesz, aby polecenie pobierania zawierało się w skrypcie na twoim serwerze bezgłowym.
Jak pokazano w tej odpowiedzi , należy wykonać następujące czynności na komputerze lokalnym , aby umieścić plik na zdalnym serwerze bezgłowym:
Szybsze przesyłanie przez SSH z trzeciego komputera
Wadą powyższego rozwiązania w porównaniu do pobierania jest niższa prędkość transferu, ponieważ połączenie z lokalną maszyną ma zwykle znacznie mniejszą przepustowość niż połączenie między serwerem bezgłowym a innymi serwerami.
Aby rozwiązać ten problem, możesz oczywiście wykonać powyższe polecenie na innym serwerze z przyzwoitą przepustowością. Aby uczynić to wygodniejszym (unikając ręcznego logowania na trzecim komputerze), oto polecenie, które należy wykonać na komputerze lokalnym .
Aby zabezpieczyć się, skopiuj i wklej to polecenie, w tym wiodący znak spacji
' '
. Powód wyjaśniono poniżej.Objaśnienia:
Polecenie prześle ssh na twój trzeci komputer
intermediate-host
, rozpocznie pobieranie pliku do niego przezwget
i rozpocznie przesyłanie go natarget-host
SSH. Pobieranie i przesyłanie wykorzystuj przepustowość twojegointermediate-host
i dzieje się w tym samym czasie (ze względu na odpowiedniki rur Bash), więc postęp będzie szybki.Korzystając z tego, musisz zastąpić dwa loginy serwera (
user@*-host
), hasło hosta docelowego (yourpassword
), adres URL pobierania (http://example.com/…
) i ścieżkę wyjściową na hoście docelowym (/path/to/output-file.zip
) odpowiednimi własnymi wartościami.Aby
-T -e none
zapoznać się z opcjami SSH podczas przesyłania plików, zobacz te szczegółowe wyjaśnienia .To polecenie jest przeznaczone dla przypadków, w których nie można użyć mechanizmu uwierzytelniania klucza publicznego SSH - nadal występuje w przypadku niektórych dostawców hostingu współdzielonego, w szczególności Host Europe . Aby nadal automatyzować proces, polegamy na tym, że możemy
sshpass
podać hasło w poleceniu. Wymagasshpass
to zainstalowania na twoim hoście pośrednim (sudo apt-get install sshpass
pod Ubuntu).Staramy się używać
sshpass
w bezpieczny sposób, ale nadal nie będzie tak bezpieczny, jak mechanizm klucza publicznego SSH (mówiman sshpass
). W szczególności podajemy hasło SSH nie jako argument wiersza poleceń, ale poprzez plik, który jest zastępowany przez podstawienie procesu bash, aby upewnić się, że nigdy nie istnieje na dysku. Jestprintf
to wbudowany bash, upewniający się, że ta część kodu nie wyskakuje jako osobne polecenieps
wyjściowe, ponieważ odsłoniłoby to hasło [ źródło ]. Myślę , że takie użyciesshpass
jest tak samo bezpieczne, jaksshpass -d<file-descriptor>
zalecany wariantman sshpass
, ponieważ bash i tak mapuje go wewnętrznie na taki/dev/fd/*
deskryptor pliku. I to bez użycia pliku tymczasowego [ źródło]. Ale żadnych gwarancji, może coś przeoczyłem.Ponownie, aby
sshpass
korzystanie było bezpieczne, musimy zapobiec zapisywaniu polecenia w historii bash na twoim komputerze lokalnym. W tym celu całe polecenie jest poprzedzone jednym znakiem spacji, który ma ten efekt.-o StrictHostKeyChecking=no
Część zapobiega polecenie braku w przypadku, gdy nie podłączonego do docelowego gospodarza. (Zwykle SSH czekałby następnie na dane wejściowe użytkownika, aby potwierdzić próbę połączenia. My i tak kontynuujemy.)sshpass
oczekuje poleceniassh
lubscp
jako ostatniego argumentu. Musimy więc przepisać typowewget -O - … | ssh …
polecenie do postaci bez potoku, jak wyjaśniono tutaj .źródło
Na podstawie przepisu @Chris Snow. Wprowadziłem kilka ulepszeń:
Oto kod:
źródło
echo -en "GET ${PATH} HTTP/1.1\r\nHost: ${HOST}\r\n${tag}\r\n\r\n" >&3
,${tag}
nie jest określona.tag
zmienna ma poprawny zestaw, teraz działa dobrze.