2023-05-21    2023-12-23    7660 字  16 分钟

本章节,我们将认识 Linux 系统中常用的文件操作相关命令。

路径切换

我们可以通过cd 命令切换目录。

cd命令常用的参数如下:

命令 解释
cd ~ 切换回当前用户的家目录,注意:root和普通用户有所不同。
cd . 代表当前目录,一般在拷贝、移动等情况下使用,如:cp /etc/hostname ./
cd .. 切换回当前目录的上级目录。
cd - 切换回上一次所在的目录。

例:

进入/etc/sysconfig/network-scripts/目录。

1
[root@localhost ~]# cd /etc/sysconfig/network-scripts/

回到家目录。

1
2
3
[root@localhost network-scripts]# cd
[root@localhost network-scripts]# cd ~

回到上次所在的目录。

1
2
[root@localhost ~]# cd -
/etc/sysconfig/network-scripts

回到上级目录。

1
[root@localhost ~]# cd ..

文件路径是指用来标识文件中数据位置的字符串,路径包文件所在的位置以文件名称,比如: /etc/hostname

绝对路径:只要是以/开始的命令都算绝对路径。例如:

1
[root@localhost ~]# ls /etc/sysconfig/network-scripts/ifcfg-ens32

相对路径:相对于当前目录的路径。例如:

1
[root@localhost sysconfig]# cat network-scripts/ifcfg-ens32 

文件操作

文件操作主要包括文件的创建、复制、移动、删除等。

mkdir命令

mkdir命令用于创建目录。以下mkdir常用参数及说明:

选项 解释
-p 递归创建目录。

创建一个名称为snoopy目录。

1
[root@localhost ~]# mkdir snoopy

同时创建多个目录。

1
[root@localhost ~]# mkdir snoopy1 snoopy2 snoopy3

创建snoopy-1snoopy-50的目录。

1
[root@localhost ~]# mkdir snoopy-{1..50}

递归创建目录。

1
[root@localhost ~]# mkdir -p /opt/nginx/log

利用{ }灵活创建目录。

1
2
3
[root@localhost ~]# mkdir /opt/nginx/{conf,cert,bin} 
[root@localhost ~]# ls /opt/nginx/
cert  conf  iplist.txt  log

touch命令

touch命令用于创建一个文件。如:创建一个名为test.txt的文件。

1
[root@localhost ~]# touch test.txt

mv命令

Linux中,移动文件和对文件重命名都是通过mv命令实现的。

test.txt移动到snoopy-1目录中。

1
[root@localhost ~]# mv test.txt snoopy-1/

dir-1中的test.txt移动到snoopy-2目录下,并重命名为test2.txt

1
[root@localhost ~]# mv snoopy-1/test.txt snoopy-2/test2.txt

test2.txt重命名为test3.txt

1
[root@localhost dir-2]# mv test2.txt test3.txt

snoopy-1snoopy-2snoopy-3 移动到 snoopy-4 中。

1
2
3
[root@localhost ~]# mv snoopy-1 snoopy-2 snoopy-3 snoopy-4
[root@localhost ~]# ls snoopy-4
snoopy-1  snoopy-2  snoopy-3

rm命令

我们可以通过rm命令删除文件或者目录,rm命令常用的选项如下:

选项 解释
-f 强制删除,没有提示。
-r 递归删除,删除目录时必须加r。

强制删除test3.txt

1
[root@localhost snoopy-2]# rm -f test3.txt

删除目录

1
2
3
4
5
6
# 不加-r选项,删除失败
[root@localhost snoopy-4]# rm snoopy-1/
rm: cannot remove ‘snoopy-1/’: Is a directory

[root@localhost snoopy-4]# rm -r snoopy-1/
rm: remove directory ‘snoopy-1/’? y

删除所有以snoopy-开头的目录

1
[root@localhost ~]# rm -rf snoopy-*

cp命令

我们可以通过cp命令实现文件或目录的复制,cp常用的选项如下表:

选项 解释
-r 递归拷贝,拷贝目录时必须加r。
-v 显示拷贝详细信息。
-p 保持文件原有的属性,不发生变化。

file拷贝到/tmp下,并重命名为file_copy

1
2
3
4
[root@localhost ~]# cp file /tmp/file_copy
[root@localhost ~]# ll /tmp/
total 0
-rw-r--r--. 1 root root 0 Jul 29 10:34 file_copy

递归拷贝。

1
[root@localhost ~]# cp -rv /etc/ ./

/etcoptfile复制到/mnt目录下。

1
2
3
[root@localhost ~]# cp -rf /etc/ /opt/ file  /mnt/
[root@localhost ~]# ls /mnt/
etc  file  opt

