Вход в терминал Linux: чтение пользовательского ввода с терминальных линий усечения при значении 4095 символов
В bash script я пытаюсь читать строки со стандартного ввода, используя встроенную команду read
после установки IFS=$'\n'
. Строки усекаются с пределом 4095 символов, если я вставляю ввод в чтение. Это ограничение, похоже, исходит от чтения с терминала, потому что это отлично работает:
fill=
for i in $(seq 1 94); do fill="${fill}x"; done
for i in $(seq 1 100); do printf "%04d00$fill" $i; done | (read line; echo $line)
Я испытываю такое же поведение с Python script (не принимал дольше 4095 ввода от терминала, но принимал его из канала):
#!/usr/bin/python
from sys import stdin
line = stdin.readline()
print('%s' % line)
Программа Even C работает одинаково, используя read(2)
:
#include <stdio.h>
#include <unistd.h>
int main(void)
{
char buf[32768];
int sz = read(0, buf, sizeof(buf) - 1);
buf[sz] = '\0';
printf("READ LINE: [%s]\n", buf);
return 0;
}
Во всех случаях я не могу ввести более 4095 символов. Запрос на ввод прекращает принимать символы.
Вопрос-1: Есть ли способ интерактивного чтения с терминала длиной более 4095 символов в системах Linux (по крайней мере, Ubuntu 10.04 и 13.04)?
Вопрос-2: Откуда взялось это ограничение?
Затрагиваемые системы: Я заметил это ограничение в Ubuntu 10.04/x86 и 13.04/x86, но Cygwin (по крайней мере, последняя версия) не обрезает еще более 10000 символов (не тестировалось дальше, так как я нужно, чтобы этот script работал в Ubuntu). Используемые терминалы: Виртуальная консоль и KDE konsole
(Ubuntu 13.04) и gnome-terminal
(Ubuntu 10.04).
Ответы
Ответ 1
Это частичный ответ. Настройка терминала в неканоническом режиме позволяет читать более 4096 символов (где символ # 4096 должен быть новой строкой).
В bash script это можно сделать следующим образом:
IFS=$'\n' # Allow spaces and other white spaces.
stty -icanon # Disable canonical mode.
read line # Now we can read without inhibitions set by terminal.
stty icanon # Re-enable canonical mode (assuming it was enabled to begin with).
После этой модификации добавления stty -icanon
вы можете вставить длиной более 4096 символов и прочитать ее успешно, используя bash
встроенную команду read
(я успешно пробовал более 10000 символов).
Предел для буфера терминальной линии, вероятно, задается ядром где-то.
TODO:
- C, чтобы продемонстрировать это (используя
tcgetattr()
и tcsetattr()
)
- Тест с архитектурой Linux/x86_64 - может иметь разные ограничения.
- Найти, где в ядре это определено (возможно,
N_TTY_BUF_SIZE
определено в ${linux_source_path}/include/linux/tty.h
).
Ответ 2
У меня нет обходного пути для вас, но я могу ответить на вопрос 2.
В linux PIPE_BUF установлено значение 4096 (в limits.h
). Если вы пишете более 4096 в канал, он будет усечен.
От /usr/include/linux/limits.h
:
#ifndef _LINUX_LIMITS_H
#define _LINUX_LIMITS_H
#define NR_OPEN 1024
#define NGROUPS_MAX 65536 /* supplemental group IDs are available */
#define ARG_MAX 131072 /* # bytes of args + environ for exec() */
#define LINK_MAX 127 /* # links a file may have */
#define MAX_CANON 255 /* size of the canonical input queue */
#define MAX_INPUT 255 /* size of the type-ahead buffer */
#define NAME_MAX 255 /* # chars in a file name */
#define PATH_MAX 4096 /* # chars in a path name including nul */
#define PIPE_BUF 4096 /* # bytes in atomic write to a pipe */
#define XATTR_NAME_MAX 255 /* # chars in an extended attribute name */
#define XATTR_SIZE_MAX 65536 /* size of an extended attribute value (64k) */
#define XATTR_LIST_MAX 65536 /* size of extended attribute namelist (64k) */
#define RTSIG_MAX 32
#endif
Ответ 3
Проблема, безусловно, не в read(); так как он может читать до любого действительного целочисленного значения. Проблема возникает из памяти кучи или размера трубы.. поскольку они являются единственными возможными ограничивающими факторами размера.