Страницы

Поиск по вопросам

Показаны сообщения с ярлыком pipes. Показать все сообщения
Показаны сообщения с ярлыком pipes. Показать все сообщения

понедельник, 24 февраля 2020 г.

как узнать что открытый pipe был удален?

#c #pipes #fifo


Допустим у нас есть именованный канал. Мы его открыли на чтение и читаем читаем читаем.
Но вдруг писатель удалил этот pipe(ошибка или ещё что-то). Как правильно проверить
что pipe больше не существует.



Корректно ли проверять результат read и если он равен 0, то считать что канал отвалился?
Если нет данных, то read будет долго ждать своего часа.
Но read возвращает ноль если достигнут конец файла (а pipe по сути тот же файл, ну
почти. поправьте если я ошибаюсь.) и это вовсе не значит что файл удален (для пайпов
не уверена, поэтому и спрашиваю).
Подскажите как правильно проверить, что pipe закрыт(удален).
    


Ответы

Ответ 1



При использованиие функции read() Если в канале нет данных будет возврашен 0 а если произошла ошибка будет возврашено значение -1 и в переемной errno установлен код ошибки. Ну тут еще важен момет как открыт канал. В блокируещем или не блокируещем режими. Но всеравно функция чтения не сможет указать что файл был удален. Поэтому если в программе есть вероятность что канал будет удален. То перед чтением из канала нужно воспользоваться функцией stat() она укажет существует такой файл или нет. И в этом случаи нужно открывать файл в неблокируешем режиме fd = open("test.pipe",O_RDONLY|O_NONBLOCK);

Ответ 2



До тех пор пока хотя бы один процесс держит pipe открытой, объект не будет удалён. То есть даже если FIFO файл удалён (согласно stat()), read() всё равно может вернуть данные из уже открытой pipe. Если нет процессов, в которых pipe открыта для записи, то read() вернёт 0 (чтобы отметить EOF), если больше нет данных в буфере pipe. Если ваша задача прочитать данные из FIFO, то открывайте (open()) и читайте (read()), не забывая обрабатывать ошибки. Никакие дополнительные вызовы не нужны. Вот пример, который показывает, что можно данные писать и читать даже если stat() говорит что нет файла (исполняемый псевдо-код): #!/usr/bin/env python from os import * mkfifo('fifo') # create named pipe r, w = pipe() # "communication tube" between the parent and the child if fork(): # parent process (the reader) close(r) # close the unused end of the pipe fd = open('fifo', O_RDONLY) # open for reading write(1, read(fd, 512)) # read some remove('fifo') # delete fifo write(w, b'\0') # tell the child, the parent removed fifo close(w) # nothing more to say wait() # wait until the writer exits write(2, b'read some more\n') write(1, read(fd, 512)) # read some more if not read(fd, 512): write(1, b'EOF') # read() returns nothing else: # child: writer process close(w) # close the unused end of the pipe fd = open('fifo', O_WRONLY) # open for writing write(fd, b'data\n') read(r, 512) # wait until the parent removes fifo close(r) # won't listen no more try: # make sure fifo is gone stat('fifo') except IOError: pass else: assert 0, "shouldn't happen" write(fd, b'more data\n') # write after fifo is removed _exit(0) Если вас интересует узнать когда имя файла (fifo) было удалено (а не возможность чтения данных), то чтобы stat() не вызывать постоянно, можно сервисы такие как предложенный @avp inotify для Linux использовать (на разных системах—разные интерфейсы, но сама возможность на многих распространённых системах есть).

воскресенье, 22 декабря 2019 г.

Как перенаправить вывод функции в pipe?

#linux #shell #pipes


Здесь pipe работает нормально:

dpkg -l | grep nginx

ii  nginx                                1.4.6-1ubuntu3.2                       
all          small, powerful, scalable web/proxy server
ii  nginx-common                         1.4.6-1ubuntu3.2                       
all          small, powerful, scalable web/proxy server - common files
ii  nginx-full                           1.4.6-1ubuntu3.2                       
amd64        nginx web/proxy server (standard version)


А вот так вывод первого выражения пролетает мимо grep:

nginx -V | grep echo

nginx version: nginx/1.4.6 (Ubuntu)
built by gcc 4.8.2 (Ubuntu 4.8.2-19ubuntu1)
TLS SNI support enabled
configure arguments: ...


(дальше идет список аргументов, в котором тоже нет слова "echo").

Как можно увидеть, 4 строки печатаются прямо в stdout и не попадают в pipe. А можно
ли их всё-таки поймать и обработать? Как?
    


