- Linux pipes tips & tricks
- Pipe — что это?
- Логика
- Простой дебаг
- Исходный код, уровень 1, shell
- Исходный код, уровень 2, ядро
- Tips & trics
- lnguin
- Timeouts
- Pipe timeouts
- Global timeout
- Endpoint-specific timeout
- What happens when the timeout is reached?
- HTTP Request timeouts
- HTTP Read Timeout
- HTTP Write Timeout
- HTTP Idle Timeout
- HTTP Read Header Timeout
- Time units
- Unresolved issues?
- memset’s blog
- Timeout on Named Pipes
- ИТ База знаний
- Полезно
- Навигация
- Серверные решения
- Телефония
- Корпоративные сети
- Использование timeout в Linux с примерами
- Как взять timeout — об использовании команды
- Базовый синтаксис
- Сообщение с космосом или отправка определенного сигнала исполняемому процессу
- Как убить процесс, если он завис
- Сохраняем статус
- Запуск команды явно, а не за кулисами
- Заключение
Linux pipes tips & tricks
Pipe — что это?
Pipe (конвеер) – это однонаправленный канал межпроцессного взаимодействия. Термин был придуман Дугласом Макилроем для командной оболочки Unix и назван по аналогии с трубопроводом. Конвейеры чаще всего используются в shell-скриптах для связи нескольких команд путем перенаправления вывода одной команды (stdout) на вход (stdin) последующей, используя символ конвеера ‘|’:
grep выполняет регистронезависимый поиск строки “error” в файле log, но результат поиска не выводится на экран, а перенаправляется на вход (stdin) команды wc, которая в свою очередь выполняет подсчет количества строк.
Логика
Конвеер обеспечивает асинхронное выполнение команд с использованием буферизации ввода/вывода. Таким образом все команды в конвейере работают параллельно, каждая в своем процессе.
Размер буфера начиная с ядра версии 2.6.11 составляет 65536 байт (64Кб) и равен странице памяти в более старых ядрах. При попытке чтения из пустого буфера процесс чтения блокируется до появления данных. Аналогично при попытке записи в заполненный буфер процесс записи будет заблокирован до освобождения необходимого места.
Важно, что несмотря на то, что конвейер оперирует файловыми дескрипторами потоков ввода/вывода, все операции выполняются в памяти, без нагрузки на диск.
Вся информация, приведенная ниже, касается оболочки bash-4.2 и ядра 3.10.10.
Простой дебаг
Исходный код, уровень 1, shell
Т. к. лучшая документация — исходный код, обратимся к нему. Bash использует Yacc для парсинга входных команд и возвращает ‘command_connect()’, когда встречает символ ‘|’.
parse.y:
Также здесь мы видим обработку пары символов ‘|&’, что эквивалентно перенаправлению как stdout, так и stderr в конвеер. Далее обратимся к command_connect():make_cmd.c:
где connector это символ ‘|’ как int. При выполнении последовательности команд (связанных через ‘&’, ‘|’, ‘;’, и т. д.) вызывается execute_connection():execute_cmd.c:
PIPE_IN и PIPE_OUT — файловые дескрипторы, содержащие информацию о входном и выходном потоках. Они могут принимать значение NO_PIPE, которое означает, что I/O является stdin/stdout.
execute_pipeline() довольно объемная функция, имплементация которой содержится в execute_cmd.c. Мы рассмотрим наиболее интересные для нас части.
execute_cmd.c:
Таким образом, bash обрабатывает символ конвейера путем системного вызова pipe() для каждого встретившегося символа ‘|’ и выполняет каждую команду в отдельном процессе с использованием соответствующих файловых дескрипторов в качестве входного и выходного потоков.
Исходный код, уровень 2, ядро
Обратимся к коду ядра и посмотрим на имплементацию функции pipe(). В статье рассматривается ядро версии 3.10.10 stable.
fs/pipe.c (пропущены незначительные для данной статьи участки кода):
Если вы обратили внимание, в коде идет проверка на флаг O_NONBLOCK. Его можно выставить используя операцию F_SETFL в fcntl. Он отвечает за переход в режим без блокировки I/O потоков в конвеере. В этом режиме вместо блокировки процесс чтения/записи в поток будет завершаться с errno кодом EAGAIN.
Максимальный размер блока данных, который будет записан в конвейер, равен одной странице памяти (4Кб) для архитектуры arm:
arch/arm/include/asm/limits.h:
Для ядер >= 2.6.35 можно изменить размер буфера конвейера:
Максимально допустимый размер буфера, как мы видели выше, указан в файле /proc/sys/fs/pipe-max-size.
Tips & trics
В примерах ниже будем выполнять ls на существующую директорию Documents и два несуществующих файла: ./non-existent_file и. /other_non-existent_file.
Перенаправление и stdout, и stderr в pipe
или же можно использовать комбинацию символов ‘|&’ (о ней можно узнать как из документации к оболочке (man bash), так и из исходников выше, где мы разбирали Yacc парсер bash):
Перенаправление _только_ stderr в pipe
Shoot yourself in the foot
Важно соблюдать порядок перенаправления stdout и stderr. Например, комбинация ‘>/dev/null 2>&1′ перенаправит и stdout, и stderr в /dev/null.
Получение корректного кода завершения конвейра
По умолчанию, код завершения конвейера — код завершения последней команды в конвеере. Например, возьмем исходную команду, которая завершается с ненулевым кодом:
И поместим ее в pipe:
Теперь код завершения конвейера — это код завершения команды wc, т.е. 0.
Обычно же нам нужно знать, если в процессе выполнения конвейера произошла ошибка. Для этого следует выставить опцию pipefail, которая указывает оболочке, что код завершения конвейера будет совпадать с первым ненулевым кодом завершения одной из команд конвейера или же нулю в случае, если все команды завершились корректно:
Shoot yourself in the foot
Следует иметь в виду “безобидные” команды, которые могут вернуть не ноль. Это касается не только работы с конвейерами. Например, рассмотрим пример с grep:
Здесь мы печатаем все найденные строки, приписав ‘new_’ в начале каждой строки, либо не печатаем ничего, если ни одной строки нужного формата не нашлось. Проблема в том, что grep завершается с кодом 1, если не было найдено ни одного совпадения, поэтому если в нашем скрипте выставлена опция pipefail, этот пример завершится с кодом 1:
В больших скриптах со сложными конструкциями и длинными конвеерами можно упустить этот момент из виду, что может привести к некорректным результатам.
Источник
lnguin
/* This example program demonstrates how to read and write a raw data in a serial port.
Reading the serial port is handled with timeout. */
#include // standard input / output functions
#include // string function definitions
#include // UNIX standard function definitions
#include // File control definitions
#include // Error number definitions
#include // POSIX terminal control definitionss
#include // time calls
int fd;
int read_port_flag = 0;
struct serial_data
<
unsigned char len; /* data length */
char data[32] __attribute__((aligned(32)));
>;
int openPort(const char* port)
<
fd = open(port, O_RDWR | O_NOCTTY);
if(fd == -1)
<
return (-1);
>
else
<
struct termios port_settings;
bzero(&port_settings, sizeof(port_settings));
/* enable the receiver and set local mode */
port_settings.c_cflag |= (CLOCAL | CREAD);
/* set no parity, stop bits, data bits */
port_settings.c_cflag &=
CSTOPB;
/* set character size as 8 bits */
port_settings.c_cflag &=
CSIZE;
port_settings.c_cflag |= CS8;
/* Raw input mode, sends the raw and unprocessed data ( send as it is) */
port_settings.c_lflag &=
(ICANON | ECHO | ISIG);
/* Raw output mode, sends the raw and unprocessed data ( send as it is).
* If it is in canonical mode and sending new line char then CR
* will be added as prefix and send as CR LF
*/
port_settings.c_oflag =
int send_port(struct serial_data *send_data)
<
if ((write(fd, send_data->data, send_data->len)) != send_data->len)
<
return (-1);
>
void set_port_read_min_size(int min_size)
<
struct termios settings;
/* set the minimimum no. of chracters to read in each
* read call.
*/
settings.c_cc[VMIN] = min_size;
/* set “read timeout between characters” as 100 ms.
* read returns either when the specified number of chars
* are received or the timout occurs */
settings.c_cc[VTIME] = 1; /* 1 * .1s */
if (tcsetattr (fd, TCSANOW, &settings))
<
/* handle error */
>
>
void read_port()
<
struct serial_data recv_data;
int recvbytes = 0;
int maxfd = fd + 1;
int index = 0;
/* set the timeout as 1 sec for each read */
struct timeval timeout = <1, 0>;
fd_set readSet;
/* set the “mininum characters to read” */
set_port_read_min_size(16);
read_port_flag = 1;
/* select() – returns 0 on timeout and -1 on error condtion */
if (!read_port_flag)
<
return;
>
>
Источник
Timeouts
Being KrakenD an API Gateway that talks to other services, being able to control the waiting times for different aspects is crucial. KrakenD will allow you to fine-tune these settings.
The timeouts can apply to:
- The duration of the whole pipe (from user request to user response)
- The HTTP request related timeouts
Additionally, you can control the number of maximum IDLE connections.
Pipe timeouts
Global timeout
The timeout key in the krakend.json at the root level is used in the first place to apply a default timeout for the whole duration of the pipe (and not only the connection to the backends). The timeout takes into account all the time involved between the request, the fetching of the data, manipulation and any other middleware. You can see it is an end-user timeout.
Endpoint-specific timeout
Even the timeout value in the root level sets a default timeout for all the endpoints, you can override it later on any specific endpoints.
To do so, just place it inside the desired endpoint:
The example above will use 1 second timeout for the /splash endpoint and 2000 milliseconds for all the other endpoints.
What happens when the timeout is reached?
When the timeout for a pipe is reached, the request is canceled and the user receives an HTTP status code 500 Internal Server Error
HTTP Request timeouts
In addition to the timeouts for the whole pipe, you can configure the specific HTTP layer timeouts. All the settings below work just like the pipeline timeouts. If you place this values in an endpoint, they will override the global setting.
HTTP Read Timeout
Maximum duration for reading the entire HTTP request, including the body.
This timeout does not let Handlers make per-request decisions on each request body’s acceptable deadline.
HTTP Write Timeout
Maximum duration before timing out writes of the response.
It is reset whenever a new request header is read. Like HTTP Read Timeout, it does not let Handlers make decisions on a per-request basis.
HTTP Idle Timeout
Maximum amount of time to wait for the next request when keep-alives are enabled.
If IdleTimeout is zero, the value of ReadTimeout is used. If both are zero, ReadHeaderTimeout is used.
HTTP Read Header Timeout
Amount of time allowed to read request headers.
The connection’s read deadline is reset after reading the headers and the Handler can decide what is considered too slow for the body.
Time units
The time units you can use to specify timeouts are integers (not floats) using any of these units:
- Nanoseconds: ns
- Microseconds: us , or µs
- Milliseconds: ms
- Seconds: s
It is also available although you should never use them:
Examples of equivalent timeouts in different units are:
Unresolved issues?
The documentation is only a piece of the help you can get! Whether you are looking for Open Source or Enterprise support, see more support channels that can help you.
The Ultra-High performance Open Source API Gateway with middlewares
KrakenD helps application developers release features quickly by eliminating all the complexities of SOA architectures while offering a unique performance.
Источник
memset’s blog
Timeout on Named Pipes
Hi. In this post, I will show you how make a timeouted namedpipe with the WIN32 API: the msdn’s manual doesn’t explain how to do it.
The named pipes are an IPC’s method by which we can send data to an other process (like a son process).
This solution is useful when for example we have a parent process A that create a son process B. We want send data from A to B through the namedpipe. A has to create the namedpipe and connect to it. When A connects to the pipe, it waits until B opens the pipe allowing data transfer.
But, if B die before opening the pipe, then A will wait indefinitely.
To resolve this problem, we need to set a maximum timeout to wait at the end of which we are sure that there was some problem.
So, you have to create your namedpipe (msdn man) that you need:
In this example, I have created a namedpipe named PIPE_NAME, duplex, byte oriented, overlapped, etc..
Now we want to connect us to the namedpipe so we can send our data:
So, what have we done?
In the line 8, we create a dummy event on which we will wait. In the line 10 we try to connect to the namedpipe “hpipe” using the ConnectNamedPipe() function (msdn man) . This function will return an error because we are using it in overlapped mode: so we have to check the type of error (line 14):
1 – ERROR_PIPE_CONNECTED: the client is connected;
2 – ERROR_IO_PENDING: we are waiting the client’s connection: we can wait PIPE_TIMEOUT_CONNECT ms (10 seconds) using the WaitForSingleObject() (msdn man) on the ol.hEvent. If the function succeed, we must just have to check the result of the GetOverlappedResult() (msdn man). Otherwise we delete all the I/O pending operations (msdn man).
At the end (line 45), if ret != 0, we can send our data through the WriteFile() function (line 45) (msdn man).
For any question, you can use comments. 🙂
Bye.
Источник
ИТ База знаний
Курс по Asterisk
Полезно
— Узнать IP — адрес компьютера в интернете
— Онлайн генератор устойчивых паролей
— Онлайн калькулятор подсетей
— Калькулятор инсталляции IP — АТС Asterisk
— Руководство администратора FreePBX на русском языке
— Руководство администратора Cisco UCM/CME на русском языке
— Руководство администратора по Linux/Unix
Навигация
Серверные решения
Телефония
FreePBX и Asterisk
Настройка программных телефонов
Корпоративные сети
Протоколы и стандарты
Использование timeout в Linux с примерами
Все имеет начало и конец
3 минуты чтения
Вот вы пользователь Linux машины. И вот вам захотелось запустить какую-нибудь команду только на определенное время, и вы задаете вопрос — как это сделать? А вот как — использовать команду timeout .
Мини — курс по виртуализации
Знакомство с VMware vSphere 7 и технологией виртуализации в авторском мини — курсе от Михаила Якобсена
Как взять timeout — об использовании команды
Базовый синтаксис
Как и следовало ожидать, синтакс у команды экстремально прост: сама команда timeout — опции — длительность выполнения (можно даже с единицами измерения) — целевая команда
Единицы измерения для указания длительности:
- s — секунды (стоит по умолчанию)
- m — минуты
- h — часы
- d — дни
Если вы не укажете никакого параметра по длительности, команда не будет активирована.
- timeout 5 ping 1.1.1.1 — пингуем 1.1.1.1 5 секунд
- timeout 5m ping 1.1.1.1 — пингуем 1.1.1 5 минут
- timeout 5.5h ping 1.1.1.1 — 5,5 часов пингуем 1.1.1
Если у вас есть необходимость, можно запустить команду с добавкой sudo (если для целевой команды требуются права суперпользователя):
sudo timeout 100 tcpdump -n -w dump.pcap
Сообщение с космосом или отправка определенного сигнала исполняемому процессу
Если вы не указали какой-то особый сигнал, по умолчанию передается SIGTERM (сигнал о том, что надо бы мягко терминировать процесс). Однако, если вы укажете ключ -s после команды timeout, вы можете указать любой другой допустимый сигнал. К примеру: sudo timeout -s SIGKILL ping 1.1.1.1 или sudo timeout -s 9 ping 1.1.1.1
Обе команды выше идентичны, и если вы хотите увидеть весь список сигналов, просто введите kill -l
Как убить процесс, если он завис
Как вы уже поняли, SIGTERM — это сигнал, который отправляется после истечения таймаута, но он легко может быть проигнорирован процессом, и тогда процесс не остановится. Для уверенности в смерти процесса, нужно использовать ключ -k и некое временное значение. Тогда после окончания таймаута будет отправляться сигнал SIGKILL, который процесс не сможет проигнорировать при всем желании. В примере ниже команда выполняется одну минуту, и, если в течение 10 секунд после окончания таймаута она не «умирает», отправляется сигнал SIGKILL и «добивает» процесс:
sudo timeout -k 10 1m ping 1.1.1.1
Сохраняем статус
Команда timeout всегда возвращает значение 124 после истечения указанного времени или возвращает статус «exit» управляемой команды (той, что вы вводите после команды timeout). Таким образом, вы можете использовать ключ — -preserve-status :
timeout —preserve-status 10 ping 1.1.1.1
Запуск команды явно, а не за кулисами
По умолчанию, timout работает в бэкграунде, и если вы хотите обратного (вдруг после запуска управляемой команды потребуется какой-нибудь пользовательский ввод), нужно использовать ключ -foreground:
timeout —foreground 10m ./bestscripteva.sh
Заключение
В 99% процентов случаев команда timeout требует всего двух аргументов и ни одного факта: времени исполнения и самой исполняемой команды. Однако, вы теперь знаете и другие фишки использования этой замечательной команды.
Мини — курс по виртуализации
Знакомство с VMware vSphere 7 и технологией виртуализации в авторском мини — курсе от Михаила Якобсена
Источник