放弃不会更舒服,只会万劫不复
撑住,才有后来的一切 ---2017.8.26
我们在编写shell的时候或者查看系统中的脚本程序时,经常会碰到题目中的文字信息,很多人搞不清楚这是什么意思(What),如何使用(How),用在何处(Where),何时要用(When),为什么这么用(Why)。
下面小编带你逐步剖析一下,相信读过本文后,你会豁然开朗,妈妈再也不用担心我的学习了。
一、知识储备
1、文件描述符
在Linux shell执行命令时,每个进程都和三个打开的文件相联系,并使用文件描述符来引用这些文件。由于文件描述符不容易记忆,shell同时也给出了相应的文件名:
文件 | 文件描述符 |
输入文件—标准输入 | 0(缺省是键盘,为0时是文件或者其他命令的输出) |
输出文件—标准输出 | 1(缺省是屏幕,为1时是文件) |
错误输出文件—标准错误 | 2(缺省是屏幕,为2时是文件) |
这里对文件描述符作一下引申:
我们在进行应用的测试或者运维时经常会碰到“Too many open files”的提示,这说明你操作的文件句柄已经超过了系统的参数配置,需要进行相应修改,下面简单介绍一下linux与solaris系统下文件句柄的修改方式:
1.1、Linux平台
A、查看配置
通过命令:ulimit -n 进行查看系统当前值;
查看当前系统使用的打开文件描述符数,可以使用下面的命令:
[root@localhost ~]# cat /proc/sys/fs/file-nr
1632 0 1513506
-
第一个数表示当前系统已分配使用的打开文件描述符数
-
第二个数为分配后已释放的(目前已不再使用)
-
第三个数等于file-max。
B、修改配置
Linux内核本身有文件描述符最大值的限定,你可以根据需要更改:
-
系统最大打开文件描述符数:/proc/sys/fs/file-max
临时性设置:echo 1000000 > /proc/sys/fs/file-max
永久设置:修改/etc/sysctl.conf文件,增加fs.file-max = 1000000
进程最大打开文件描述符数
使用ulimit -n查看当前设置。使用ulimit -n 1000000进行临时性设置。
要想永久生效,你可以修改/etc/security/limits.conf文件,增加下面的行:
* hard nofile 1000000
* soft nofile 1000000
root hard nofile 1000000
root soft nofile 1000000
(对于安装过oracle数据库的各位,上面的信息想必不会陌生)
还有一点要注意的就是hard limit不能大于/proc/sys/fs/nr_open,因此有时你也需要修改nr_open的值。
执行echo 2000000 > /proc/sys/fs/nr_open
C、总结
-
所有进程打开的文件描述符数不能超过/proc/sys/fs/file-max
-
单个进程打开的文件描述符数不能超过user limit中nofile的soft limit
-
nofile的soft limit不能超过其hard limit
-
nofile的hard limit不能超过/proc/sys/fs/nr_open
1.2、Solaris平台
进程能够打开的最大文件句柄数决定了每个进程能够同时打开的文件数量。Solaris10上缺省值是256,对于某些应用而言,缺省值太小,需要手工修改。
A、查看配置
有两种方式,一是使用ulimit命令,二是使用prctl命令;
a)、ulimit命令
oracle@hisdb:~ $>ulimit -a
core file size (blocks, -c) unlimited
data seg size (kbytes, -d) unlimited
file size (blocks, -f) unlimited
open files (-n) 256
pipe size (512 bytes, -p) 10
stack size (kbytes, -s) 10240
cpu time (seconds, -t) unlimited
max user processes (-u) 11445
virtual memory (kbytes, -v) unlimited
open files表示进程能够打开的最大文件句柄数量。
b)、prctl命令
oracle@hisdb:~ $>prctl -i process $$
process: 1079: -bash
NAME PRIVILEGE VALUE FLAG ACTION RECIPIENT
……
process.max-file-descriptor
basic 256 - deny 1079
privileged 65.5K - deny -
system 2.15G max deny -
……
process.max-file-descriptor表示进程能够打开的最大文件句柄数,其中basic表示软限制,privileged表示硬限制。非root用户可以在硬限制的范围内自行调整软硬限制值。
B、修改配置
修改此参数通常有以下几种方法:
1)、使用ulimit命令或plimit命令修改
ulimit命令只能修改当前SHELL及其子进程的设置,设置后立即生效,一旦当前SHELL退出设置即失效。-S参数用于设置软限制,-H参数用于设置硬限制。
-
设置软限制:
oracle@hisdb:~ $>ulimit -S -n 1024
oracle@hisdb:~ $>ulimit -a
core file size (blocks, -c) unlimited
data seg size (kbytes, -d) unlimited
file size (blocks, -f) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 10
stack size (kbytes, -s) 10240
cpu time (seconds, -t) unlimited
max user processes (-u) 11445
virtual memory (kbytes, -v) unlimited
oracle@hisdb:~ $>prctl -i process $$
process: 1079: -bash
NAME PRIVILEGE VALUE FLAG ACTION RECIPIENT
……
process.max-file-descriptor
basic 1.02K - deny 1079
privileged 65.5K - deny -
system 2.15G max deny -
……
oracle@hisdb:~ $>ulimit -S -n 65536
oracle@hisdb:~ $>ulimit -a
core file size (blocks, -c) unlimited
data seg size (kbytes, -d) unlimited
file size (blocks, -f) unlimited
open files (-n) 65536
pipe size (512 bytes, -p) 10
stack size (kbytes, -s) 10240
cpu time (seconds, -t) unlimited
max user processes (-u) 11445
virtual memory (kbytes, -v) unlimited
oracle@hisdb:~ $>ulimit -S -n 65537
-bash: ulimit: open files: cannot modify limit: Invalid argument
软限制只能在privileged的值以下调整,此例中所能调整的最大值是65536。
-
设置硬限制
oracle@hisdb:~ $>ulimit -a
core file size (blocks, -c) unlimited
data seg size (kbytes, -d) unlimited
file size (blocks, -f) unlimited
open files (-n) 256
pipe size (512 bytes, -p) 10
stack size (kbytes, -s) 10240
cpu time (seconds, -t) unlimited
max user processes (-u) 11445
virtual memory (kbytes, -v) unlimited
ulimit命令中open files显示的是软限制,可以用prctl命令显示硬限制,即privileged值。
oracle@hisdb:~ $>prctl -i process $$
process: 1139: -bash
NAME PRIVILEGE VALUE FLAG ACTION RECIPIENT
……
process.max-file-descriptor
basic 256 - deny 1139
privileged 65.5K - deny -
system 2.15G max deny -
……
oracle@hisdb:~ $>ulimit -H -n 65537
-bash: ulimit: open files: cannot modify limit: Not owner
oracle@hisdb:~ $>ulimit -H -n 32768
oracle@hisdb:~ $>ulimit -a
core file size (blocks, -c) unlimited
data seg size (kbytes, -d) unlimited
file size (blocks, -f) unlimited
open files (-n) 256
pipe size (512 bytes, -p) 10
stack size (kbytes, -s) 10240
cpu time (seconds, -t) unlimited
max user processes (-u) 11445
virtual memory (kbytes, -v) unlimited
oracle@hisdb:~ $>prctl -i process $$
process: 1139: -bash
NAME PRIVILEGE VALUE FLAG ACTION RECIPIENT
process.max-file-descriptor
basic 256 - deny 1139
privileged 32.8K - deny -
system 2.15G max deny -
非root用户调整硬限制时只能往小调,不能往大调。
2)、修改/etc/system参数
在Solaris10上,这种方法已经不建议使用,但这种方式仍然有效。/etc/system中设置参数是全局有效的,即所有用户均会受影响。并且设置后,需要重启系统才能生效。
设置方法是在/etc/system文件中增加以下两个参数,然后重启系统。
set rlim_fd_cur=1024
set rlim_fd_max=65535
-
以下是两个参数的说明:
-
rlim_fd_max (硬限制)
Description : Specifies the “hard” limit on file descriptors that a single process might have open.Overriding this limit requires superuser privilege.
Data Type : Signed integer
Default : 65,536
Range : 1 to MAXINT
Units : File descriptors
Dynamic? : No
Validation : None
When to Change : When the maximum number of open files for a process is not enough. Other limitations in system facilities can mean that a larger number of file descriptors is not as useful as it might be. For example:
■ A 32-bit program using standard I/O is limited to 256 file descriptors. A 64-bit program using standard I/O can use up to 2 billion descriptors. Specifically, standard I/O refers to the
stdio(3C) functions in libc(3LIB).
■ select is by default limited to 1024 descriptors per fd_set. For more information, see select(3C). Starting with the Solaris 7 release, 32-bit application code can be recompiled with a larger fd_set size (less than or equal to 65,536). A 64-bit application uses an fd_set size of 65,536, which cannot be changed.
An alternative to changing this on a system wide basis is to use the plimit(1) command. If a parent process has its limits changed by plimit, all children inherit the increased limit. This alternative is useful for daemons such as inetd.
Commitment Level : Unstable
ChangeHistory : For information, see “rlim_fd_max (Solaris 8 Release)” on page 184.
-
rlim_fd_cur (软限制)
Description : Defines the “soft” limit on file descriptors that a single process can have open. A process might adjust its file descriptor limit to any value up to the “hard” limit defined by rlim_fd_max by using the setrlimit() call or by issuing the limit command in whatever shell it is running. You do not require superuser privilege to adjust the limit to any value less than or equal to the hard limit.
Data Type : Signed integer
Default : 256
Range : 1 to MAXINT
Units : File descriptors
Dynamic? : No
Validation : Compared to rlim_fd_max. If rlim_fd_cur is greater than rlim_fd_max, rlim_fd_cur is reset to rlim_fd_max.
When to Change : When the default number of open files for a process is not enough. Increasing this value means only that it might not be necessary for a program to use setrlimit to increase the maximum number of file descriptors available to it.
Commitment Level : Unstable
3)、project命令
project是Solaris10新增加的特性,可以通过设置project参数为一个用户或一组用户设置参数值。设置后可立即生效。
以下是设置示例:
root@hisdb:/ #>projadd user.test (创建project user.test)
root@hisdb:/ #>id -p test
uid=100(test) gid=1(other) projid=100(user.test) (test用户属于project user.test)
root@hisdb:/ #>projmod -a -K "process.max-file-descriptor=(basic,65537,deny)" user.test
root@hisdb:/ #>projmod -a -K "process.max-file-descriptor=(priv,65538,deny)" user.test
root@hisdb:/ #>grep 'user.test' /etc/project
user.test:100::::process.max-file-descriptor=(basic,65537,deny),(priv,65538,deny)
设置basic和privilege值分别为65537和65538,越过/etc/system中的最大硬限制
root@hisdb:/ #>tail -2 /etc/system
set rlim_fd_cur=1024
set rlim_fd_max=65535
root@hisdb:/ #>plimit $$
1041: -bash
resource current maximum
time(seconds) unlimited unlimited
file(blocks) unlimited unlimited
data(kbytes) unlimited unlimited
stack(kbytes) 10240 unlimited
coredump(blocks) unlimited unlimited
nofiles(descriptors) 1024 65535
vmemory(kbytes) unlimited unlimited
root用户的结果只受/etc/system里参数的影响,而不受project user.test影响,root用户不属于此project.
root@hisdb:/ #>su - test
Oracle Corporation SunOS 5.10 Generic Patch January 2005
test@hisdb:~ $>plimit $$
1091: -bash
resource current maximum
time(seconds) unlimited unlimited
file(blocks) unlimited unlimited
data(kbytes) unlimited unlimited
stack(kbytes) 10240 unlimited
coredump(blocks) unlimited unlimited
nofiles(descriptors) 65535 65535
vmemory(kbytes) unlimited unlimited
test@hisdb:~ $>id -p
uid=100(test) gid=1(other) projid=100(user.test)
用户test当前值和最大值都是65535,而project user.test里设置的值分别是65537和65538,用户结果与project设置值不一致,这是因为project中设置的值超过了/etc/system里设置的最大硬限制数是65535,此时系统自动将用户结果调整为/etc/system中设置的最大硬限制数。
root@hisdb:/ #>projmod -s -K "process.max-file-descriptor=(basic,32767,deny),(priv,32768,deny)" user.test
root@hisdb:/ #>plimit $$
1041: -bash
resource current maximum
time(seconds) unlimited unlimited
file(blocks) unlimited unlimited
data(kbytes) unlimited unlimited
stack(kbytes) 10240 unlimited
coredump(blocks) unlimited unlimited
nofiles(descriptors) 1024 65535
vmemory(kbytes) unlimited unlimited
root用户未受project user.test调整影响。
root@hisdb:/ #>su - test
Oracle Corporation SunOS 5.10 Generic Patch January 2005
test@hisdb:~ $>plimit $$
1099: -bash
resource current maximum
time(seconds) unlimited unlimited
file(blocks) unlimited unlimited
data(kbytes) unlimited unlimited
stack(kbytes) 10240 unlimited
coredump(blocks) unlimited unlimited
nofiles(descriptors) 32767 32768
vmemory(kbytes) unlimited unlimited
用户test当前值和最大值均与project user.test中的设置一致。
注:
如果在系统里同时设置/etc/system和project里的参数时要注意以下几点:
1. /etc/system的设置是全局设置,会影响所有用户,而project的设置仅影响属于此project的用户。
2. /etc/system的设置需要重启系统才能生效,而project的设置立即生效(新进程)。
3. /etc/system的硬限制值是所有用户的最大限制值。如果project中的设置值超过了/etc/system的硬限制值,则project设置无效,相应用户值会被设置为/etc/system的硬限制值。
1.3、HPUX平台
A、查看配置
通过命令:ulimit -a
B、修改配置
1)、通过sam(smh)命令
2)、设定HP-UX的核心环境,对核心环境进行管理。但修改后不能立即对核心参数进行管理。因为系统会向boot.config读出参数,所以只有移走boot.config,然后再用getkinfo重建boot.config文件。在SAM--》Kernel configuration--> Parameter会自动运行getkinfo 命令。
-
先修改/usr/conf/master.d/core-hpux:
*range maxfiles<=60000
*range maxfiles_lim<=60000
-
把/var/sam/boot.config文件mv成boot.config.bak
mv /var/sam/boot.config /var/sam/boot.config.bak
-
然后运行:/usr/sam/lbin/getkinfo -b
1.4、AIX平台
A、查看配置
通过命令:ulimit -a
B、修改配置
1)、通过工具smit进行修改
2)、修改文件:/etc/security/limits
2、文件重定向
2.1、输出重定向
Command > filename | 把标准输出重定向到一个新文件中 |
Command >> filename | 把标准输出重定向到一个文件中(追加) |
Command > filename | 把标准输出重定向到一个文件中 |
Command > filename 2>&1 | 把标准输出和错误一起重定向到一个文件中 |
Command 2 > filename | 把标准错误重定向到一个文件中 |
Command 2 >> filename | 把标准输出重定向到一个文件中(追加) |
Command >> filename2>&1 | 把标准输出和错误一起重定向到一个文件(追加) |
2.2、输入重定向
Command < filename > filename2 | Command命令以filename文件作为标准输入,以filename2文件作为标准输出 |
Command < filename | Command命令以filename文件作为标准输入 |
Command << delimiter | 从标准输入中读入,知道遇到delimiter分界符 |
2.3、绑定重定向
Command >&m | 把标准输出重定向到文件描述符m中 |
Command < &- | 关闭标准输入 |
Command 0>&- | 同上 |
3、/dev/null介绍
是个黑洞设备,它丢弃一切写入其中数据,空设备通常被用于丢弃不需要的输出流。记得当年用windows时候,有个类似的设备:NUL ,跟这个功能一样。任何写入该设备数据都会被丢弃掉。从这个里面读取数据返回是空。将一些不用内容经常发送给这个设备,丢弃不需要的数据。
二、>/dev/null 2>&1剖析
前面啰嗦了太多,各位是不是有点不耐烦了,不要着急,如果你仔细阅读了前面的基础知识,相信这个问题就迎刃而解了:
我们把题目分解开来如下:
-
/dev/null 代表空设备文件
-
> 代表重定向到哪里,例如:echo "123" > /home/123.txt
-
1 表示stdout标准输出,系统默认值是1,所以">/dev/null"等同于"1>/dev/null"
-
2 表示stderr标准错误
-
& 表示等同于的意思,2>&1,表示2的输出重定向等同于1
那么本文标题的正确理解为:
-
1>/dev/null 首先表示标准输出重定向到空设备文件,也就是不输出任何信息到终端,说白了就是不显示任何信息。
-
2>&1 接着,标准错误输出重定向等同于 标准输出,因为之前标准输出已经重定向到了空设备文件,所以标准错误输出也重定向到空设备文件。
各位看官,不知你理解了没有,你应该明白What/How/Where/When/Why,如果没有理解的话,请再回头多看几遍,相信你会有收获的。
如果你觉得有所收获并愿意继续学习的话,请扫码关注:
你也可以转账赞赏哟
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/23149897/viewspace-2144189/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/23149897/viewspace-2144189/