Он работает как единый инструмент:
curl "someURL"
curl -o - "someURL"
но он не работает в конвейере:
curl "someURL" | tr -d '\n'
curl -o - "someURL" | tr -d '\n'
он возвращает:
(23) Failed writing body
В чем проблема с конвейером вывода cURL? Как буферизовать весь вывод cURL, а затем обработать его?
curl 'http://www.multitran.ru/c/m.exe?CL=1&s=hello&l1=1' | tr -d '\n'
iconv -f ...
Ответы:
Это происходит, когда программа с конвейером (например, grep) закрывает конвейер чтения до того, как предыдущая программа завершила запись всей страницы.
In
curl "url" | grep -qs foo
, как только grep получит то, что хочет, он закроет поток чтения из curl. cURL этого не ожидает и выдает ошибку «Ошибка записи тела».Обходной путь - направить поток через промежуточную программу, которая всегда считывает всю страницу, прежде чем передать ее следующей программе.
Например
curl "url" | tac | tac | grep -qs foo
tac
- это простая программа Unix, которая считывает всю страницу ввода и меняет порядок строк (поэтому мы запускаем ее дважды). Поскольку он должен прочитать весь ввод, чтобы найти последнюю строку, он не будет ничего выводить в grep до завершения cURL. Grep все равно закроет поток чтения, когда получит то, что ищет, но повлияет только на tac, который не выдаст ошибку.источник
cat
один раз? По крайней мере, решает проблему для меня.-s
чтобы заглушить все сообщения об ошибках (и прогресс), если они вам не нужны.tac|tac
изменяет ввод, если ввод не заканчивается переводом строки, или, например,printf a\\nb\\nc|tac|tac
печатает,a\ncb
где\n
это перевод строки.sponge /dev/stdout
Вместо этого можно использовать . Другой вариантprintf %s\\n "$(cat)"
, но когда вход содержит нулевые байты в оболочках, отличных от Zsh, он либо пропускает нулевые байты, либо прекращает чтение после первого нулевого байта.tac
в macOS нет командыДля полноты и будущих поисков:
Это вопрос того, как cURL управляет буфером, буфер отключает выходной поток с параметром -N.
Пример:
curl -s -N "URL" | grep -q Welcome
источник
curl -s https://raw.githubusercontent.com/hermitdave/FrequencyWords/master/content/2016/ro/ro_50k.txt | head -20
(без-s
той же ошибки).Другая возможность, если использовать
-o
опция (выходной файл) - целевой каталог не существует.например. если у вас есть
-o /tmp/download/abc.txt
и / tmp / download не существует.Следовательно, убедитесь, что все необходимые каталоги созданы / существуют заранее, используйте
--create-dirs
параметр, а также -o
при необходимостиисточник
Вы можете сделать это вместо использования
-o
опции:curl [url] > [file]
источник
Так что это была проблема с кодировкой. Iconv решает проблему
curl 'http://www.multitran.ru/c/m.exe?CL=1&s=hello&l1=1' | iconv -f windows-1251 | tr -dc '[:print:]' | ...
источник
У меня была такая же ошибка, но по другой причине. В моем случае у меня был раздел (tmpfs) с объемом всего 1 ГБ, и я загружал большой файл, который, наконец, заполнил всю память на этом разделе, и я получил ту же ошибку, что и вы.
источник
В моем случае на сервере закончилось место на диске.
Проверьте это с помощью
df -k .
Я был предупрежден о нехватке места на диске, когда
tac
дважды пытался выполнить подключение по конвейеру , как описано в одном из других ответов: https://stackoverflow.com/a/28879552/336694 . Он показал мне сообщение об ошибкеwrite error: No space left on device
.источник
docker system prune
Ошибка возникает при запуске команды от имени пользователя root
curl -L https://packagecloud.io/varnishcache/varnish5/gpgkey | apt-key add -
решение - запустить
apt-key add
как не rootисточник
Для меня это была проблема с разрешением. Запуск Docker вызывается с профилем пользователя, но root - это пользователь внутри контейнера. Решением было заставить curl записывать в / tmp, поскольку у него есть права на запись для всех пользователей, а не только для root.
Я использовал параметр -o.
-o / tmp / file_to_download
источник
Если вы пытаетесь сделать что-то подобное, например
source <( curl -sS $url )
и получаете сообщение об(23) Failed writing body
ошибке, это потому, что поиск замены процесса не работаетbash 3.2
(по умолчанию для macOS).Вместо этого вы можете использовать этот обходной путь.
source /dev/stdin <<<"$( curl -sS $url )"
источник
В Bash и zsh (и, возможно, в других оболочках) вы можете использовать замену процесса ( Bash / zsh ) для создания файла на лету, а затем использовать его в качестве входных данных для следующего процесса в цепочке конвейера.
Например, я пытался разобрать вывод JSON из cURL с помощью
jq
иless
, но получалFailed writing body
ошибку.# Note: this does NOT work curl https://gitlab.com/api/v4/projects/ | jq | less
Когда я его переписал с подстановкой процесса, все заработало!
# this works! jq "" <(curl https://gitlab.com/api/v4/projects/) | less
Примечание:
jq
использует второй аргумент для указания входного файлаБонус: Если вы используете ,
jq
как я и хотите , чтобы держать Раскрашенную выход вless
, используйте следующую командную строку вместо того, чтобы :jq -C "" <(curl https://gitlab.com/api/v4/projects/) | less -r
(Спасибо Kowaru за их объяснение, почему
Failed writing body
это произошло. Однако их решение использоватьtac
дважды не сработало для меня. Я также хотел найти решение, которое лучше масштабировалось бы для больших файлов, и пытается избежать других проблем, отмеченных как комментарии на этот ответ.)источник