-p参数用于保持在复制过程中,文件的原有属性不变。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
[root@localhost ~]# ll
total 0
# 文件权限为rw-r--r--
-rw-r--r--.  1 root root    0 Nov  6 23:02 file

# 更改文件的权限
[root@localhost ~]# chmod  777 file 
# 更改文件的所属关系
[root@localhost ~]# chown adm:adm file 
[root@localhost ~]# ll
total 0
# 修改后的文件属性
-rwxrwxrwx.  1 adm  adm     0 Nov  6 23:02 file

# 将文件复制到/tmp目录下
[root@localhost ~]# cp file  /tmp/
# 保持文件的原有属性不变,复制文件到/tmp下,并重命名为file1
[root@localhost ~]# cp -p file /tmp/file1

[root@localhost ~]# ll /opt
total 0
# 不加-p参数,复制过程中,文件属性发生了变化
-rwxr-xr-x. 1 root root   0 Nov  6 23:06 file
# 加上-p参数,复制过程中,文件的属性不发生改变
-rwxrwxrwx. 1 adm  adm    0 Nov  6 23:02 file1

我们也可以通过{ }去复制文件。

test.txt复制一份test.txt.bak-v显示复制过程。

1
2
[root@localhost ~]# cp {test.txt,test.txt.bak} -v
‘test.txt’ -> ‘test.txt.bak’

ifcfg-ens32复制一份,命名为ifcfg-ens32.bak

1
2
3
4
[root@localhost ~]# cp /etc/sysconfig/network-scripts/{ifcfg-ens32,ifcfg-ens32.bak}
[root@localhost ~]# ls /etc/sysconfig/network-scripts/ifcfg-e*
/etc/sysconfig/network-scripts/ifcfg-ens32
/etc/sysconfig/network-scripts/ifcfg-ens32.bak

查看与过滤

cat命令

我们可以通过cat命令查看文件全部内容,常用的选项如下表:

选项 解释
-n 查看文件时,显示行号。
-A 查看文件时,显示特殊字符。

查看pass文件内容。

1
2
3
4
5
[root@localhost ~]# cat passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
test17:x:1016:1016::/home/test17:/bin/bash

查看pass文件内容并显示行号。

1
2
3
4
5
[root@localhost ~]# cat -n passwd
1	root:x:0:0:root:/root:/bin/bash
2	bin:x:1:1:bin:/bin:/sbin/nologin
3	daemon:x:2:2:daemon:/sbin:/sbin/nologin
4	test17:x:1016:1016::/home/test17:/bin/bash

查看pass文件内容并显示特殊字符。

1
2
3
4
5
6
[root@localhost ~]# cat -A passwd
# 行尾$表示换行
root:x:0:0:root:/root:/bin/bash$
bin:x:1:1:bin:/bin:/sbin/nologin$
daemon:x:2:2:daemon:/sbin:/sbin/nologin$
adm:x:3:4:adm:/var/adm:/sbin/nologin$

cat创建一个文件,并写入内容。

1
2
3
4
5
6
7
8
9
[root@localhost ~]# cat >> test.txt <<EOF
TEST1
TEST2
TEST3
EOF
[root@localhost ~]# cat test.txt
TEST1
TEST2
TEST3

less命令

翻页查看文件内容,可通过方向/空格/回车键翻页。

1
[root@localhost ~]# less /etc/services

more命令

翻页查看文件内容,可通过空格/回车键翻页,并显示百分比。

1
[root@localhost ~]# more /etc/services

head命令

head命令用于打印前n行,常用的选项如下表:

选项 解释
-n 打印的行数。

使用head命令,不加任何参数,默认只打印前十行的内容。

打印pass前3行内容,等同于head -n 3 pass

1
2
3
4
[root@localhost ~]# head -3 pass 
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin

tail命令

tail命令用于显示文本的末尾几行,常用的选项如下表:

选项 解释
-n 打印的行数。
-f 查看文件尾部新追加的内容。

tail默认打印文本的末尾10行,若需指定打印行数,可以通过-n实现,如打印文件的后3行内容。

1
2
3
4
[root@localhost ~]# tail -3 passwd
polkitd:x:999:998:User for polkitd:/:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin

使用tail -f可以查看文件尾部的变化。

1
2
3
4
5
[root@localhost ~]# tail -f /var/log/secure
# 等同于 tailf /var/log/secure
Jul 29 14:05:54 localhost sshd[8613]: error: Received disconnect from 10.0.0.1 port 61962:0:
Jul 29 14:05:54 localhost sshd[8613]: Disconnected from 10.0.0.1 port 61962
Jul 29 14:05:54 localhost sshd[8613]: pam_unix(sshd:session): session closed for user root

