Linux 终端输入:从 4095 个字符限制的终端截断行读取用户输入 [英] Linux terminal input: reading user input from terminal truncating lines at 4095 character limit
问题描述
在 bash 脚本中,我尝试在设置 IFS=$'
'
后使用内置的 read
命令从标准输入读取行.如果我将输入粘贴到读取中,这些行将在 4095 个字符限制处被截断.这个限制似乎来自从终端读取,因为它工作得很好:
In a bash script, I try to read lines from standard input, using built-in read
command after setting IFS=$'
'
. The lines are truncated at 4095 character limit if I paste input to the read. This limitation seems to come from reading from terminal, because this worked perfectly fine:
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 脚本时遇到了相同的行为(不接受来自终端的超过 4095 的输入,但接受来自管道的输入):
I experience the same behavior with Python script (did not accept longer than 4095 input from terminal, but accepted from pipe):
#!/usr/bin/python
from sys import stdin
line = stdin.readline()
print('%s' % line)
即使是C程序也一样,使用read(2)
:
Even C program works the same, using read(2)
:
#include <stdio.h>
#include <unistd.h>
int main(void)
{
char buf[32768];
int sz = read(0, buf, sizeof(buf) - 1);
buf[sz] = ' ';
printf("READ LINE: [%s]
", buf);
return 0;
}
在所有情况下,我都不能输入超过 4095 个字符.输入提示停止接受字符.
In all cases, I cannot enter longer than about 4095 characters. The input prompt stops accepting characters.
问题 1: 有没有办法在 Linux 系统(至少是 Ubuntu 10.04 和 13.04)中从终端交互式读取超过 4095 个字符的内容?
Question-1: Is there a way to interactively read from terminal longer than 4095 characters in Linux systems (at least Ubuntu 10.04 and 13.04)?
问题 2:这个限制从何而来?
系统受影响:我注意到 Ubuntu 10.04/x86 和 13.04/x86 中的这个限制,但是 Cygwin(至少是最近的版本)没有截断超过 10000 个字符(因为我没有进一步测试)需要让这个脚本在 Ubuntu 中工作).使用的终端:虚拟控制台和 KDE konsole
(Ubuntu 13.04) 和 gnome-terminal
(Ubuntu 10.04).
Systems affected: I noticed this limitation in Ubuntu 10.04/x86 and 13.04/x86, but Cygwin (recent version at least) does not truncate yet at over 10000 characters (did not test further since I need to get this script working in Ubuntu). Terminals used: Virtual Console and KDE konsole
(Ubuntu 13.04) and gnome-terminal
(Ubuntu 10.04).
推荐答案
请参考termios(3) 手册页,在规范和非规范模式"部分下.
Please refer to termios(3) manual page, under section "Canonical and noncanonical mode".
通常,终端(标准输入)处于规范模式;在这种模式下,内核将在将输入返回给应用程序之前缓冲输入行.Linux 的硬编码限制(${linux_source_path}/include/linux/tty.h
中定义的N_TTY_BUF_SIZE
)设置为 4096,允许输入 4095 个字符,不包括结束新行.您还可以查看文件 ${linux_source_path}/drivers/tty/n_tty.c
、函数 n_tty_receive_buf_common()
以及上面的注释.
Typically, the terminal (standard input) is in canonical mode; in this mode the kernel will buffer the input line before returning the input to the application. The hard-coded limit for Linux (N_TTY_BUF_SIZE
defined in ${linux_source_path}/include/linux/tty.h
) is set to 4096 allowing input of 4095 characters not counting the ending new line. You can also have a look at file ${linux_source_path}/drivers/tty/n_tty.c
, function n_tty_receive_buf_common()
and the comment above that.
在非规范模式下,默认情况下内核和 read(2) 一旦返回一个输入字符(按下键),系统调用立即返回.您可以操作终端设置以读取指定数量的字符或为非规范模式设置超时,但根据 termios(3)
手册页,硬编码限制也是 4095(以及上面提到的 n_tty_receive_buf_common()
上面的注释).
In noncanonical mode there will by default be no buffering by kernel and the read(2) system call returns immediately once a single character of input is returned (key is pressed). You can manipulate the terminal settings to read a specified amount of characters or set a time-out for non-canonical mode, but then too the hard-coded limit is 4095 per the termios(3)
manual page (and the comment above the above mentioned n_tty_receive_buf_common()
).
Bash read
内置命令在非规范模式下仍然有效,如下所示:
Bash read
builtin command still works in non-canonical mode as can be demonstrated by the following:
IFS=$'
' # 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 个字符).
After this modification of adding stty -icanon
you can paste longer than 4096 character string and read it successfully using bash
built-in read
command (I successfully tried longer than 10000 characters).
如果你把它放在一个文件里,也就是把它变成一个脚本,你可以使用strace
来查看调用的系统调用,你会看到read(2)
多次调用,每次输入输入时返回一个字符.
If you put this in a file, i.e. make it a script, you can use strace
to see the system calls called, and you will see read(2)
called multiple times, each time returning a single character when you type input to it.
这篇关于Linux 终端输入:从 4095 个字符限制的终端截断行读取用户输入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!