linux⽂件描述符-标准输⼊输出
当某个进程打开⽂件时,操作系统返回相应的⽂件描述符,进程为了处理该⽂件必须引⽤此描述符。
所谓的⽂件描述符是⼀个低级的正整数。最前⾯的三个⽂件描述符(0,1,2)分别与标准输⼊(stdin),标准输出(stdout)和标准错误(stderr)对应。
因此,函数 scanf() 使⽤ stdin,⽽函数 printf() 使⽤ stdout。你可以⽤不同的⽂件描述符改写默认的设置并重定向进程的 I/O 到不同的⽂件。
标准输⼊与输出
执⾏⼀个shell命令⾏时通常会⾃动打开三个标准⽂件,即标准输⼊⽂件(stdin),通常对应终端的键盘;
标准输出⽂件(stdout)和标准错误输出⽂件(stderr),这两个⽂件都对应终端的屏幕。
进程将从标准输⼊⽂件中得到输⼊数据,将正常输出数据输出到标准输出⽂件,⽽将错误信息送到标准错误⽂件中。
以cat命令为例,cat命令的功能是从命令⾏给出的⽂件中读取数据,并将这些数据直接送到标准输出。
若使⽤如下命令:
$ cat config
将会把⽂件config的内容依次显⽰到屏幕上。但是,如果cat的命令⾏中没有参数,它就会从标准输⼊中读取数据,并将其送到标准输出。例如:
$ cat
Hello world
Hello world
⽤户输⼊的每⼀⾏都⽴刻被cat命令输出到屏幕上。
直接使⽤标准输⼊/输出⽂件存在以下问题:
输⼊数据从终端输⼊时,⽤户费了半天劲输⼊的数据只能⽤⼀次。下次再想⽤这些数据时就得重新输⼊。⽽且在终端上输⼊时,若输⼊有误修改起来不是很⽅便。
输出到终端屏幕上的信息只能看不能动。⽆法对此输出作更多处理,如将输出作为另⼀命令的输⼊进
⾏进⼀步的处理等。
为了解决上述问题,Linux系统为输⼊、输出的传送引⼊了另外两种机制,即输⼊/输出重定向和管道。
输⼊重定向
输⼊重定向是指把命令(或可执⾏程序)的标准输⼊重定向到指定的⽂件中。也就是说,输⼊可以不来⾃键盘,⽽来⾃⼀个指定的⽂件。所以说,输⼊重定向主要⽤于改变⼀个命令的输⼊源,特别是改变那些需要⼤量输⼊的输⼊源。
例如,命令wc统计指定⽂件包含的⾏数、单词数和字符数。如果仅在命令⾏上键⼊:
$ wc
wc将等待⽤户告诉它统计什么,这时shell就好象死了⼀样,从键盘键⼊的所有⽂本都出现在屏幕上,但并没有什么结果,直⾄按下
ctrl+d,wc才将命令结果写在屏幕上。
如果给出⼀个⽂件名作为wc命令的参数,如下例所⽰,wc将返回该⽂件所包含的⾏数、单词数和字符数。
$ wc /etc/passwd
20 23 726 /etc/passwd
另⼀种把/etc/passwd⽂件内容传给wc命令的⽅法是重定向wc的输⼊。输⼊重定向的⼀般形式为:命令<⽂件名。可以⽤下⾯的命令把wc 命令的输⼊重定向为/etc/passwd⽂件:
$ wc < /etc/passwd
20 23 726
输出重定向
输出重定向是指把命令(或可执⾏程序)的标准输出或标准错误输出重新定向到指定⽂件中。这样,该命令的输出就不显⽰在屏幕上,⽽是写⼊到指定⽂件中。
输出重定向⽐输⼊重定向更常⽤,很多情况下都可以使⽤这种功能。
例如,如果某个命令的输出很多,在屏幕上不能完全显⽰,那么将输出重定向到⼀个⽂件中,然后再⽤⽂本编辑器打开这个⽂件,就可以查看输出信息;如果想保存⼀个命令的输出,也可以使⽤这种⽅法。
还有,输出重定向可以⽤于把⼀个命令的输出当作另⼀个命令的输⼊(还有⼀种更简单的⽅法,就是使⽤管道,将在下⾯介绍)。
输出重定向的⼀般形式为:命令>⽂件名。例如:
$ ls > directory.out
$ cat directory.out
ch1.doc ch2.doc ch3.doc chimp config mail/ test/
将ls命令的输出保存为⼀个名为directory.out的⽂件。
注:如果>符号后边的⽂件已存在,那么这个⽂件将被重写。
为避免输出重定向中指定⽂件只能存放当前命令的输出重定向的内容,shell提供了输出重定向的⼀种追加⼿段。
输出追加重定向与输出重定向的功能⾮常相似,区别仅在于输出追加重定向的功能是把命令(或可执⾏程序)的输出结果追加到指定⽂件的最后,⽽该⽂件原有内容不被破坏。
如果要将⼀条命令的输出结果追加到指定⽂件的后⾯,可以使⽤追加重定向操作符>>。
形式为:命令>>⽂件名。例如:
$ ls *.doc>>directory.out
$ cat directory.out
ch1.doc ch2.doc ch3.doc chimp config mail/ test/
ch1.doc ch2.doc ch3.doc
和程序的标准输出重定向⼀样,程序的错误输出也可以重新定向。2>(或2>>)表⽰对错误输出设备重定向。例如下⾯的命令:
$ ls /usr/tmp 2> err.file
可在屏幕上看到程序的正常输出结果,但⼜将程序的任何错误信息送到⽂件err.file中,以备将来检查⽤。
还可以使⽤另⼀个输出重定向操作符(&>)将标准输出和错误输出同时送到同⼀⽂件中。例如:
$ ls /usr/tmp &> output.file
利⽤重定向将命令组合在⼀起,可实现系统单个命令不能提供的新功能。例如使⽤下⾯的命令序列:
$ ls /usr/bin > /tmp/dir
$ wc -w < /tmp/dir
459
统计了/usr/bin⽬录下的⽂件个数。
管道
将⼀个程序或命令的输出作为另⼀个程序或命令的输⼊,有两种⽅法,
⼀种是通过⼀个临时⽂件将两个命令或程序结合在⼀起,例如上个例⼦中的/tmp/dir⽂件将ls和wc命令联在⼀起;
另⼀种是Linux所提供的管道功能。这种⽅法⽐前⼀种⽅法更好。
管道可以把⼀系列命令连接起来,这意味着第⼀个命令的输出会作为第⼆个命令的输⼊通过管道传给第⼆个命令,第⼆个命令的输出⼜会作为第三个命令的输⼊,以此类推。
显⽰在屏幕上的是管道⾏中最后⼀个命令的输出(如果命令⾏中未使⽤输出重定向)。
通过使⽤管道符“|”来建⽴⼀个管道⾏。⽤管道重写上⾯的例⼦:
$ ls /usr/bin|wc -w
1789
命令替换
命令替换和重定向有些相似,但区别在于命令替换是将⼀个命令的输出作为另外⼀个命令的参数。常⽤命令格式为:
command1 `command2`
其中,command2的输出将作为command1的参数。需要注意的是这⾥的`符号,被它括起来的内容将作为命令执⾏,执⾏后的结果作为command1的参数。例如:
$ cd `pwd`
该命令将pwd命令列出的⽬录作为cd命令的参数,结果仍然是停留在当前⽬录下
⾸先说什么是⽂件描述符,它有什么作⽤?
⽂件描述符是⼀个简单的整数,⽤以标明每⼀个被进程所打开的⽂件和socket。第⼀个打开的⽂件是0,第⼆个是1,依此类推。
Unix 操作系统通常给每个进程能打开的⽂件数量强加⼀个限制。更甚的是,unix 通常有⼀个系统级的限制。
例如:squid 的⼯作⽅式,⽂件描述符的限制可能会极⼤的影响性能。当squid ⽤完所有的⽂件描述符后,它不能接收⽤户新的连接。
也就是说,⽤完⽂件描述符导致拒绝服务。squid 不能接收新请求,直到⼀部分当前请求完成,相应的⽂件和socket 被关闭。当squid发现⽂件描述符短缺时,它会发布警告。
在运⾏./configure 之前,检查你的系统的⽂件描述符限制是否合适,能给你避免⼀些⿇烦。
⼤多数情况下,1024 个⽂件描述符⾜够了。⾮常忙的cache可能需要4096或更多。在配置⽂件描述符限制时,我推荐设置系统级限制的数量为每个进程限制的2 倍。
2、怎么突破,具体⽅法?
先查看Linux默认的⽂件描述符:
# ulimit -nlinux重定向
1024
我们⽤命令ulimit -HSn 65536来增⼤⽂件描述符,然后编译安装squid,把ulimit -HSn 65536放到/etc/rc.d/rc.local让启动时加载。
在Linux下⾯部署web应⽤的时候,有时候会遇上Socket/File: Can’t open so many files的问题;
这个值也会影响服务器的最⼤并发数,其实Linux是有⽂件句柄限制的,⽽且Linux默认不是很⾼,⼀般都是1024,⽣产服务器⽤其实很容易就达到这个数量。
查看⽅法
我们可以⽤ulimit -a来查看所有限制值
[root@centos5 ~]# ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
max nice (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 4096
max locked memory (kbytes, -l) 32
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
max rt priority (-r) 0
stack size (kbytes, -s) 10240
cpu time (seconds, -t) unlimited
max user processes (-u) 4096
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited||<
其中 "open files (-n) 1024 "是Linux操作系统对⼀个进程打开的⽂件句柄数量的限制(也包含打开的SOCKET数量,可影响MySQL的并发连接数⽬)。
这个值可⽤ulimit命令来修改,但ulimit命令修改的数值只对当前登录⽤户的⽬前使⽤环境有效,系统重启或者⽤户退出后就会失效。
(在布署Nginx+FastCGI我就遇到这个问题,将ulimit -SHn 65535放到/etc/rc.d/rc.local也没起什么作⽤)
系统总限制是在这⾥,/proc/sys/fs/file-max。可以通过cat查看⽬前的值,修改/f 中也可以控制。
另外还有⼀个,/proc/sys/fs/file-nr,可以看到整个系统⽬前使⽤的⽂件句柄数量。
查⽂件句柄问题的时候,还有⼀个很实⽤的程序lsof。可以很⽅便看到某个进程开了那些句柄,也可以看到某个⽂件/⽬录被什么进程占⽤了。
修改⽅法
若要令修改ulimits的数值永久⽣效,则必须修改配置⽂档,可以给ulimit修改命令放⼊/etc/profile⾥⾯,这个⽅法实在是不⽅便,还有⼀个⽅法是修改/f。
我修改了,测试过,但对⽤户的ulimits -a 是不会改变的,只是/proc/sys/fs/file-max的值变了。
我认为正确的做法,应该是修改/etc/f,⾥⾯有很详细的注释,⽐如
* soft nofile 32768
* hard nofile 65536
就可以将⽂件句柄限制统⼀改成软32768,硬65536。配置⽂件最前⾯的是指domain,设置为星号代表全局,另外你也可以针对不同的⽤户做出不同的限制。
注意:这个当中的硬限制是实际的限制,⽽软限制,是warnning限制,只会做出warning;其实ulimit命令本⾝就有分软硬设置,加-H就是硬,加-S就是软
默认显⽰的是软限制,如果运⾏ulimit命令修改的时候没有加上的话,就是两个参数⼀起改变。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论