grep命令

我们可以通过grep命令对文本进行过滤,常用的选项如下表:

选项 解释
-n 显示行符。
-v 反转查找。
-i 不区分大小写过滤文件。
-E 多条件过滤。
-A 匹配后,再向下打印。
-B 匹配后,再向上打印。

过滤文件常用的符号。

选项 解释
^ 表示以什么开头。
$ 表示以什么结尾。
^$ 表示空行。

过滤文中含有root的相关的行。

1
2
3
[root@localhost ~]# grep "root" passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin

过滤以root开头的行。

1
2
[root@localhost ~]# grep "^root" passwd
root:x:0:0:root:/root:/bin/bash

过滤以bash结尾的行。

1
2
[root@localhost ~]# grep "bash$" passwd
root:x:0:0:root:/root:/bin/bash

过滤并显示行符。

1
2
[root@localhost ~]# grep -n "bash" passwd
1:root:x:0:0:root:/root:/bin/bash

使用grep匹配后,再向下打印,如匹配到root后在向下打印两行。

1
2
3
4
5
6
7
8
[root@localhost ~]# grep -n -A 2 "root" passwd
1:root:x:0:0:root:/root:/bin/bash
2-bin:x:1:1:bin:/bin:/sbin/nologin
3-daemon:x:2:2:daemon:/sbin:/sbin/nologin
--
10:operator:x:11:0:operator:/root:/sbin/nologin
11-games:x:12:100:games:/usr/games:/sbin/nologin
12-ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin

使用grep匹配后,再向上打印,如匹配到root后,再向上打印两行。

1
2
3
4
5
6
[root@localhost ~]# grep -n -B 2 "root" passwd
1:root:x:0:0:root:/root:/bin/bash
--
8-halt:x:7:0:halt:/sbin:/sbin/halt
9-mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
10:operator:x:11:0:operator:/root:/sbin/nologin

使用grep匹配后,再向上和向下打印,如匹配到root后,再向上和向下各打印两行。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
[root@localhost ~]# grep -n -C 2 "root" passwd
1:root:x:0:0:root:/root:/bin/bash
2-bin:x:1:1:bin:/bin:/sbin/nologin
3-daemon:x:2:2:daemon:/sbin:/sbin/nologin
--
8-halt:x:7:0:halt:/sbin:/sbin/halt
9-mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
10:operator:x:11:0:operator:/root:/sbin/nologin
11-games:x:12:100:games:/usr/games:/sbin/nologin
12-ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin

筛选出不含ftp的行。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
[root@localhost ~]# grep -v "ftp" passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
polkitd:x:999:998:User forf polkitd:/:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin

不区分大小写过滤出含ftp的行。

1
2
[root@localhost ~]# grep -i "ftp" passwd
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin

不区分大小写的打印出以sync结尾或者包含ftp的行。

1
2
3
[root@localhost ~]# grep -Ei "sync$|ftp" /etc/passwd
sync:x:5:0:sync:/sbin:/bin/sync
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin

下载与上传

wget命令

wget是一个从网络上自动下载文件的工具,若系统为最小化安装,需要先安装wget命令。

1
[root@localhost ~]# yum install wget -y

wget常用参数如下:

选项 说明
-O 下载文件到指定目录。

wget下载http://mirrors.aliyun.com/repo/Centos-7.repo到当前目录。

1
2
3
4
5
6
[root@localhost ~]# wget http://mirrors.aliyun.com/repo/Centos-7.repo
......
100%[=========================================>] 2,523       --.-K/s   in 0s      

[root@localhost ~]# ll
-rw-r--r--. 1 root root 2523 Jun 16  2018 Centos-7.repo

将下载http://mirrors.aliyun.com/repo/Centos-7.repo/mnt目录下,保持文件名称不变。

1
2
3
4
5
6
7
8
[root@localhost ~]# wget -O /mnt/Centos-7.repo http://mirrors.aliyun.com/repo/Centos-7.repo
# 若想保持文件名称不变 ,在下载路径中要指定原名,否则不能下载成功
......
100%[=========================================>] 2,523       --.-K/s   in 0s      

[root@localhost ~]# ll /mnt/
total 4
-rw-r--r--. 1 root root 2523 Jun 16  2018 Centos-7.repo

将下载http://mirrors.aliyun.com/repo/Centos-7.repo/mnt目录下,并重命名为test.txt

