Działa dobrze jako pojedyncze narzędzie:
curl "someURL"
curl -o - "someURL"
ale nie działa w potoku:
curl "someURL" | tr -d '\n'
curl -o - "someURL" | tr -d '\n'
zwraca:
(23) Failed writing body
Jaki jest problem z przesyłaniem potoku na wyjście cURL? Jak zbuforować całe wyjście cURL, a następnie obsłużyć?
curl 'http://www.multitran.ru/c/m.exe?CL=1&s=hello&l1=1' | tr -d '\n'
iconv -f ...
Odpowiedzi:
Dzieje się tak, gdy program potokowy (np. Grep) zamyka potok odczytu przed zakończeniem zapisywania całej strony przez poprzedni program.
W programie
curl "url" | grep -qs foo
, gdy tylko grep uzyska to, czego chce, zamknie strumień odczytu z curl. cURL nie oczekuje tego i emituje błąd „Błąd zapisu treści”.Rozwiązaniem jest przepuszczenie strumienia przez program pośredniczący, który zawsze czyta całą stronę przed przekazaniem jej do następnego programu.
Na przykład
tac
jest prostym programem uniksowym, który czyta całą stronę wejściową i odwraca kolejność wierszy (dlatego uruchamiamy go dwukrotnie). Ponieważ musi odczytać całe wejście, aby znaleźć ostatnią linię, nie wyśle nic do grep, dopóki cURL nie zostanie zakończony. Grep nadal zamyka strumień odczytu, gdy ma to, czego szuka, ale wpłynie tylko na tac, który nie generuje błędu.źródło
cat
raz? Przynajmniej rozwiązuje problem dla mnie.-s
Możesz użyć do wyciszenia wszystkich komunikatów o błędach (i postępu), jeśli ich nie potrzebujesz.tac|tac
zmienia dane wejściowe, jeśli wejście nie kończy się wysuwem wiersza, lub na przykładprintf a\\nb\\nc|tac|tac
wypisujea\ncb
gdzie\n
jest wysuw. Możesz użyćsponge /dev/stdout
zamiast tego. Inną opcją jestprintf %s\\n "$(cat)"
, ale gdy dane wejściowe zawierają bajty o wartości null w powłokach innych niż Zsh, to albo pomija bajty zerowe, albo przestaje czytać po pierwszym bajcie zerowym.tac
polecenia w systemie macOSAby uzyskać kompletność i przyszłe wyszukiwania:
Jest to kwestia tego, jak cURL zarządza buforem, bufor wyłącza strumień wyjściowy opcją -N.
Przykład:
curl -s -N "URL" | grep -q Welcome
źródło
curl -s https://raw.githubusercontent.com/hermitdave/FrequencyWords/master/content/2016/ro/ro_50k.txt | head -20
(bez-s
tego samego błędu).Inna możliwość, jeśli używasz opcji
-o
(plik wyjściowy) - katalog docelowy nie istnieje.na przykład. jeśli masz
-o /tmp/download/abc.txt
i / tmp / download nie istnieje.Dlatego upewnij się, że wszystkie wymagane katalogi zostały utworzone / istnieją wcześniej, użyj
--create-dirs
opcji, a także -o
jeśli to konieczneźródło
Więc to był problem z kodowaniem. Iconv rozwiązuje problem
źródło
Możesz to zrobić zamiast używać
-o
opcji:curl [url] > [file]
źródło
Miałem ten sam błąd, ale z innego powodu. W moim przypadku miałem partycję (tmpfs) z tylko 1 GB miejsca i pobierałem duży plik, który w końcu zapełnił całą pamięć na tej partycji i dostałem ten sam błąd co ty.
źródło
W moim przypadku na serwerze zabrakło miejsca na dysku.
Sprawdź to za pomocą
df -k .
Zostałem ostrzeżony o braku miejsca na dysku, gdy
tac
dwukrotnie próbowałem przepuścić , jak opisano w jednej z pozostałych odpowiedzi: https://stackoverflow.com/a/28879552/336694 . Pokazał mi komunikat o błędziewrite error: No space left on device
.źródło
docker system prune
Błąd został napotkany podczas wykonywania polecenia jako root
curl -L https://packagecloud.io/varnishcache/varnish5/gpgkey | apt-key add -
rozwiązaniem jest działanie
apt-key add
bez uprawnień administratoraźródło
Jeśli próbujesz czegoś podobnego
source <( curl -sS $url )
i otrzymujesz(23) Failed writing body
błąd, dzieje się tak, ponieważ zastępowanie procesu nie działabash 3.2
(ustawienie domyślne dla macOS).Zamiast tego możesz skorzystać z tego obejścia.
źródło
Dla mnie była to kwestia pozwolenia. Uruchomienie Dockera jest wywoływane z profilem użytkownika, ale root jest użytkownikiem wewnątrz kontenera. Rozwiązaniem było umożliwienie curl zapisu do / tmp, ponieważ ma on uprawnienia do zapisu dla wszystkich użytkowników, a nie tylko dla roota.
Użyłem opcji -o.
-o / tmp / file_to_download
źródło
W Bash i zsh (i być może w innych powłokach) możesz użyć podstawiania procesów ( Bash / zsh ), aby utworzyć plik w locie, a następnie użyć go jako danych wejściowych do następnego procesu w łańcuchu potoków.
Na przykład próbowałem przeanalizować dane wyjściowe JSON z cURL przy użyciu
jq
iless
, ale otrzymywałemFailed writing body
błąd.Kiedy przepisałem go za pomocą zastępowania procesów, zadziałało!
Uwaga:
jq
używa drugiego argumentu do określenia pliku wejściowegoBonus: Jeśli używasz
jq
jak ja i chce zachować pokolorowane wyjście wless
, należy użyć następującego wiersza polecenia zamiast:(Dziękuję Kowaru za wyjaśnienie, dlaczego
Failed writing body
tak się dzieje. Jednak ich rozwiązanie polegające natac
dwukrotnym użyciu nie zadziałało dla mnie. Chciałem również znaleźć rozwiązanie, które będzie lepiej skalować dla dużych plików i próbuję uniknąć innych problemów odnotowanych jako komentarze do tej odpowiedzi.)źródło