Ответы

Ответ 1



процесс может читать информацию как минимум из одного потока, условно называемого stdin (поток номер 0), и выводить информацию как минимум в два потока, условно называемые stdout (поток номер 1) и stderr (поток номер 2). оператор shell-а | ("pipe", "вертикальная черта"), употреблённый между двумя командами (которые запускают процессы), связывает stdout первого процесса с stdin второго процесса. и второй процесс может этот поток информации как-то обработать. но та информация, которую первый процесс отправляет в stderr, «проходит мимо» оператора |, а значит, и «мимо» второго процесса. с помощью оператора 2>&1, вставленного до или после команды, можно «изменить направление» потока stderr (поток номер 2) процесса, созданного этой командой, так, что выводимая процессом в этот поток информация будет «попадать» в поток stdout (поток номер 1). поток stderr «как бы исчезнет», а в потоке stdout будет (вперемешку) присутствовать вся информация, выданная в оба этих потока. таким образом оператору | (а значит, и второму процессу) попадёт и содержимое stdout, и содержимое stderr первого процесса. т.е., возвращаясь к вопросу, можно переписать команду так: $ /usr/sbin/nginx -V 2>&1 | grep echo или так: $ 2>&1 /usr/sbin/nginx -V | grep echo у реализации shell-а под названием bash (возможно, и у других реализаций) есть не описанная в стандарте posix сокращённая форма записи этих двух операторов. вместо 2>&1 | можно писать |&: $ /usr/sbin/nginx -V |& grep echo

понедельник, 8 июля 2019 г.

Ubuntu/CentOS pipe к процессу по PID

Доброго времени суток. Требуется кидать данные процессу через пайп, по PID. Не понятно, как это сделать. Ну то есть. Процесс запущен. Известен его PID. надо изредка сделать что-то вроде:
cat something | PID:XXXX


Ответ

что-то вроде:
$ cat something | PID:XXXX
вероятно, имеется в виду запись в stdin процесса (если, конечно, процесс готов к этому):
$ cat something > /proc/XXXX/fd/0

вторник, 13 ноября 2018 г.

Как перенаправить вывод функции в pipe?

Здесь pipe работает нормально:
dpkg -l | grep nginx
ii nginx 1.4.6-1ubuntu3.2 all small, powerful, scalable web/proxy server ii nginx-common 1.4.6-1ubuntu3.2 all small, powerful, scalable web/proxy server - common files ii nginx-full 1.4.6-1ubuntu3.2 amd64 nginx web/proxy server (standard version)
А вот так вывод первого выражения пролетает мимо grep:
nginx -V | grep echo
nginx version: nginx/1.4.6 (Ubuntu) built by gcc 4.8.2 (Ubuntu 4.8.2-19ubuntu1) TLS SNI support enabled configure arguments: ...
(дальше идет список аргументов, в котором тоже нет слова "echo").
Как можно увидеть, 4 строки печатаются прямо в stdout и не попадают в pipe. А можно ли их всё-таки поймать и обработать? Как?


Ответ

процесс может читать информацию как минимум из одного потока, условно называемого stdin (поток номер 0), и выводить информацию как минимум в два потока, условно называемые stdout (поток номер 1) и stderr (поток номер 2).
оператор shell-а | ("pipe", "вертикальная черта"), употреблённый между двумя командами (которые запускают процессы), связывает stdout первого процесса с stdin второго процесса. и второй процесс может этот поток информации как-то обработать.
но та информация, которую первый процесс отправляет в stderr, «проходит мимо» оператора |, а значит, и «мимо» второго процесса.

с помощью оператора 2>&1, вставленного до или после команды, можно «изменить направление» потока stderr (поток номер 2) процесса, созданного этой командой, так, что выводимая процессом в этот поток информация будет «попадать» в поток stdout (поток номер 1). поток stderr «как бы исчезнет», а в потоке stdout будет (вперемешку) присутствовать вся информация, выданная в оба этих потока. таким образом оператору | (а значит, и второму процессу) попадёт и содержимое stdout, и содержимое stderr первого процесса.

т.е., возвращаясь к вопросу, можно переписать команду так:
$ /usr/sbin/nginx -V 2>&1 | grep echo
или так:
$ 2>&1 /usr/sbin/nginx -V | grep echo

у реализации shell-а под названием bash (возможно, и у других реализаций) есть не описанная в стандарте posix сокращённая форма записи этих двух операторов. вместо 2>&1 | можно писать |&
$ /usr/sbin/nginx -V |& grep echo