1
2
3
4
5
6
7
[root@localhost ~]#  wget -O  /mnt/test.txt http://mirrors.aliyun.com/repo/Centos-7.repo
......
100%[=========================================>] 2,523       --.-K/s   in 0s      

[root@localhost ~]# ll /mnt
total 4
-rw-r--r--. 1 root root 2523 Jun 16  2018 test.txt

curl命令

curl命令是一个用于发送HTTP请求的命令行工具,可以用于获取、上传、发送各种类型的HTTP请求。常用参数如下:

选项 说明
-I 获取HTTP响应头
-o 下载文件到指定目。

curl查看http://mirrors.aliyun.com/repo/Centos-7.repo内容。

1
2
3
4
5
6
7
8
9
[root@localhost ~]# curl http://mirrors.aliyun.com/repo/Centos-7.repo
[base]
name=CentOS-$releasever - Base - mirrors.aliyun.com
failovermethod=priority
baseurl=http://mirrors.aliyun.com/centos/$releasever/os/$basearch/
        http://mirrors.aliyuncs.com/centos/$releasever/os/$basearch/
        http://mirrors.cloud.aliyuncs.com/centos/$releasever/os/$basearch/
gpgcheck=1
gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7

访问http://mirrors.aliyun.com/repo/Centos-7.repo,获取请求头信息。

1
2
3
4
5
6
7
8
9
[root@localhost ~]# curl -I http://mirrors.aliyun.com/repo/Centos-7.repo
HTTP/1.1 200 OK
Server: Tengine
Content-Type: application/octet-stream
Content-Length: 2523
Connection: keep-alive
Date: Sat, 18 Nov 2023 14:34:02 GMT
Expires: Sat, 18 Nov 2023 14:37:02 GMT
......

curl下载http://mirrors.aliyun.com/repo/Centos-7.repo并保存到/mnt下,并重命名为test.txt

1
2
3
4
5
6
7
[root@localhost ~]# curl -o /mnt/test.txt http://mirrors.aliyun.com/repo/Centos-7.repo
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  2523  100  2523    0     0  18920      0 --:--:-- --:--:-- --:--:-- 18969
[root@localhost ~]# ll /mnt/
total 4
-rw-r--r--. 1 root root 2523 Jul 30 09:58 test.txt

通常情况下,下载文件使用wget命令,但是最小化安装系统默认不安装wget,可以使用curl下载。

rz sz命令

rz命令

lrzsz是一个在Linux系统中进行文件传输的工具集合,由rzsz两个命令组成,主要作用是通过终端在本地系统和远程系统之间进行文件传输,特别适用于与远程服务器进行文件交互。安装命令如下:

1
[root@localhost ~]# yum install lrzsz

rz用于从本地电脑上传文件至Linux服务器上。只能上传文件,不支持上传文件夹和断点续传。且不支持上传大于4G的文件,若上传超过4G的文件,需要通过其他方式实现。

终端直接执行rz命令即可。

sz命令

sz用于从Linux服务器上下载文件至Windows上,不支持下载文件夹。其格式为sz + 文件名称,如

1
[root@localhost ~]# sz /etc/passwd

查看文件类型

ls命令

我们可通过ls命令查看文件属性。

1
2
3
4
5
6
7
8
[root@localhost ~]# ll -d /etc/hosts /tmp /bin/ls /dev/sda /dev/tty1 /etc/grub2.cfg /dev/log
-rwxr-xr-x. 1 root root 117608 Aug 20  2019 /bin/ls
srw-rw-rw-. 1 root root      0 Nov  5 23:06 /dev/log
brw-rw----. 1 root disk   8, 0 Nov  5 23:06 /dev/sda
crw--w----. 1 root tty    4, 1 Nov  6 22:16 /dev/tty1
lrwxrwxrwx. 1 root root     22 Nov  5 23:03 /etc/grub2.cfg -> ../boot/grub2/grub.cfg
-rw-r--r--. 1 root root    158 Jun  7  2013 /etc/hosts
drwxrwxrwt. 7 root root    132 Nov  6 22:26 /tmp

各列输出含义

第一列:文件的类型和权限。

第二列:对于目录文件,表示它的第一级子目录的个数。此处看到的值要减2才等于该目录下的子目录的实际个数,因为这个数值统计了...目录。对于其他文件,表示指向它的链接文件的个数。

第三四列:所有者及组。

第五列:对于文件,则表示该文件的大小,单位为字节。对于目录,则表示该目录符所占的大小,并不表示该目录下所有文件的大小。

第六-八列:该文件最后修改的日期时间。

第九列:文件名称。

