Прочитать все в буфере канала, не дожидаясь

Они не то же самое с точки зрения Unix (или, скорее, с точки зрения оболочки).

https_proxy=http://myproxy.com/ aws [aws-param]

явно определяет переменную https_proxy для команды aws ; оболочка копирует его в среду процесса aws , и aws видит его.

https_proxy=http://myproxy.com/ 
aws [aws-param]

определяет переменную в среде оболочки, но поскольку она не экспортируется, оболочка не копирует ее в среду процесса aws .

Эквивалент (с точки зрения aws ) на самом деле

https_proxy=http://myproxy.com/ 
export https_proxy
aws [aws-param]

См. Что это за синтаксис Bash: someVariable = someValue command для получения дополнительных сведений (и ссылки на документация).

5
12.12.2016, 01:20
2 ответа

Если вы выполните один системный вызов read () в канале, он зависнет, если в канале ничего нет, но в противном случае немедленно вернуться с тем, что там.

Теперь, для , что там , с Linux 4.4 на моей многоядерной системе amd64 по крайней мере (YMMV с другими системами или другими версиями Linux), если один или несколько процессов в настоящее время выполняют write () (или другой системный вызов записи) на другом конце, возможно, больше, чем емкость канала (64 КБ по умолчанию в текущих версиях Linux), планировщик будет переключаться между этими процессами и одно чтение из канала несколько раз во время этого системного вызова read () и read () может вернуть гораздо больше, чем емкость канала.

Команда dd - это интерфейс командной строки для системного вызова read .

dd bs=1G count=1

(обратите внимание, что не все реализации dd поддерживают эти суффиксы G ) делает ли один read () размером 1 ГБ со стандартного ввода (за которым следует один ] write () на стандартный вывод)

С помощью GNU dd вы можете избежать блокировки на пустом канале с помощью iflag = nonblock . Это устанавливает канал в неблокирующий режим, но учтите, что впоследствии он оставляет его неблокирующим, что может быть нежелательно.Например:

(date; sleep 2; date) |
  (sleep 1
   dd bs=1G count=1 status=none iflag=nonblock
   wc -c)

give:

Mon 23 Jan 22:11:30 GMT 2017
wc: 'standard input': Resource temporarily unavailable
0

Поскольку канал также становится неблокирующим для wc .

И как было сказано ранее, с неблокируемым или без него, вы можете в конечном итоге прочитать больше, чем может поместиться в конвейер:

$ (cat /dev/zero & cat /dev/zero & cat /dev/zero) |
     (sleep 1; dd bs=1G count=1) | wc -c
0+1 records in
0+1 records out
545914880 bytes (546 MB, 521 MiB) copied, 0.48251 s, 1.1 GB/s
545914880

(и вы будете получать разные числа от одного запуска к другому ).

Другой подход к системам, которые его поддерживают, заключается в использовании FIONREAD ioctl () для запроса объема данных в конвейере перед выполнением чтения.

perl -e '
  require "sys/ioctl.ph";
  ioctl(STDIN, &FIONREAD, $n) or die "ioctl: $!\n";
  $n = unpack "L", $n;
  if ($n) {
    sysread STDIN, $text, $n or die "read: $!\n";
    print $text
  }'

Обратите внимание, что, поскольку это выполняется в два этапа, если другой процесс одновременно читает из конвейера, он все равно может закончить блокировку, если этот другой процесс опустошает конвейер между ioctl () , а читается как () .

3
27.01.2020, 20:42

Вы можете использовать простую программу C для чтения из stdin , записи в stdout и выхода, фактически не дожидаясь EOF , и использовать его как промежуточное звено в трубопроводной цепи.

Вот простой пример:

main.c

#include <stdio.h>
#include <unistd.h>

#define BUFFER_SIZE 1024

int main(int argc, char **argv){
    char buffer[BUFFER_SIZE];

    ssize_t read_size;

    //Read up to BUFFER_SIZE bytes of what's currently at the stdin
    read_size = read(STDIN_FILENO, buffer, BUFFER_SIZE);
    if(read_size > 0){
        write(STDOUT_FILENO, buffer, read_size);
    }

    return 0;
}

Скомпилируйте эту программу, используя gcc -o test main.c .

Затем, если вы запустите {echo a; спать 2 секунды; эхо б; } | {спит 1 сек; ./тестовое задание; } | {./mycommand; } , mycommand получит только a , поскольку это был единственный символ в stdin при чтении ./ test от него.

Чтобы проверить это, вы можете запустить {echo a; спать 2 секунды; эхо б; } | {спит 1 сек; ./тестовое задание; } | cat , при котором на экране будет отображаться только a .

0
27.01.2020, 20:42

Теги

Похожие вопросы