2013-08-02 34 views
11

bashスクリプトでは、IFS=$'\n'を設定した後に組み込みのreadコマンドを使用して標準入力から行を読み込もうとします。読み込みに入力を貼り付けると、行は4095文字の制限で切り捨てられます。この制限は、これは完全に罰金働いていたので、端末からの読み込みから来ているようだ: Linux端末入力: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システム(少なくとも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

解決方法はありませんが、質問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 
+0

はいパイプにはこのような制限があります。実際には、非インタラクティブバージョンはパイプを使用し、必然的に_いくつかの書き込みと読み取りが行われます_。しかし、私はこの限界が端末の入力に影響してはならないと考えています(端末はパイプではありません)。 – FooF

7

これは部分的な答えです。 非正規モードの端末を設定するは、4096文字以上の文字を読み取ることができます(文字#4096は改行する必要があります)。 bashスクリプトで

これは次のように行うことができます。stty -icanonあなたを追加し、この変更が長い4096文字列よりも貼り付けると、内蔵readコマンド(I首尾bashを使用して正常に読み取ることができた後

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). 

10000文字以上を試しました)。

端末ラインバッファの制限はおそらくカーネルによってどこかで設定されます。

TODO:

  1. Cプログラムは、Linux/x86_64のアーキテクチャと
  2. テスト(tcgetattr()tcsetattr()を使用して)これを実証する - 別の限界を有することができます。
  3. カーネルのどこに定義されていますか(おそらくN_TTY_BUF_SIZE${linux_source_path}/include/linux/tty.hで定義されています)。
-1

問題は間違いなくread()です。任意の有効な整数値まで読み取ることができます。問題はヒープメモリまたはパイプサイズから来ています。これらはサイズの唯一の制限要因です。

+0

いいえ、問題はターミナル・カノニカル・モードのバッファ・サイズです。入力行は4096(新しい行に予約されている最後のバイト)です。これは元の質問者の答えで説明され実証されています。彼はこれを実証するためのCプログラムを書く時間がまだなかったため、答えが完全ではないと言っています。カーネルのどこにこの限界が定義されているかを指摘できませんでした。 – FooF

+0

それは私が言っていることです、パイプのバッファーサイズは4096です。 "ulimit -p"を使ってチェックすることができます。これは8を返します。これは8 * 512バイト= 4096を意味します。あなたが言ったように、各文字が1バイトであるので、それは4095バイトだけを読み、最後の文字を改行として読みます。 – Abhishek

+1

私はそれが異なる定数だと思います。 4096はデフォルトのページサイズであり、正規のモードで最大パイプサイズと端末入力バッファで値が同じになる理由を説明しています。 – FooF