文件颜色含义:

  • 灰白色表示普通文件。
  • 亮绿色表示可执行文件。
  • 亮红色表示压缩文件。
  • 灰蓝色表示目录。
  • 亮蓝色表示链接文件。
  • 亮黄色表示设备文件。

第一列srw-rw-rw-首个字符表示文件的类型。

字符 说明
- 文件。
d 目录,类似于Windows的文件夹。
l 链接文件,类似于Windows的快捷方式。
s socket,套接字文件,可实现进程间的通信。
b block块设备文件,例如光盘、硬盘、分区等。
c 字符设备,用于提供用户的输入和输出。

file命令

file命令是一个用于查看文件类型的命令,它可以检测文件的类型,并显示该文件的信息。

查看文件的类型。

1
2
3
4
5
[root@localhost ~]# file anaconda-ks.cfg  tp.jpeg test.zip  process_exporter_install.sh
anaconda-ks.cfg:             ASCII text
tp.jpeg:                     JPEG image data, JFIF standard 1.01
test.zip:                    Zip archive data, at least v2.0 to extract
process_exporter_install.sh: Bourne-Again shell script, UTF-8 Unicode text executable

硬链接和软链接

Linux系统中,我们可以把一个文件看做文件名、文件内容和描述信息三个部分组成。

文件名:从用户角度来描述一个文件。

文件内容:文件中存储的数据,系统会从硬盘上划分一块区域,用来存放文件本身的内容(数据),这块区域按照一个最小单位块(block)来进行划分。

描述信息:文件的类型、所有者、创建时间等等,也称之为元信息。每一个文件的描述信息,都用一个名为索引节点(inode)的数据结构来表示。

一个文件的索引节点(inode)中,除了记录了这个文件的所有描述信息,包括:文件类型、所有者、创建时间等,当然也记录了文件内容存储在硬盘的哪些块(block)中。

当我们打开文件时候,操作系统首先根据传入的文件路径,找到这个文件的inode,然后进行一系列的权限检查操作,最后从inode中获得这个文件的内容存储在哪些块(block)中,从而可以对文件的内容进行读取、写入操作。 当我们创建一个新文件的时候,就同时创建了这个文件对应的inode节点。 当我们删除一个文件的时候,就同时删除了这个文件对应的inode节点。文件本身内容所在的那个块中,数据并不会被抹除掉,因此有些数据恢复软件就是利用这个特点来进行数据找回。

硬链接

多个文件名同时指向同一个索引节点(Inode),就是硬链接inode通过links字段表示指inode的硬链接数量,当links0时,操纵系统就会把这个 inode 删除了,于是这个文件就彻底不存在了。

硬链接

我们可以通过ln命令创建连接。

准备一个测试文件,此时links1

1
2
[root@localhost ~]# cat a.txt
snoopyops.top

创建硬链接,此时links2

1
[root@localhost ~]# ln a.txt a_hard_link.txt

查看文件,这两个文件就如同一个文件一样,inode 值相同,都指向同一个区块。

1
2
3
[root@localhost ~]# ll -i
100682319 -rw-r--r--. 2 root    root          8 5月  23 14:59 a_hard_link.txt
100682319 -rw-r--r--. 2 root    root          8 5月  23 14:59 a.txt

修改文件内容,两个文件均发生变化。

1
2
3
4
[root@localhost ~]# echo "New line" >> a_hard_link.txt
[root@localhost ~]# cat a.txt
snoopyops.top
New line

删除源文件后,此时links变为1,通过硬链接的文件名依然可以找到数据。

1
2
3
4
[root@localhost ~]# rm a.txt
[root@localhost ~]# cat a_hard_link.txt
snoopyops.top
New line

硬链接作用

该机制可以有效的防止误删操作。

硬链接的限制

  • 不允许用户给目录创建硬链接,但操作系统可以(比如...)。

  • 只有在同一个文件系统中的文件,才能创建硬链接,也就是说:不能跨文件系统。

软链接

相当于Windows中的快捷方式。通过ln命令和-s选项,可实现软链接的创建。

软链接文件的内容是一个文本字符串,存储的是目标文件(即:链接到的文件)的路径名。这个路径名可以指向任意一个文件系统的任意文件或者目录,甚至可以指向一个不存在的文件。

与创建硬链接不同的是:当我们创建了一个软链接之后,操作系统会创建一个新的inode来表示这个软链接文件。

软链接

准备一个测试文件。

1
2
[root@localhost ~]# cat a.txt
snoopyops.top

创建软链接。

1
[root@localhost ~]# ln -s a.txt a_soft_link.txt

查看文件,inode 值不同,指向不同的区块。

