文件描述符讲解

1、文件描述符定义

文件描述符:是内核为了高效管理已被打开的文件所创建的索引,用于指向被打开的文件,所有的i/o操作的系统调用都会通过文件描述符

文件描述符是一个简单的非负整数,用来表明每一个被进程锁打开的文件,程序刚启动的时候,第一个打开的文件是0,第二个是1,如此类推

stdin–>0:输入设备

stdout–>1:输出设备

stderr–>2:错误

stdin—>进程—>stdout/stderr—>用户看到

#查看一个进程打开了那些文件
[root@master30 data]# vim a.txt 
ldsfjksdl
sjldfjsl
sdlfkjsldf


#打开另外一个终端
[root@master30 ~]# ps -aux | grep vim
root       1216  0.2  0.5 149596  5348 pts/0    S+   08:28   0:00 vim a.txt
root       1264  0.0  0.0 112676   980 pts/1    R+   08:29   0:00 grep --color=auto vim

#查看打开的文件
[root@master30 ~]# ls -l /proc/1216/fd
总用量 0
lrwx------ 1 root root 64 8月   7 08:30 0 -> /dev/pts/0
lrwx------ 1 root root 64 8月   7 08:30 1 -> /dev/pts/0
lrwx------ 1 root root 64 8月   7 08:29 2 -> /dev/pts/0
lrwx------ 1 root root 64 8月   7 08:30 4 -> /data/.a.txt.swp

注: 这些0,1,2,4就是文件的描述符。一个进程启动时,都会打开 3 个文件:标准输入、标准输出和标准出错处理

#/proc目录/进程/fd-->用于存放文件描述符

一个进程可以打开多少个文件?

这里就会涉及一个调优的常用:ulimit

其实就是调整文件描述符

[root@master30 ~]# ulimit -n
1024
#临时调整文件描述符
[root@master30 ~]# ulimit -n 2048
[root@master30 ~]# ulimit -n 
2048

2、重定向的讲解

输出重定向
  • 将命令的正确输出结果保存到指定的文件中,而不是直接显示在显示屏幕上;
  • 重定向输出使用“>”“>>”操作符号

语法:

  • “> +文件名”:表示将标准输出的内容,写到后面的文件中,如果此文件名已经存在,将会覆盖原文件中的内容
  • “>> +文件名”:表示将标准输出的内容,追加到后面的文件中。若重定向的输出的文件不存在,则会新建该文件
#修改输出的信息
[root@Node0 data]# cat /proc/cpuinfo > a.txt
[root@Node0 data]# cat a.txt 

#追加:
[root@Node0 data]# uname -a >> a.txt 

#清空文件
[root@Node0 data]# > a.txt
输入重定向
[root@Node0 data]# grep "root" /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@Node0 data]# grep "root" < /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin

EOFj结尾

格式:cat >> 文件名 << EOF

在文件名里面输入内容,直到遇到EOF才会停止并且推出,是个分界符;

[root@Node0 data]# cat >> a.txt <<EOF
> MY NAME is liangjiawei
> hello
> EOF

#在使用脚本中,使用“<<”结束
[root@Node0 data]# vim a.txt
MY NAME is liangjiawei
#!/bin/bash
cat <<EOF
==========================
1.NGINX
2.MYSQL
3.PHP
==========================
EOF
[root@Node0 data]# sh a.txt 
==========================
1.NGINX
2.MYSQL
3.PHP
==========================
错误重定向

将命令执行过程中出现的错误信息保存到指定的文件,不显示到屏幕

作用:错误信息保存到文件

操作符:错误重定向符号:“2>”或者“2>>”

2指的是标准错误输出的文件描述符 (在使用标准的输入和输出省略了1、0 编号)

使用 2> 操作符时,会像使用 > 一样覆盖目标文件的内容,若追加而不覆盖文件的内容即可使用 2>> 操作符

#错误的指令显示到屏幕
[root@Node0 data]# cat a.txt xxx
#!/bin/bash
cat <<EOF
==========================
1.NGINX
2.MYSQL
3.PHP
==========================
EOF
cat: xxx: 没有那个文件或目录

#屏蔽错误的信息
[root@Node0 data]# ls a.txt xxx 2> b.txt
a.txt
[root@Node0 data]# cat b.txt 
ls: 无法访问xxx: 没有那个文件或目录
黑洞null和zero空文件

/etc/null:linux中的黑洞文件,写什么给它都它都会丢失

/etc/zero:linux中的特殊文件,它会提供无限的空字符;

#你写什么进去,然后什么都没有
[root@Node0 data]# echo lala >> /dev/null 
[root@Node0 data]# cat /dev/null
dd命令

