Cela fonctionne bien comme un seul outil:
curl "someURL"
curl -o - "someURL"
mais cela ne fonctionne pas dans un pipeline:
curl "someURL" | tr -d '\n'
curl -o - "someURL" | tr -d '\n'
il renvoie:
(23) Failed writing body
Quel est le problème avec la canalisation de la sortie cURL? Comment mettre en mémoire tampon toute la sortie cURL puis la gérer?
curl 'http://www.multitran.ru/c/m.exe?CL=1&s=hello&l1=1' | tr -d '\n'
iconv -f ...
Réponses:
Cela se produit quand un programme canalisé (par exemple grep) ferme le tube de lecture avant que le programme précédent n'ait fini d'écrire la page entière.
Dans
curl "url" | grep -qs foo
, dès que grep a ce qu'il veut, il fermera le flux de lecture de curl. cURL ne s'y attend pas et émet l'erreur «Échec de l'écriture du corps».Une solution de contournement consiste à diriger le flux via un programme intermédiaire qui lit toujours la page entière avant de l'envoyer au programme suivant.
Par exemple
tac
est un simple programme Unix qui lit toute la page d'entrée et inverse l'ordre des lignes (donc nous l'exécutons deux fois). Comme il doit lire toute l'entrée pour trouver la dernière ligne, il ne sortira rien vers grep tant que cURL ne sera pas terminé. Grep fermera toujours le flux de lecture lorsqu'il aura ce qu'il recherche, mais cela n'affectera que tac, qui n'émet pas d'erreur.la source
cat
une seule fois? Résout le problème pour moi, au moins.-s
pour faire taire tous les messages d'erreur (et la progression) si vous n'en avez pas besoin.tac|tac
modifie l'entrée si l'entrée ne se termine pas par un saut de ligne, ou par exempleprintf a\\nb\\nc|tac|tac
imprimea\ncb
où\n
est un saut de ligne. Vous pouvez utiliser à lasponge /dev/stdout
place. Une autre option estprintf %s\\n "$(cat)"
, mais lorsque l'entrée contient des octets nuls dans des shells autres que Zsh, cela ignore les octets nuls ou arrête la lecture après le premier octet nul.tac
commande sur macOSPour l'exhaustivité et les recherches futures:
C'est une question de comment cURL gère le tampon, le tampon désactive le flux de sortie avec l'option -N.
Exemple:
curl -s -N "URL" | grep -q Welcome
la source
curl -s https://raw.githubusercontent.com/hermitdave/FrequencyWords/master/content/2016/ro/ro_50k.txt | head -20
(sans-s
que j'obtienne la même erreur).Une autre possibilité, si vous utilisez le
-o
option (fichier de sortie) - le répertoire de destination n'existe pas.par exemple. si vous avez
-o /tmp/download/abc.txt
et / tmp / download n'existe pas.Par conséquent, assurez-vous que tous les répertoires requis sont créés / existent au préalable, utilisez l'
--create-dirs
option ainsi que -o
si nécessairela source
C'était donc un problème d'encodage. Iconv résout le problème
la source
Vous pouvez le faire au lieu d'utiliser l'
-o
option:curl [url] > [file]
la source
J'ai eu la même erreur mais pour une raison différente. Dans mon cas, j'avais une partition (tmpfs) avec seulement 1 Go d'espace et je téléchargeais un gros fichier qui a finalement rempli toute la mémoire de cette partition et j'ai eu la même erreur que vous.
la source
Le serveur a manqué d'espace disque, dans mon cas.
Vérifiez-le avec
df -k .
J'ai été alerté du manque d'espace disque lorsque j'ai essayé de passer
tac
deux fois, comme décrit dans l'une des autres réponses: https://stackoverflow.com/a/28879552/336694 . Il m'a montré le message d'erreurwrite error: No space left on device
.la source
docker system prune
Le bogue est rencontré lors de l'exécution de la commande en tant que root
curl -L https://packagecloud.io/varnishcache/varnish5/gpgkey | apt-key add -
la solution est de fonctionner en
apt-key add
tant que non rootla source
Si vous essayez quelque chose de similaire
source <( curl -sS $url )
et que vous obtenez l'(23) Failed writing body
erreur, c'est parce que l'approvisionnement d'une substitution de processus ne fonctionne pas dansbash 3.2
(par défaut pour macOS).Au lieu de cela, vous pouvez utiliser cette solution de contournement.
la source
Pour moi, c'était une question de permission. L'exécution de Docker est appelée avec un profil utilisateur mais root est l'utilisateur à l'intérieur du conteneur. La solution était de faire en sorte que curl écrive dans / tmp puisque cela a l'autorisation d'écriture pour tous les utilisateurs, pas seulement root.
J'ai utilisé l'option -o.
-o / tmp / file_to_download
la source
Dans Bash et zsh (et peut-être dans d'autres shells), vous pouvez utiliser la substitution de processus ( Bash / zsh ) pour créer un fichier à la volée, puis l'utiliser comme entrée du processus suivant dans la chaîne de pipeline.
Par exemple, j'essayais d'analyser la sortie JSON de cURL en utilisant
jq
etless
, mais j'obtenais l'Failed writing body
erreur.Quand je l'ai réécrit en utilisant la substitution de processus, cela a fonctionné!
Remarque:
jq
utilise son 2ème argument pour spécifier un fichier d'entréeBonus: Si vous utilisez
jq
comme moi et que vous voulez garder la sortie colorisée enless
, utilisez la ligne de commande suivante à la place:(Merci à Kowaru pour leur explication sur les raisons de cet incident
Failed writing body
. Cependant, leur solution consistant à utilisertac
deux fois n'a pas fonctionné pour moi. Je voulais également trouver une solution qui serait mieux adaptée aux fichiers volumineux et essaie d'éviter les autres problèmes mentionnés dans les commentaires. à cette réponse.)la source