[root@localhost ~]# ll -i
100682318 lrwxrwxrwx. 1 root    root          8 5月  23 15:11 ta_soft_link.txt -> a.txt
100682319 -rw-r--r--. 1 root    root          8 5月  23 15:09 a.txt

修改软链接文件时,操作系统就根据其中的路径信息,找到 a.txtinode 节点,从而对最终的目标文件进行操作。

[root@localhost ~]# echo "New line" >> a_soft_link.txt
[root@localhost ~]# cat a.txt
snoopyops.top
New line

删除源文件后,软链接失效。

1
2
3
[root@localhost ~]# rm a.txt
[root@localhost ~]# cat a_soft_link.txt
cat: a_soft_link.txt: No such file or directory

软链接应用场景

  1. 软件升级与回退。

    下载并解压openjdk

    1
    2
    
    [root@localhost opt]# wget https://repo.huaweicloud.com/openjdk/18/openjdk-18_linux-x64_bin.tar.gz
    [root@localhost opt]# tar xf openjdk-18_linux-x64_bin.tar.gz
    

    创建软链接。

    1
    2
    3
    
    [root@localhost opt]# ln -s /opt/jdk-18/bin/java /usr/local/bin/java
    [root@localhost opt]# ll /usr/local/bin/java
    lrwxrwxrwx. 1 root root 20 Nov  7 04:08 /usr/local/bin/java -> /opt/jdk-18/bin/java
    

    查看版本信息。

    1
    2
    3
    4
    
    [root@localhost opt]# java -version
    openjdk version "18" 2022-03-22
    OpenJDK Runtime Environment (build 18+36-2087)
    OpenJDK 64-Bit Server VM (build 18+36-2087, mixed mode, sharing)
    

    升级openjdk

    下载并解压新版本openjdk

    1
    2
    
    [root@localhost opt]# wget https://repo.huaweicloud.com/openjdk/19/openjdk-19_linux-x64_bin.tar.gz
    [root@localhost opt]# tar xf openjdk-19_linux-x64_bin.tar.gz
    

    删除原软链接,并新建软链接,指向新版本的openjdk

    1
    
    [root@localhost opt]# rm -f /usr/local/bin/java && ln -s /opt/jdk-19/bin/java /usr/local/bin/java
    

    查看版本信息。

    1
    2
    3
    4
    
    [root@localhost opt]# java -version
    openjdk version "19" 2022-09-20
    OpenJDK Runtime Environment (build 19+36-2238)
    OpenJDK 64-Bit Server VM (build 19+36-2238, mixed mode, sharing)
    

    版本回退。

    1
    2
    3
    4
    5
    
    [root@localhost opt]# rm -f /usr/local/bin/java && ln -s /opt/jdk-18/bin/java /usr/local/bin/java
    [root@localhost opt]# java -version
    openjdk version "18" 2022-03-22
    OpenJDK Runtime Environment (build 18+36-2087)
    OpenJDK 64-Bit Server VM (build 18+36-2087, mixed mode, sharing)
    
  2. 代码上线与回退。

  3. 移动文件而不改变路径,常用于磁盘容量不足,且大文件路径无法更改的情况。

软链接和硬链接的区别

  1. ln命令创建硬链接,ln -s命令创建软链接。
  2. 目录不能创建硬链接,并且硬链接不可以跨越分区系统。
  3. 目录软链接特别常用,并且软链接支持跨越分区系统。
  4. 硬链接文件与源文件inode相同,软链接文件与源文件inode不同。
  5. 删除硬链接的源文件,对硬链接无任何影响。
  6. 删除软链接的源文件,会导致软链接失效。

命令查找

PATH变量是一个环境变量,它告诉操作系统在哪里可以找到可执行文件。当您在命令行中输入命令时,操作系统会在PATH变量指定的目录中查找可执行文件。

PATH变量由一系列目录组成,每个目录之间用冒号(:)分隔。这些目录是系统默认的,也可以根据需要进行修改。

Linux中,我们可以通过以下命令查看PATH变量。

1
2
[root@localhost ~]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin

那么我们如何才能知道我们执行的命令在哪个目录里呢?

which命令

which可用于查看命令文件的绝对路径及别名。

1
2
3
[root@localhost ~]# which ls
alias ls='ls --color=auto'
	/usr/bin/ls

whereis命令

whereis可用于查看命令的文件的绝对路径及帮助文档路径。

1
2
[root@localhost ~]# whereis ls
ls: /usr/bin/ls /usr/share/man/man1/ls.1.gz

type命令

type命令是Linux系统的一种机制,用来显示指定命令的类型。