作用:产生一个指定大小的文件

语法:dd+if=/dev/zero of=b.txt bs=1M count=50

语法:

  • if 代表输入文件。如果不指定if,默认就会从stdin中读取输入。
  • of 代表输出文件。如果不指定of,默认就会将stdout作为默认输出。
  • bs 代表字节为单位的块大小。
  • count 代表被复制的块数。
[root@Node0 data]# dd if=/dev/zero of=lala.txt bs=1M count=10
记录了10+0 的读入
记录了10+0 的写出
10485760字节(10 MB)已复制,0.0388636 秒,270 MB/秒
[root@Node0 data]# du -sh lala.txt 
10M	lala.txt
“&>”和“>&”符号

1>&2 把标准输出重定向到标准错误

2>&1 把标准错误重定向到标准输出

#不管是正式的还是错误的都是指向ok.txt
 [root@Node0 data]# ls /tmp/ xxx >ok.txt 2>&1
[root@Node0 data]# cat ko.txt 
ls: 无法访问haha: 没有那个文件或目录
/root/:
anaconda-ks.cfg

#将标准输出和错误输出信息都重定向,丢弃所有的屏幕信息
[root@Node0 data]# cat /etc/passwd > /dev/null 2>&1

3、管道|

语法:命令A|命令B|命令C

注意事项:

  • 管道只处理前一个命令正确输出,不处理错误输出
  • 管道符右边的命令,必须能够接受标准输入的数据流命令才行
  • 管道可以把两条命令连起来,可以接多个命令使用
[root@Node0 data]# ps -aux | grep sshd
root       7145  0.0  0.2 112756  4320 ?        Ss   06:08   0:00 /usr/sbin/sshd -D
root       7404  0.0  0.2 161364  6048 ?        Ss   06:09   0:00 sshd: root@pts/0
root       7533  0.0  0.0 112724   984 pts/0    R+   06:57   0:00 grep --color=auto sshd

[root@Node0 data]# ls xxx | grep ok
ls: 无法访问xxx: 没有那个文件或目录
tee命令

作用:读取标准输入的数据,并将内容输出成文件

语法:tee + 选项+文件名

选项:

  • -a:把内容追加
  • –help:在线帮助
[root@Node0 data]# ls | tee log.txt
a.txt
b.txt
ko.txt
lala.txt
ok.txt
[root@Node0 data]# cat log.txt 
a.txt
b.txt
ko.txt
lala.txt
ok.txt

#追加
[root@Node0 data]# ls /tmp/ | tee -a log.txt 
ks-script-SzW0Mu
vmware-root_5971-1689656024
vmware-root_5990-700614315
vmware-root_6027-1690049126
yum.log
[root@Node0 data]# cat log.txt

4、查找相关命令

which命令

作用:查看可执行文件的位置

语法:which+命令

[root@Node0 data]# which ls
alias ls='ls --color=auto'
	/usr/bin/ls
whereis命令

作用:查看可执行文件的位置以及相关文件

语法:whereis+命令

[root@Node0 data]# whereis  ls
ls: /usr/bin/ls /usr/share/man/man1/ls.1.gz
locate命令

作用:快速查看文件的位置

语法:locate+文件名

注意:是根据本地数据库缓存来查找的,需要更新数据库

#查找文件
[root@Node0 data]# locate fstab

#我这重新创建文件,然后重新查找就无法查找到刚创建的文件,
[root@Node0 data]# mkdir haha
[root@Node0 data]# locate haha
[root@Node0 data]# 

#需要更新数据库之后就能够查找
[root@Node0 data]# updatedb
[root@Node0 data]# locate haha
/data/haha

#数据库的位置在
/var/lib/mlocate/mlocate.db 
	#这里文件指定了locate命令的搜索范围
[root@Node0 data]# cat /etc/updatedb.conf 
PRUNE_BIND_MOUNTS = "yes"
PRUNEFS = "9p afs anon_inodefs auto autofs bdev binfmt_misc cgroup cifs coda configfs cpuset debugfs devpts ecryptfs exofs fuse fuse.sshfs fusectl gfs gfs2 gpfs hugetlbfs inotifyfs iso9660 jffs2 lustre mqueue ncpfs nfs nfs4 nfsd pipefs proc ramfs rootfs rpc_pipefs securityfs selinuxfs sfs sockfs sysfs tmpfs ubifs udf usbfs fuse.glusterfs ceph fuse.ceph"
PRUNENAMES = ".git .hg .svn"
PRUNEPATHS = "/afs /media /mnt /net /sfs /tmp /udev /var/cache/ccache /var/lib/yum/yumdb /var/spool/cups /var/spool/squid /var/tmp /var/lib/ceph"
grep命令

