Linux终端输入:从终端截断行读取用户输入,限制为4095个字符

时间:2013-08-02 10:52:36

标签: linux input terminal

在bash脚本中,我尝试在设置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脚本相同的行为(不接受来自终端的4095输入,但是从管道接受):

#!/usr/bin/python

from sys import stdin

line = stdin.readline()
print('%s' % line)

即使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:有没有办法在Linux系统中以超过4095个字符的交互方式进行交互式读取(至少是Ubuntu 10.04和13.04)?

问题2:此限制来自哪里?

受影响的系统:我注意到Ubuntu 10.04 / x86和13.04 / x86中存在这种限制,但Cygwin(至少是最近的版本)还没有截断超过10000个字符(因为我没有进一步测试)需要让这个脚本在Ubuntu中工作)。使用的终端:虚拟控制台和KDE konsole(Ubuntu 13.04)和gnome-terminal(Ubuntu 10.04)。

3 个答案:

答案 0 :(得分:10)

请参阅termios(3)手册页,“Canonical and noncanonical mode”。

默认情况下,终端(标准输入)处于规范模式;在此模式下,内核将在将输入返回给应用程序之前缓冲输入行。 Linux的硬编码限制(可能N_TTY_BUF_SIZE中定义的${linux_source_path}/include/linux/tty.h)设置为4096,允许输入4095个字符,不包括结束的新行。在非规范模式下,默认情况下,内核不会进行缓冲,并且一旦返回单个输入字符(按下键),read(2)系统调用将立即返回。您可以操作终端设置以读取指定数量的字符或为非规范模式设置超时,但是对于termios(3)手册页,硬编码限制也是4095。

Bash read内置命令仍然可以在非规范模式下运行,如下所示:

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个字符)。

如果你把它放在一个文件中,即把它变成一个脚本,你可以使用strace查看被调用的系统调用,你会看到多次调用read(2),每次返回一个字符。

答案 1 :(得分:-1)

我没有为您解决方法,但我可以回答问题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

答案 2 :(得分:-2)

问题绝对不是read();因为它可以读取任何有效的整数值。问题来自堆内存或管道大小..因为它们是尺寸的唯一可能的限制因素..