1
2
3
4
5
6
7
8
[root@localhost ~]# type ls
ls is aliased to `ls --color=auto'
[root@localhost ~]# type wget
wget is /usr/bin/wget
[root@localhost ~]# type for
for is a shell keyword
[root@localhost ~]# type cd
cd is a shell builtin

文件内容处理

sort命令

sort常用于对文本截取、排序等。常用的选项及说明如下表:

选项 说明
-n 依照数值大小进行排序。
-r 以倒序的方式显示。
-t 指定分隔符。
-k 指定要取的字符。

准备测试文件。

1
2
3
4
5
6
7
[root@localhost ~]# cat file.txt 
b:3
c:2
a:4
e:5
d:1
f:11

将文件排序首列进行排序。

1
2
3
4
5
6
7
[root@localhost ~]# sort file.txt 
a:4
b:3
c:2
d:1
e:5
f:11

将文本第二列数字按照大小进行排序。

1
2
3
4
5
6
7
8
[root@localhost ~]# sort -t ":" -n -k2 file.txt 
# -t指定分隔符,-n以数字大小进行排序,-k指定要排序的列
d:1
c:2
b:3
a:4
e:5
f:11

准备测试文件。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
[root@localhost ~]# cat sort-test.txt
10.0.3.1 00:0F:AF:81:19:1F
10.0.3.2 00:0F:AF:85:6C:25
10.0.2.20 00:0F:AF:85:55:DE
10.0.2.21 00:0F:AF:85:6C:09
10.0.2.22 00:0F:AF:85:5C:41
10.0.0.151 00:0F:AF:85:6C:F6
10.0.0.152 00:0F:AF:83:1F:65
10.0.1.10 00:30:15:A2:3B:B6
10.0.1.12 00:30:15:A2:3A:A1
10.0.1.1 00:0F:AF:81:19:1F
10.0.2.2 00:0F:AF:85:6C:25
10.0.3.3 00:0F:AF:85:70:42
10.0.1.21 00:0F:AF:85:6C:09
10.0.1.152 00:0F:AF:83:1F:65
10.0.0.153 00:0F:AF:85:70:03
10.0.3.10 00:30:15:A2:3B:B6
10.0.1.11 00:30:15:A3:23:B7
10.0.3.12 00:30:15:A2:3A:A1

对该文件输出内容进行排序,可通过第3列的第一个字符以及第4列的所有字符进行排序。

1
[root@localhost ~]# sort -t "." -n -k3.1,3.1 -k4.1,4.3 sort-test.txt

uniq命令

uniq用于删除相邻的重复的行或统计文本,常用选项如下表:

选项 说明
-c 计算重复的行。

源文件。

1
2
3
4
5
6
7
[root@localhost ~]# cat uniq-test.txt 
123
abc
abc
123
abc
123

uniq去重,并显示重复次数。

1
2
3
[root@localhost ~]# sort uniq-test.txt | uniq -c
      3 123
      3 abc

要想用uniq去重,必须先用sort将重复的内容排列到一起。

cut命令

cut主要用于截取文本。

选项 说明
-d 指定分隔符。
-f 取第几列。

取用户名及QQ号。

1
2
3
4
[root@localhost ~]# cat cut-test.txt 
I am Snoopy, MY QQ is 793499077
[root@localhost ~]# cut -d " " -f 3,7 cut-test.txt
Snoopy, 793499077

我们发现使用cut很难将Snoopy后的逗号处理掉。可通过以下方式实现删除逗号。

1
2
3
[root@localhost ~]# cut -d " " -f 3,7 cut-test.txt | sed 's#,##g'
[root@localhost ~]# cut -d " " -f 3,7 cut-test.txt | awk -F ',' '{print $1,$2}'
[root@localhost ~]# awk '{print $3,$7}' cut-test.txt | awk -F ',' '{print $1,$2}'

实际生产过程中,很少使用到cut,通常会使用awk处理列。

awk命令

Awk是一种强大的文本处理工具,它以行为单位读取文本文件,根据用户指定的规则进行处理和操作。主要用于截取文本。

选项 说明
-F 指定分隔符。
  1. 取出设备的IP地址。

    1
    2
    
    [root@localhost ~]# ifconfig | grep broadcast | awk '{print $2}'
    10.0.0.201
    
  2. 取出访问日志服务器的top10IP地址。

    获取源文件。

    1
    
    [root@localhost ~]# wget tools.snoopyops.top/file/access.log
    

    查看源文件格式。

    [root@localhost ~]# head access.log
    183.162.52.7 - - [10/Nov/2016:00:01:02 +0800] "POST /api3/getadv HTTP/1.1" 200 813 "www.snoopyops.top" "-" cid=0&timestamp=1478707261865&uid=2871142&marking=androidbanner&secrect=a6e8e14701ffe9f6063934780d9e2e6d&token=f51e97d1cb1a9caac669ea8acc162b96 "oldxu/5.0.0 (Android 5.1.1; Xiaomi Redmi 3 Build/LMY47V),Network 2G/3G" "-" 10.100.134.244:80 200 0.027 0.027
    10.100.0.1 - - [10/Nov/2016:00:01:02 +0800] "HEAD / HTTP/1.1" 301 0 "117.121.101.40" "-" - "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.16.2.3 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2" "-" - - - 0.000
    117.35.88.11 - - [10/Nov/2016:00:01:02 +0800] "GET /article/ajaxcourserecommends?id=124 HTTP/1.1" 200 2345 "www.snoopyops.top" "http://www.snoopyops.top/code/1852" - "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36" "-" 10.100.136.65:80 200 0.616 0.616
    182.106.215.93 - - [10/Nov/2016:00:01:02 +0800] "POST /socket.io/1/ HTTP/1.1" 200 94 "chat.snoopyops.top" "-" - "android-websockets-2.0" "-" 10.100.15.239:80 200 0.004 0.004
    10.100.0.1 - - [10/Nov/2016:00:01:02 +0800] "HEAD / HTTP/1.1" 301 0 "117.121.101.40" "-" - "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.16.2.3 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2" "-" - - - 0.000
    183.162.52.7 - - [10/Nov/2016:00:01:02 +0800] "POST /api3/userdynamic HTTP/1.1" 200 19501 "www.snoopyops.top" "-" cid=0&timestamp=1478707261847&uid=2871142&touid=2871142&page=1&secrect=a6e8e14701ffe9f6063934780d9e2e6d&token=3837a5bf27ea718fe18bda6c53fbbc14 "oldxu/5.0.0 (Android 5.1.1; Xiaomi Redmi 3 Build/LMY47V),Network 2G/3G" "-" 10.100.136.65:80 200 0.195 0.195
    10.100.0.1 - - [10/Nov/2016:00:01:02 +0800] "HEAD / HTTP/1.1" 301 0 "117.121.101.40" "-" - "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.16.2.3 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2" "-" - - - 0.000
    114.248.161.26 - - [10/Nov/2016:00:01:02 +0800] "POST /api3/getcourseintro HTTP/1.1" 200 2510 "www.snoopyops.top" "-" cid=283&secrect=86b720f312c2b25da3b20e59e7c89780&timestamp=1478707261951&token=4c144b3f4314178b9527d1e91ecc0fac&uid=3372975 "oldxu/5.0.2 (iPhone; iOS 8.4.1; Scale/2.00)" "-" 10.100.136.65:80 200 0.007 0.008
    120.52.94.105 - - [10/Nov/2016:00:01:02 +0800] "POST /api3/getmediainfo_ver2 HTTP/1.1" 200 633 "www.snoopyops.top" "-" cid=608&secrect=e25994750eb2bbc7ade1a36708b999a5&timestamp=1478707261945&token=9bbdba949aec02735e59e0868b538e19&uid=4203162 "oldxu/5.0.2 (iPhone; iOS 10.0.1; Scale/3.00)" "-" 10.100.136.65:80 200 0.049 0.049
    10.100.0.1 - - [10/Nov/2016:00:01:02 +0800] "HEAD / HTTP/1.1" 301 0 "117.121.101.40" "-" - "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.16.2.3 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2" "-" - - - 0.000
    

    取出访问日志服务器的top10IP地址。

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    
    [root@localhost ~]# awk '{print $1}' access.log | sort | uniq -c | sort -nr | head -10
    # 通过awk取出带有IP地址的列,排序后统计,将统计的结果以倒叙的方式显示,用head控制,显示前10行
       4714 10.100.0.1
         94 122.234.145.54
         56 171.34.14.120
         51 115.34.187.133
         50 58.61.60.183
         48 27.38.56.2
         44 119.131.143.179
         43 58.217.137.221
         39 117.174.26.235
         37 223.73.113.60
    

wc命令

wc用于统计文本行数

选项 说明
-l 显示文件的行数。

统计/etc/services文件的行数

1
2
[root@localhost ~]# wc -l /etc/services 
11176 /etc/services

统计/etc/passwd中以nologin结尾的有多少行。

1
[root@localhost ~]# grep "/sbin/nologin$" /etc/passwd | wc -l

image-20231028232834657