Linux 终端输入:从终端截断行读取用户输入,限制为 4095 个字符
- 2024-11-04 08:43:00
- admin 原创
- 39
问题描述:
在 bash 脚本中,我尝试在设置后使用内置read
命令从标准输入读取行`IFS=$'
'`。如果我将输入粘贴到读取中,行会在 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] = ' ';
printf("READ LINE: [%s]
", buf);
return 0;
}
在所有情况下,我都无法输入超过 4095 个字符。输入提示停止接受字符。
问题 1:在 Linux 系统(至少是 Ubuntu 10.04 和 13.04)中,有没有办法从终端以交互方式读取超过 4095 个字符的内容?
问题 2:这个限制从何而来?
受影响的系统:我注意到 Ubuntu 10.04/x86 和 13.04/x86 中存在此限制,但 Cygwin(至少是最新版本)在超过 10000 个字符时不会截断(没有进一步测试,因为我需要让此脚本在 Ubuntu 中运行)。使用的终端:虚拟控制台和 KDE konsole
(Ubuntu 13.04)和gnome-terminal
(Ubuntu 10.04)。
解决方案 1:
请参阅termios(3)手册页的“规范和非规范模式”部分。
通常,终端(标准输入)处于规范模式;在此模式下,内核将在将输入返回给应用程序之前缓冲输入行。Linux 的硬编码限制(N_TTY_BUF_SIZE
在 中定义${linux_source_path}/include/linux/tty.h
)设置为 4096,允许输入 4095 个字符(不包括结束的新行)。您还可以查看文件${linux_source_path}/drivers/tty/n_tty.c
、函数n_tty_receive_buf_common()
和上面的注释。
在非规范模式下,默认情况下内核不会进行缓冲,一旦返回一个输入字符(按下键) ,read(2)系统调用就会立即返回。您可以操纵终端设置来读取指定数量的字符或为非规范模式设置超时,但根据termios(3)
手册页(以及上述注释n_tty_receive_buf_common()
),硬编码限制也是 4095。
Bashread
内置命令在非规范模式下仍然有效,如下所示:
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).
添加此修改后,您可以粘贴长度超过 4096 个字符的字符串并使用内置命令stty -icanon
成功读取它(我成功尝试了长度超过 10000 个字符)。bash
`read`
如果您将其放在一个文件中,即将其制作成脚本,则您可以使用它strace
来查看被调用的系统调用,并且您将看到read(2)
多次被调用,每次在您键入输入时都返回一个字符。
解决方案 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() 上,因为它可以读取任意有效的整数值。问题出在堆内存或管道大小上,因为它们是唯一可能限制大小的因素。
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件