这个命令很重要,经常使用到;

作用:过滤匹配,它是一个文件搜索工具,可以支持正则表达式来查找文件

语法:grep+选项+文件名

选项:

  • -v:取反
  • -i:忽略大小写
  • 正则:
  • ^#:以#开头的
  • “”#$“:以#结尾的
  • “^$”:表示匹配空行
  • -n:表示对过滤的内容佳航行号
  • |:逻辑或的意思
#查找passwd文件中以bash结尾的文件
[root@Node0 ~]# grep bash$ /etc/passwd
root:x:0:0:root:/root:/bin/bash
liangjiawei:x:1000:1000:liangjiawei:/home/liangjiawei:/bin/bash

#查找进程
[root@Node0 ~]# ps -aux | grep sshd | grep -v grep
root       7142  0.0  0.2 112756  4320 ?        Ss   07:57   0:00 /usr/sbin/sshd -D
root       7400  0.1  0.2 161364  6060 ?        Ss   08:00   0:00 sshd: root@pts/0

#查找两个条件
[root@Node0 ~]# grep "bash$\|root " /etc/passwd
root:x:0:0:root:/root:/bin/bash
liangjiawei:x:1000:1000:liangjiawei:/home/liangjiawei:/bin/bash
	#\这个表示转义符

#egrep是它的升级版;
[root@Node0 data]# egrep "nologin|root" /etc/passwd | wc -l
17
find命令

这个命令也是十分重要

作用:查找系统下的文件

语法:find + 路径+选项+条件

选项:

  • -name:按照文件名来查找,支持通配
  • -perm:按照权限来找文件,666或者777
  • 666:按照666的权限查找
  • -644:按照起码是644的权限
  • -user:按照所有者来查找文件
  • -group:按照文件的所属组来查找文件
  • -mtime:按照文件最后一次修改的时间来查找
  • -n:多少天以内
  • n:刚好多少天修改过的文件
  • +n:多少天以前修改过的文件
  • -atime:按照最后一次访问的时间来查找
  • ctime:文件的最后一次变化时间,修改时间来查找
  • -type:按照文件的类型来查找文件
  • f:文件
  • d:目录
  • l:链接文件
  • c:字符设备文件
  • p:管道文件
  • b:块设备文件
  • -a:并且
  • -o:或者
  • -size:按照文件的大小来查找
  • +n:大于多少m
  • -n:小于多少
  • n:刚好文件等于多少
  • -exec:固定格式,把查找出来的内容应该做什么操作操作
  • -exec 命令 {} \;(注意:{} 和;有个空格)
  • {}:代表查找出来的内容
  • -maxdepth:按照目录的深度来查找
#查找log结尾的文件
[root@Node0 data]# find /var/ -name "*.log"

#查找前三天访问过的文件
[root@Node0 data]# find /root -atime +3 
/root/.bash_logout
/root/.cshrc
/root/.tcshrc


#查找前天修改过的文件并且删除
[root@Node0 data]# find /data/ -mtime +1 -exec rm -rf {} \;

#结合xargs来使用
[root@Node0 data]# find /data/ -name "*.txt" | xargs rm -rf


#按照文件内容来查找
[root@Node0 data]# find /data/ -type d  -a -ctime -1 -exec rm -rf {} \;

#按照所有者来匹配
[root@Node0 data]# find /home -user zhangsan
[root@Node0 data]# find /  -maxdepth 2 -user zhangsan
/home/zhangsan

5、命令判断

分号;

作用:前面的命令和后面的命令没有相关性,连续执行,不会保证所有命令都是执行成功的

[root@Node0 ~]# ls /data ; date
ls: 无法访问/data: 没有那个文件或目录
2021年 08月 31日 星期二 08:04:15 CST
逻辑与&&

作用:前面执行成功的命令,后面才会继续执行

[root@Node0 ~]# ls /root && date
2021年 08月 31日 星期二 08:05:05 CST
[root@Node0 ~]# ls /data && date
ls: 无法访问/data: 没有那个文件或目录
逻辑或||

作用: 如果前面命令执行不成功,后面的命令才会执行,或者前面执行成功了,后面就不会执行

[root@Node0 ~]# ls /root/ || date
[root@Node0 ~]# ls /data/ || date
ls: 无法访问/data/: 没有那个文件或目录
2021年 08月 31日 星期二 08:08:23 CST

判断一个文件是否存在,存在则不创建,不存在就创建该文件

[root@Node0 ~]# cd /data/ && echo "exit" || mkdir /data/ -p
-bash: cd: /data/: 没有那个文件或目录
[root@Node0 data]# cd /data/ && echo "exit" || mkdir /data/ -p
exit