187. Linux文件

文件权限

在 Linux ,对文件的访问是通过文件权限、属性和所有权来验证。这确保只有授权的用户和进程才能访问文件和目录。

权限说明

在继续之前,让我们解释一下基本的 Linux 权限模型。在 Linux 每个文件都与一个所有者和一个组相关联,并为三类不同的用户分配访问权限:

  • 文件所有者。
  • 组成员。
  • 其他人。

可以使用 chownchgrp 命令更改文件所有权。

每个文件都有的三种权限类型:

  • 读取权限。
  • 写权限。
  • 执行权限。

此概念允许您指定允许哪些用户读取文件、写入文件或者执行文件。你可以使用 ls 命令查看文件权限 :

更详细地说明

1
2
3
4
5
6
7
8
9
10
11
$ ls -l filename.txt
-rw-r--r-- 12 myfreax users 12.0K Apr 8 20:51 filename.txt
|[-][-][-]- [------] [---]
| | | | | | |
| | | | | | +-----------> 7. 组Group
| | | | | +-------------------> 6. 所有者Owner
| | | | +--------------------------> 5. 访问方法 Access Method
| | | +----------------------------> 4. 其它人权限 Others Permissions
| | +-------------------------------> 3. 组权限 Group Permissions
| +----------------------------------> 2. 所有者 Owner Permissions
+------------------------------------> 1. 文件类型 File Type
  • 第一个字符显示文件类型。它可以是普通文件 -、目录 d符号链接 l 或任何其他特殊类型的文件。

  • 接下来的九个字符代表文件权限,三个三元组,每个元组包含三个字符。第一个三元组显示所有者权限。

    • 第二个三元组显示组权限
    • 最后一个三元组显示其他人权限。根据文件类型的不同,权限可能具有不同的含义。

上面示例例中的 rw-r--r-- 表示文件拥有有读写权限 rw-,组和其他人只有读权限 r--

三个权限三元组中的每一个都可以由以下字符构成,并且具有不同的效果,具体取决于它们是为文件还是目录设置。

权限对文件的影响

权限 字符 含义
- 这个文件不可读,也意味着不能够查看文件内容
r 文件可读。
- 文件不可写,也不能修改
w 文件可以被修改或者写入
执行 - 文件不可以被执行
x 文件可以被执行
s 如果在 user(用户) 三元组中找到 s 表示文件已设置 setuid 位。如果在 group(Linux 组) 三元组中找到 s,则表示文件已设置 setgid 位。这也意味着可执行权限已设置。当在可执行文件设置 setuid 或 setgid 标志时,文件将以文件的所有者或组权限执行。
S 和 s 一样,但可执行权限没有被设置,这个标志很少使用在文件上
t 如果在 others(其它人) 三元组中找到它设置 t ,也就是已设置 sticky 位。 这也意味着已设置文件的可执行权限。此标志对文件无用。
T 与 t 相同,但未设置可执行权限。此标志对文件无用。

权限对目录(文件夹)的影响

在 Linux 中,目录是包含其他文件和目录的特殊类型的文件。

权限 字符 含义
- 目录的内容不可见
r 目录内容可见。 例如你可以在目录内部使用 ls 命令列出文件的内容
- 无法修改目录内容
w 目录的内容可以更改。 例如 创建文件 或者删除文件 删除文件 等等
执行 - 不能使用 cd 命令切换目录
x 可以使用 cd 命令切换到目录
s 如果在 user 三元组中找到 s,则目录已设置 setuid 位。如果在 group 三元组中找到 s 则表示已设置 setgid 位。这也意味着可执行权限已设置。当在目录设置 setgid 标志时,在目录创建的文件将继承目录组 GID,而不是创建文件的用户主要组 ID。setuid 对目录没有影响。
S 与 s 相同,但未设置可执行权限。此标志在目录上没有用。
t 如果在其他人三元组中找到,它会设置粘性位。这也意味着设置可执行权限。当在目录设置粘性位时,只有文件所有者、目录所有者或管理用户可以删除或重命名目录中的文件。
T 与 t 相同,但未设置可执行权限。此标志在目录上没用。

文件颜色所代表的含义

颜色 文件类型标识 含义
浅蓝色 [l] 软链接
白色 [-] 普通文件/硬链接
蓝色 [d] 目录
红色 [l] 某文件被删除后,链接到该文件的软链接的颜色
红色闪烁 表示该文件已被删除,但还存在该文件的软链接
红色 [-] 压缩包
黄色 [c] 字符设备文件,如键盘鼠标
绿色 [-] 可执行文件,可执行的程序
桃红色 [s] 套接字文件
土黄色 [p] 管道文件
灰色文件 表示其它文件

chmod

命令

chmod命令的语法形式 chmod [OPTIONS] MODE FILE...

  • MODE 是权限的模式
  • FILE... 可以是一个或者多个文件与目录
  • [OPTIONS] chmod 命令的选项,是可选参数。

chmod 命令允许您使用符号或数字模式或参考文件修改改文件的权限。我们将在本文后面更详细地解释这些模式。当使用 chmod 命令修改多个文件与目录时 请使用空格分隔多个文件与目录。

只有 root、文件所有者或具有 sudo 权限的用户才能更修改文件的权限。使用 chmod 时要格外小心,尤其在递归修改权限时。

1
chmod [OPTIONS] MODE FILE...

符号模式

使用符号模式时 chmod 命令的语言法式如下:

1
chmod [OPTIONS] [ugoa…][-+=]perms…[,…] FILE...

第一组参数 [ugoa…],即用户类型的参数,确定修改文件权限的用户类别,[] 中括号表示参数是可选的。

  • u- 文件所有者。
  • g- 组。
  • o- 其它人。
  • a- 所有用户,与同时指定 ugo 一样。

如果省略[ugoa…] 参数,则默认为所有用户并且由 umask 设置的权限不受影响。

第二组参数 [-+=],操作权限的参数,定义是否要删除、添加或设置权限,[] 中括号表示参数是可选的:

  • - 删除指定的权限。
  • + 添加指定的权限。
  • = 将当前权限改为指定权限。如果在符号后没有指定权限=,则删除指定用户类的所有权限。

可以使用字母 r、w、x、X、s 和 t 中的零个,一个或多个来设置权限 perms... 参数。使用单个字母 u、g 和 o 为指定类别的用户设置权限。

当为多个种用户类型设置权限时,请使用逗号分隔多个符号模式。下面的一些示例展示如何在符号模式下使用 chmod 命令。

授予组成员读取文件的权限,但不能写入和执行它:

1
chmod g=r filename

删除所有用户的执行权限:

1
chmod a-x filename

递归删除其他用户的写权限:

1
chmod -R o-w dirname

删除除文件所有者之外的所有用户的读、写和执行权限:

1
chmod og-rwx filename

同样的事情也可以通过使用下面的命令来完成:

1
chmod og= filename

授予文件所有者读取、写入和执行权限,授予文件组读取权限,不授予其他用户权限:

1
chmod u=rwx,g=r,o= filename

将文件的所有者权限添加到文件组成员权限中:

1
chmod g+u filename

向指定目录添加粘性位:

1
chmod o+t dirname

数字模式

使用数字模式时 chmod 命令的语言法式如下:

1
chmod [OPTIONS] NUMBER FILE...

使用数字模式时,您可以同时设置所有者、组和所有其他人的权限。参数 NUMBER 可以是 3 位或 4 位数字。

当使用 3 位数字时,第一位代表文件所有者的权限,第二位代表文件的组,最后一位代表所有其他用户。

指定用户类型的权限都可以使用权限值的总和表示。写入、读取和执行权限都可以使用数值表示:

  • r(读)= 4
  • w(写)= 2
  • x(执行)= 1
  • 无权限 = 0

要以数字模式设置文件的权限,只需计算指定用户类别的总数即可。例如,要授予文件所有者读取、写入和执行权限,授予组的读取和执行权限,而只授予其他用户读取权限,您可以执行以下操作:

  • 所有者:rwx=4+2+1=7
  • 组:rx=4+0+1=5
  • 其他人:rx=4+0+0=4

使用上面的方法,我们得出数值是 754,它代表要设置的权限。

要设置 setuidsetgidsticky bit 粘性位,请使用四位数字。当使用 4 位数字时,第一位数字的含义如下:

  • setuid =4
  • setgid =2
  • sticky =1
  • 没有变化 = 0

接下来的三个数字与使用 3 位数字时的含义相同。如果首位是 0 则可以省略,模式可以用 3 位表示。数字模式 0755755 相同。

要计算数字模式,您还可以使用另一种二进制方法,但它稍微复杂一些。对于大多数用户来说,知道如何使用 4、2 和 1 计算数值模式就足够。

您可以使用 stat 命令以数字或者符号模式查看文件的权限 :

1
2
stat -c "%a" filename
644

以下是如何在数字模式下使用 chmod 命令的一些示例:

授予文件所有者读写权限,仅授予组成员和其他用户读取权限:

1
chmod 644 dirname

授予文件所有者读、写和执行权限,授予组成员读取和执行权限,不授予其他用户权限:

1
chmod 750 dirname

为指定目录设置读、写和执行权限,以及粘性位:

1
chmod 1777 dirname

递归修改文件所有者读取、写入和执行权限,而不为目录的其他用户和组设置权限:

1
chmod -R 700 dirname

使用参考文件

--reference=ref_file 选项允许您将文件的权限设置为与指定参考文件 ref_file 的权限相同。

1
chmod --reference=REF_FILE FILE

例如,以下 chmod 命令将权限分配 file1file2

1
chmod --reference=file1 file2

递归修改文件权限

要对指定目录下所有文件和目录进行递归操作,请使用chmod 命令的 -R( --recursive) 选项:

1
chmod -R MODE DIRECTORY

例如,要修改 /var/www 目录下所有文件和子目录的权限为 755,您可以运行以下命令:

1
chmod -R 755 /var/www

符号链接权限

符号链接始终具有 777 权限。默认情况下,当修改符号链接的权限时,chmod 将更改链接指向的文件的权限。

1
chmod 755 symlink

很有可能您不能够修改目标文件的所有权,而是会收到 cannot access ‘symlink’: Permission denied 的错误。不能够访问软链接,权限拒绝。

出现此错误是因为在大多数 Linux 发行版中默认情况下符号链接是受保护的,您无法对目标文件进行操作。

此选项在 /proc/sys/fs/protected_symlinks 中指定。1 表示启用和 0 禁用。建议不要禁用符号链接的保护。

批量更改文件权限

有时,在某些情况下,您需要批量修改文件和目录权限。最常见的场景是递归修改网站文件的权限为 644 和目录的权限为 755

使用数值方法:

1
find /var/www/my_website -type d -exec chmod 755 {} \;

使用符号方法:

1
find /var/www/my_website -type d -exec chmod u=rwx,go=rx {} \;

find 命令将搜索 /var/www/my_website 的文件和目录,并将找到的每个文件和目录传递给 chmod 命令设置权限。

chgrp

修改文件与目录(文件夹)所属组.

修改文件组的所有权,符号链接组的所有权,递归修改组所有权以及使用 GID 或者组名来修改组的所有权。

命令

chgrp 命令的语法形式是 chgrp [OPTIONS] GROUP FILE..GROUP 可以是组的名称或组 ID 也就是 GID,GID 必须以 + 符号作为前缀。

FILE.. 可以是一个或多个文件与目录的名称,当指定多个文件或者目录,请使用多个空格进行分隔。

chown 命令不同的是,chown 命令允许您修改文件目录的所有者,chgrp 修改文件或者目录组的所有权。

要找出文件的所属组,请运行命令 ls -al。只有 root 用户或具有 sudo 权限的用户才能修改文件目录的所属组。

1
chgrp [OPTIONS] GROUP FILE..

修改文件目录组的所有者

要修改文件目录的所属组,请运行 chgrp 命令,后跟组的名称,最后是目标文件或者目录作为参数。

例如 sudo chgrp www-data filename 命令修改 filename 文件的所属组为 www-data

1
chgrp www-data filename

如果您以没有 sudo 权限的用户运行命令,则会收到操作不允许的错误消息 Operation not permitted 。

默认情况下,chgrp 命令不产生任何输出,成功时返回退出代码 0。要验证是否成功修改,请运行命令 ls -al

1
2
sudo chgrp www-data filename
ls -al filename

您还可以将多个文件或者目录作为参数传递给 chgrp 命令。

1
sudo chgrp www-data file1 file2 dir1

使用chgrp 命令的 -v 选项获取正在处理的文件信息。

1
sudo chgrp -v www-data file1 file2

也可以使用 GID 代替组名。

1
2
3
chgrp +1000 filename
changed group of 'file1' from nginx to www-data
group of 'file2' retained as www-data

修改软链接所属组

在不进行递归修改文件目录所属组时,chgrp 命令的默认行为是修改软链接的目标文件所属组,而不是软链接本身。

例如命令 sudo chgrp www-data symlink1 修改软链接 symlink1 的目标文件所属组,软链接文件本身的所属组不会被修改。

1
sudo chgrp www-data symlink1

在修改软链接文件目录所属组时,你很有可能您会看到错误消息 cannot dereference ‘symlink1’: Permission denied。

发生错误是因为在大多数 Linux 发行版的软链接都受到保护并且您无法对目标文件进行操作。

要启用或者禁用软链接的保护,可以在 /proc/sys/fs/protected_symlinks 文件指定。1 表示启用,0 表示禁用。我们建议不要禁用软链接保护。

当遇到受保护符号链接时,可以尝试使用 chagrp 命令的 -h 选项,该选项将会尝试 修改符号链接文件的所有权,然后再修改目标的所属组。

1
sudo chgrp -h www-data symlink1

递归修改文件目录所属组

要递归更改所有文件和目录组的所有权,请使用chgrp 命令的 -R 选项。如果仅指定 -R 选项 chgrp 命令不会遍历软链接,即不会修软链接指向的目标文件。

但你可以使用 chgrp 命令的 -h 选项修改软链接指向的目标文件所属组。如果软链接的目标文件是一个目录,你还需要指定 -H 选项遍历目录。

除此之外你还需要使用 -L 选项遍历链接到目录的每个符号链接,在大多数情况,不建议使用 -L-H 选项,因为这可能会导致系统混乱或带来安全风险。

1
2
chgrp -R www-data /var/www
chgrp -hR www-data /var/www #include symlinks

chown

在 Linux ,所有文件都与一个所有者以及一个组相关联,并为文件所有者、组成员和其他人分配访问权限。

命令

在介绍如何使用该chown命令之前,让我们先回顾一下基本语法。chown 命令表达式采用以下形式:

1
chown [OPTIONS] USER[:GROUP] FILE(s)

USER 是所有者的用户名或用户 ID (UID)。GROUP 是组的名称或组 ID (GID)。FILE(s) 是一个或多个文件、目录(文件夹)或链接的名称。数字 ID 应以 + 符号为前缀。

  • USER 如果只指定用户,指定的用户将成为指定文件的所有者,组所有权不变。
  • USER: 当用户名后跟一个冒号:,并且没有给出组名时,用户将成为文件的所有者,文件组所有权更改为用户的登录组。
  • USER:GROUP 如果同时指定了用户和组(它们之间没有空格),则文件的用户所有权将更改为指定的用户,组所有权更改为指定的组。
  • :GROUP 如果省略 User 并且组以 : 冒号为前缀,则只有文件的组所有权更改为指定的组。
  • 如果只给出一个 : 冒号,而不指定用户和组,则不会进行任何修改。

默认情况下,成功时。chown 命令不产生任何输出并返回零。可以使用 ls -l 命令找出谁拥有文件或文件属于哪个组:

1
2
3
4
5
6
ls -l filename.txt
-rw-r--r-- 12 linuxize users 12.0K Apr 8 20:51 filename.txt
|[-][-][-]- [------] [---]
| |
| +-----------> Group
+-------------------> Owner

普通用户只有在拥有文件时才能修改文件的组,并且只能修改为他们所属的组。管理用户可以修改所有文件的所有权。

如何修改文件的所有者

要修改文件的所有者,请使用以下 chown 命令,后跟新所有者的用户名和目标文件作为参数:

1
chown USER FILE

例如,以下命令会将名为 file1 文件的所有权修改为所有者 myfreax

1
chown myfreax file1

要修多个文件或目录的所有权,请将多个文件名使用空格分隔。下面的命令将文件 file1 和目录 dir1 的所有权更改为 myfreax

1
chown myfreax file1 dir1

可以使用数字用户 ID (UID) 代替用户名。以下示例将会修改文件 file2 的所有权为UID 1000 的用户:

1
chown 1000 file2

如果数字就是所有者的用户名,则所有权将转移到该用户名。为避免这种情况,可以使用 + 作为 UID 的前缀,这样就可以避免将UID解释为用户名 :

1
chown 1000 file2

如何修改文件的所有者和组

要同时修改文件的所有者和组,请使用 chown 命令,后跟所有者和组,中间用冒号 : 分隔,中间没有空格,然后是目标文件。

1
chown USER:GROUP FILE

以下命令会将名为的文件 file1 的所有权更改为 myfreax 用户,组的所有权为 user 组:

1
chown myfreax:users file1

如果在冒号 : 后省略组名,文件的组将更改为指定用户,组的所有权是指定用户的主要组:

1
chown myfreax: file1

如何修改文件所有组

要仅修改文件组的所有权,请使用 chown 命令后跟冒号 : 和组名(它们之间没有空格)以及目标文件作为参数:

1
chown :GROUP FILE

以下命令将 file1 文件的所属组更改为 www-data

1
chown :www-data file1

另一个可用于修改文件组所有权的命令是 chgrp .

如何修改符号链接的所有权

当不使用递归选项时,chown 命令修改符号链接指向的文件组的所有权,而不是符号链接本身。

例如,如果您尝试修改符号链接 symlink1 指向的文件 /var/www/file1 用户和组的所有权:

1
chown www-data: symlink1

很有可能您不会修改目标文件目录的所有权,而是会收到 “cannot dereference ‘symlink1’: Permission denied” 无法取消引用 symlink1 权限被拒绝的错误。

出现该错误是因为在大多数 Linux 发行版,默认情况下符号链接是受保护的,您无法对目标文件进行操作。

此选项在 /proc/sys/fs/protected_symlinks 中指定。1表示启用, 0 禁用。我们建议不要禁用符号链接保护。

要修改符号链接本身组所有权,请使用 chown 命令的 -h选项:

1
chown -h www-data symlink1

如何递归修改文件所有权

要对指定目录的所有文件和目录进行递归操作,请使用 chown 命令的 -R/--recursive 选项:

1
chown -R USER:GROUP DIRECTORY

以下示例将 /var/www 目录下的所有文件和子目录的所有权更改为为 www-data 所有者和组:

1
chown -R www-data: /var/www

如果目录包含符号链接指定 -h 选项 :

1
chown -hR www-data: /var/www

递归修改目录所有权时可以使用选项是 -H-L

如果传递给 chown 命令的参数是指向目录的符号链接,则 -H 选项将使命令遍历它。

-L 指示 chown 遍历每个符号链接到遇到的目录。通常,您不应使用这些选项,因为这可能会弄乱系统或产生安全风险。

使用参考文件

--reference=ref_file 选项允许您将指定文件的用户和组所有权更改为与指定参考文件相同的权限。如果引用文件是符号链接,chown 将使用目标文件的用户和组。

1
chown --reference=REF_FILE FILE

例如,以下命令将 file1 的用户和组所有权分配给 file2

1
chown --reference=file1 file2

虚拟文件系统

问题

有时会出现这样的情况,磁盘空间显示已经被占满,但是在查看磁盘的具体文件占用情况时,发现磁盘仍然有很大的空余空间。

执行df命令查看磁盘使用情况,发现磁盘已经满了。

1
2
3
4
5
6
7
$ df -Th
Filesystem Type Size Used Avail Use% Mounted on
/dev/vda1 ext4 30G 30G 0 100% /
devtmpfs devtmpfs 489M 0 489M 0% /dev
tmpfs tmpfs 497M 0 497M 0% /dev/shm
tmpfs tmpfs 497M 50M 447M 11% /run
tmpfs tmpfs 497M 0 497M 0% /sys/fs/cgroup

执行du命令查看各个目录的磁盘占用情况,把各个目录文件的大小相加,发现并没有占满磁盘,有10多G空间莫名失踪。

1
2
3
4
$ du -h –max-depth=1 /home
16M /home/logs
11G /home/serverdog
11G /home

为何会出现这样的情况呢?

因为虽然文件已被删除,但是一些进程仍然打开这些文件,因此其占用的磁盘空间并没有被释放。执行lsof命令显示打开已删除的文件。将有问题的进程重启(或,清空),磁盘空间就会得到释放。

1
2
3
4
5
6
$ lsof | grep delete
mysqld 2470 mysql 4u REG 253,1 0 523577 /var/tmp/ibfTeQFn (deleted)
mysqld 2470 mysql 5u REG 253,1 0 523579 /var/tmp/ibaHcIdW (deleted)
mysqld 2470 mysql 6u REG 253,1 0 523581 /var/tmp/ibLjiALu (deleted)
mysqld 2470 mysql 7u REG 253,1 0 523585 /var/tmp/ibCFnzTB (deleted)
mysqld 2470 mysql 11u REG 253,1 0 523587 /var/tmp/ibCjuqva (deleted)

那么,Linux的文件系统,到底为什么这么设计呢?要了解这些,就要先弄清楚并不容易,下面将从一些基本概念入手,一步步将这些梳理清楚:

虚拟文件系统(virtual filesystem)

下图显示了Linux操作系统中负责文件管理的基本组件。上半区域为用户模式,下半区域为内核模式。应用程序使用标准库libc来访问文件,库将请求映射到系统调用,以便进入内核模式。

所有与文件相关的操作的入口都是虚拟文件系统(VFS),而非特定的额文件系统(如Ext3、ReiserFS和NFS)。VFS 提供了系统库和特定文件系统之间的接口。因此,VFS 不仅充当抽象层,而且实际上它提供了一个文件系统的基本实现,可以由不同的实现来使用和扩展。因此,要了解文件系统是如何工作的,就要先了解VFS 。

目录树

综合来说,Linux 的根文件系统(system’s root filessystem) 是内核启动mount的第一个文件系统。内核代码映像文件保存在根文件系统中,而系统引导启动程序会在根文件系统挂载之后,从中把一些基本的初始化脚本和服务等加载到内存中去运行(文件系统和内核是完全独立的两个部分)。其他文件系统,则后续通过脚本或命令作为子文件系统安装在已安装文件系统的目录上,最终形成整个目录树。

1
2
3
4
5
6
7
8
tart_kernel
  vfs_caches_init
    mnt_init
      init_rootfs // 注册rootfs文件系统
      init_mount_tree // 挂载rootfs文件系统
  …
  rest_init
  kernel_thread(kernel_init, NULL, CLONE_FS);

就单个文件系统而言,在文件系统安装时,创建超级块对象;沿树查找文件时,总是首先从初识目录的中查找匹配的目录项,以便获取相应的索引节点,然后读取索引节点的目录文件,转化为dentry对象,再检查匹配的目录项,反复执行以上过程,直至找到对应的文件的索引节点,并创建索引节点对象。

软链接 vs 硬链接

软链接是一个普通的文件,其中存放的是另外一个文件的路径名。硬链接则指向同一个索引节点,硬链接数记录在索引节点对象的i_nlink字段。当i_nlink字段为零时,说明没有硬链接指向该文件。

索引与数据

文件系统与文件、磁盘管理与文件、进程管理与文件,最核心的都是文件的索引,而不是文件的数据。把数据和索引分开是理解文件系统的关键。

一个数据构建了各式各样的索引,只有索引全部失效,此时数据才失去意义,此时才能释放

缓存策略

由于操作系统使用 Write back 的策略,意味着只有先释放内存,才有可能释放磁盘。

Why lsof ?

从上面的模型可以很清楚的理解,因为目录已经没有索引到文件了,但是打开文件还有索引到文件,所以不能立刻释放磁盘空间。

为什么 lsof 可以找到已删除未释放的文件呢?

lsof,顾名思义:list open files,该命令的原理就是查找打开文件的列表,因此可以找到已删除未释放的文件。

du(查看系统目录的大小)

在linux系统中,我们通常使用ls命令来查看文件列表,或者使用ll命令来查看文件列表中的详细信息,包括权限,创建时间,大小等等。

有个问题不知道大家有没有注意过,就是不管是用 ls -lh 还是ll,所显示出来的目录的大小只有4kbll显示的是4096b),这是为什么?

1
2
3
4
5
6
7
8
9
10
11
[root@xxx /]# ll
总用量 40600
dr-xr-xr-x. 2 root root 4096 12月 9 17:57 bin
dr-xr-xr-x. 4 root root 4096 7月 7 2015 boot
drwxr-xr-x. 2 root root 4096 2月 27 2014 cgroup
drwxr-xr-x 18 root root 3740 5月 5 17:07 dev
drwxr-xr-x. 147 root root 12288 5月 27 03:36 etc
drwxr-xr-x. 3 root root 4096 7月 7 2015 home
dr-xr-xr-x. 13 root root 4096 12月 7 2017 lib
dr-xr-xr-x. 10 root root 12288 12月 7 2017 lib64
drwx------. 2 root root 16384 7月 7 2015 lost+found
1
2
3
4
5
6
7
8
9
[root@xxx /]# ls -lh
总用量 40M
dr-xr-xr-x. 2 root root 4.0K 12月 9 17:57 bin
dr-xr-xr-x. 4 root root 4.0K 7月 7 2015 boot
drwxr-xr-x. 2 root root 4.0K 2月 27 2014 cgroup
drwxr-xr-x 18 root root 3.7K 5月 5 17:07 dev
drwxr-xr-x. 147 root root 12K 5月 27 03:36 etc
drwxr-xr-x. 3 root root 4.0K 7月 7 2015 home
dr-xr-xr-x. 13 root root 4.0K 12月 7 2017 lib

其实linux系统中并没有单独的目录这个概念,所有的目录或者文件,都视为文件,所以我们看到的4kb只是用于存储目录元信息的文件大小,并不是我们通常理解的目录(包括子文件)的大小。那么,我们怎么样获取到目录文件的实际大小呢?可以使用du命令。

du 是 disk usage 的缩写,表示磁盘的使用率,这是一个标准的unix程序,用于估算当前工作目录中文件空间的使用情况。

本文我们来介绍一下 du 命令的使用。

1. 查看当前目录下文件的总大小

1
2
[root@xxx opt]# du -sh
7.7G .

或者

1
2
[root@xxx opt]# du -h --max-depth=0
7.7G .

上面两种方式都可以算出目标目录的总大小,其中:

-h 表示显示成 K、M、G 等大小格式

-s 表示显示总和

--max-depth=N 表示目录级别为 N

2. 查看当前路径下每个目录(包括子目录)的大小

上面命令中,将 -s 选项去掉,也就是不进行总和的统计,就能显示每个子目录的大小了。但是如果当前路径下的目录较多,最好带上一个 head 加一个数字的参数,表示只显示前多少条,要不然会一直滚屏下去,直到显示完所有子目录。

1
2
3
4
5
6
[root@xxx opt]# du -h | sort -rh | head -5
7.7G .
1.4G ./apps
1.3G ./cobra/icinga/var/archives
1.3G ./cobra/icinga/var
1.3G ./cobra/icinga

3. 使用 * 通配符,可以查看路径下目录 + 文件的大小

1
2
3
4
5
6
[root@xxx opt]# du -h * | sort -rh | head -5
1.4G apps
1.3G cobra/icinga/var/archives
1.3G cobra/icinga/var
1.3G cobra/icinga
1.3G cobra

4. 如果只查看当前路径下的目录大小,排除子目录,可以使用 -S 选项

1
2
3
4
5
6
[root@xxx opt]# du -Sh | sort -rh | head -5
1.4G .
1.3G ./cobra/icinga/var/archives
876M ./apps/solr-tomcat/logs
641M ./solr_home/data-for-1.3.3/data/model/dependency
641M ./data-for-1.3.3/data/model/dependency

5. 查看当前路径下一级子目录的大小,可以将 max-depth 设定为1就可以了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[root@xxx opt]# du -h --max-depth=1
1.1G ./solr_home
126M ./openssl-1.1.1g
8.0K ./LinuxKPC
639M ./nportal-tomcat
15M ./ksar
533M ./tomcat-ma
5.9M ./mirror_client_for_webmin
1.2M ./mirror_storage_for_webmin
37M ./openssh-8.3p1
337M ./tomcat-gis
1018M ./data-for-1.3.3
57M ./systemcenter2.0
14M ./backup_client
1.2M ./backup_server
37M ./logs
1.4G ./apps
88K ./incron_sys_manage
1.3G ./cobra
7.7G .

6. 查看当前目录的大小,并且统计总大小,可以使用 -c 选项

1
2
3
4
5
6
[root@xxx opt]# du -shc * | sort -rh | head -5
7.7G 总用量
1.4G apps
1.3G cobra
1.1G solr_home
1018M data-for-1.3.3

7. 查看其他路径的目录大小

另外,对于 du 命令,如果后面跟了一个路径,则表示查询指定路径的大小。

1
2
[root@xxx home]# du -sh /home
40K /home

df(查看磁盘空间)

不管你是系统管理员,还是普通的用户,都需要知道你有多少可用的磁盘空间,这样才能更好的使用系统。

如果你使用桌面Linux,这可以通过常规的文件管理器来完成,但是Linux用户应该知道命令行的使用,这就是为什么您需要更多地了解“disk format”或“df”命令的原因。

本文我们了解下在Linux中如何使用df命令查看磁盘空间。

1. df 查看磁盘信息

主命令和普通命令’df‘将输出Linux安装程序中文件系统的整个列表。为了解释什么是文件系统,我们可能需要一整篇文章,但是现在让我们假设它是系统中一些文件的排列方式。

这些信息在可读性方面可能不是最好的,所以让我们来探索一个更好的方式。

2. 可读选项 df -h

为了获得输出的“可读”版本(这就是“h”的含义),你需要执行:

1
$ df -h

执行这个命令你会看到如下内容:

如上图所示,它将列出文件系统,并使用千兆字节和兆字节单位来表示空间,这更易于理解和使用。

3. 列出每个文件系统的类型

列出文件系统及其对应的文件系统类型可能很有用。为此,可以使用“-T”选项:

1
$ df -T

4. 查看Linux中的可用磁盘空间

有时候你可能需要知道某个文件夹还有多少磁盘空间可用,可以使用df命令后面跟上文件夹的名称就可以:

1
df -h directory_name

不要与此文件夹实际从系统中占用多少空间相混淆,因为此信息不是由“df”命令提供的,而是由“du”(磁盘使用)命令提供的。不过,这个df选项实际上会让您知道该特定文件夹有多少可用空间,以及该文件夹所在的文件系统。

5. 排除特定类型的文件系统

我们已经看到’df‘会给您提供大量的信息,但是,有时你可能希望排除一些文件系统类型,以便只获取特定的数据。

在我前面的示例中,你可以看到我安装了许多“快照”,每个快照都是单独列出的。它们都具有“squashfs”文件系统类型,因此如果我过滤那些不包括在内的文件系统,将得到一个更为有限的信息:

通过使用“x”选项(排除),我可以从输出中删除文件系统类型,以获得更具体的信息。

1
df -x filesystem_type

6. 仅列出特定的文件系统

另一方面,假设您只想列出某些类型的文件系统,所以您只需列出您需要的特定文件系统,而不是排除所有不需要的文件系统。

有一个非常简单的选项:只需添加’-t‘和要列出的文件系统类型:

1
df -t filesystem_type

7. 查看当前文件夹中的文件和文件夹的大小

1
df -sh *

总结

df命令是一个非常有用的命令,对此你应该知道,以便能够获得有关磁盘空间的更多信息。这不仅仅是简单地知道可用的磁盘空间的问题,而且它还提供了许多了解特定文件系统和以不同格式显示信息的选项。

当然,与任何其他命令一样,只需在其中运行一个“-help”选项,您就可以看到它的其他一些选项:

系统目录结构

介绍 Linux 系统目录结构,以及各个目录文件的用途。

如果你使用过Linux系统,那么你就会听说过root, lib, bin 等术语,这些目录在所有Linux系统中都会存在。

事实上,Linux 基金会维护文件系统层次标准(FHS)。FHS定义了Linux发行版中的目录结构和目录的内容/用途。正是因为有了FHS,所以你可以在几乎所有Linux发行版中找到相同的目录结构。

让我们详细看一下。

Linux目录结构

Linux 系统是基于 Unix的,因此它使用了 Unix 的文件系统层次结构。在类似 Unix的操作系统(如BSD和macOS)中,你可以使用类似的目录结构。

树状目录结构:

以下是对这些目录的解释:

  • /bin

    bin是Binary的缩写, 这个目录存放着最经常使用的命令。

  • /boot

    这里存放的是启动Linux时使用的一些核心文件,包括一些连接文件以及镜像文件。

  • /dev

    dev是Device(设备)的缩写, 该目录下存放的是Linux的外部设备,在Linux中访问设备的方式和访问文件的方式是相同的。

  • /etc

    这个目录用来存放所有的系统管理所需要的配置文件和子目录。

  • /home

    用户的主目录,在Linux中,每个用户都有一个自己的目录,一般该目录名是以用户的账号命名的。

  • /lib

    这个目录里存放着系统最基本的动态连接共享库,其作用类似于Windows里的DLL文件。几乎所有的应用程序都需要用到这些共享库。

  • /lost+found

    这个目录一般情况下是空的,当系统非法关机后,这里就存放了一些文件。

  • /media

    linux系统会自动识别一些设备,例如U盘、光驱等等,当识别后,linux会把识别的设备挂载到这个目录下。

  • /mnt

    系统提供该目录是为了让用户临时挂载别的文件系统的,我们可以将光驱挂载在/mnt/上,然后进入该目录就可以查看光驱里的内容了。

  • /opt

    这是给主机额外安装软件所摆放的目录。比如你安装一个ORACLE数据库则就可以放到这个目录下。默认是空的。

  • /proc

    这个目录是一个虚拟的目录,它是系统内存的映射,我们可以通过直接访问这个目录来获取系统信息。 这个目录的内容不在硬盘上而是在内存里,我们也可以直接修改里面的某些文件,比如可以通过下面的命令来屏蔽主机的ping命令,使别人无法ping你的机器

    1
    echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_all
  • /root

    该目录为系统管理员,也称作超级权限者的用户主目录。

  • /sbin

    s就是Super User的意思,这里存放的是系统管理员使用的系统管理程序。

  • /selinux

    这个目录是Redhat/CentOS所特有的目录,Selinux是一个安全机制,类似于windows的防火墙,但是这套机制比较复杂,这个目录就是存放selinux相关的文件的。

  • /srv

    该目录存放一些服务启动之后需要提取的数据。

  • /sys

    这是linux2.6内核的一个很大的变化。该目录下安装了2.6内核中新出现的一个文件系统 sysfs 。 sysfs文件系统集成了下面3种文件系统的信息:针对进程信息的proc文件系统、针对设备的devfs文件系统以及针对伪终端的devpts文件系统。该文件系统是内核设备树的一个直观反映。 当一个内核对象被创建的时候,对应的文件和目录也在内核对象子系统中被创建。

  • /tmp

    这个目录是用来存放一些临时文件的。

  • /usr

    这是一个非常重要的目录,用户的很多应用程序和文件都放在这个目录下,类似于windows下的program files目录。

  • /usr/bin

    系统用户使用的应用程序。

  • /usr/sbin

    超级用户使用的比较高级的管理程序和系统守护程序。

  • /usr/src

    内核源代码默认的放置目录。

  • /var

    这个目录中存放着在不断扩充着的东西,我们习惯将那些经常被修改的目录放在这个目录下。包括各种日志文件。

在linux系统中,有几个目录是比较重要的,平时需要注意不要误删除或者随意更改内部文件。

  • /etc 是系统中的配置文件,如果你更改了该目录下的某个文件可能会导致系统不能启动

  • /bin, /sbin, /usr/bin, /usr/sbin: 这是系统预设的执行文件的放置目录,比如 ls 就是在/bin/ls 目录下的。 值得提出的是,/bin, /usr/bin 是给系统用户使用的指令(除root外的通用户),而/sbin, /usr/sbin 则是给root使用的指令

  • /var: 这是一个非常重要的目录,系统上跑了很多程序,那么每个程序都会有相应的日志产生,而这些日志就被记录到这个目录下,具体在/var/log 目录下,另外mail的预设放置也是在这里。

/ - 根路径

Linux 中所有的内容,所有的文件/目录,都位于由”/“ 表示的“根”下。如果你看一下目录结构,会发现它类似于植物的根。

由于所有其他目录或文件都是根目录的子目录,所以任何文件的绝对路径都会通过根遍历。例如,如果在/home/user/documents中有文件,则可以猜测其目录结构为 /->home->user->documents.

残酷的 rm -rf / 段子

你可能在网上遇到过一些关于 “rm -rf /“ 的段子。rm命令用于删除Linux中的文件和目录。

使用rm -rf /,您可以要求系统强制地、递归地删除根目录的内容。因为根目录下有所有的内容,所以最终删除了所有内容,Linux系统就消失了(理论上)。

大多数Linux发行版都不会运行这个命令,除非执行 -no preserve root。所以任何时候都不要执行这个命令。

/bin - 二进制文件

/bin 目录中包含许多基本的shell命令(如ls,cp,cd等)的可执行文件。大多数程序都是二进制的。Linux系统中的所有用户都可以访问。

/dev - 设备文件

此目录仅包含特殊文件,包括与设备相关的文件。这些是虚拟文件,而不是磁盘上的物理文件。

关于该目录中文件的一些有意思的例子:

  • /dev/null:可以发送来销毁任何文件或字符串;
  • /dev/zero:包含0的无限序列;
  • /dev/random:包含无限个随机值序列.

/etc - 配置文件

/etc目录包含系统的核心配置文件,主要由管理员和服务使用,如密码文件和网络文件。

如果您需要更改系统配置(例如更改主机名),您可以在这里找到相应的文件。

/usr - 用户二进制文件和程序数据

/usr 目录中保存所有可执行文件、库和大多数系统程序的源代码。因此,对于普通用户来讲,其中的大多数文件都是只读的。

目录 说明
/bin 存放所有用户皆可用的系统程序,即普通的基本命令,如:touch, ls
/sbin 存放超级用户才能使用的系统程序,即基本的系统命令,如:sreboot
/usr/bin 存放所有用户都可用的应用程序或命令,一般是已安装软件的运行脚本
如:freemake、wget等
/usr/sbin 存放超级用户才能使用的应用程序或命令, 一般是与服务器软件程序命令相关的
如:dhcpdhttpdsamba
/usr/local/sbin 存放超级用户才能使用的第三方软件, 如 nginx
/usr/local/bin 存放所有用户都可用的第三方软件程序, 如 mysql
/usr/lib 包含系统库;
/usr/share 包含所有库通用的文档,例如 /usr/share/man 包含手册页的文本.
/usr/src 内核源代码默认的放置目录

/home - 用户个人数据

home目录是用户的个人目录,包含用户数据和用户特定的配置文件。作为一个系统用户,你需要把个人文件,笔记,程序等都放到你的个人主目录中。

在Linux系统上创建用户时,通常会为用户创建主目录。假设您的Linux系统有两个用户,Alice和Bob。他们将在 /home/alice/home/bob 有自己的主目录。

注意,Bob不能访问 /home/alice,反之亦然。这是有意义的,因为只有用户才能访问他/她的家。您可以阅读 Linux 系统文件权限相关内容,以了解有关此主题的更多信息。

/lib - 共享的库文件

库基本上是可执行二进制文件可以使用的代码。/lib 目录保存了/bin/sbin 目录中二进制文件所需的库。

/usr/bin/usr/sbin 中的二进制文件所需的库位于 /usr/lib 目录中。

/sbin - 系统二进制文件

这类似于/bin目录。唯一的区别是,它包含只能由root或sudo用户运行的二进制文件。你可以把“sbin”中的“s”想象成super或sudo。

/tmp - 临时文件

顾名思义,这个目录保存临时文件。许多应用程序使用此目录存储临时文件。甚至可以使用目录来存储临时文件。

但请注意,当系统重新启动时,/tmp目录的包含内容将被删除。有些Linux系统也会自动删除旧文件,所以不要在这里存储任何重要的文件。

/var - 可变数据文件

Var,variable的缩写,是程序存储运行时信息的地方,比如系统日志、用户跟踪、缓存以及系统程序创建和管理的其他文件。

存储在这里的文件不会自动清理,因此它为系统管理员提供了一个查找有关其系统行为的信息的好地方。例如,如果要检查Linux系统中的登录历史,只需检查 /var/log/wtmp 中文件的内容。

/boot - 启动文件

/boot 目录包含内核和启动映像的文件,以及LILO和Grub。通常建议将该目录放在磁盘开头的分区中。

/proc - 进程和内核文件

/proc 目录包含有关当前正在运行的进程和内核参数的信息。proc目录的内容被许多工具用来获取运行时系统信息。

例如,如果您想检查Linux中的处理器信息,只需参考/proc/cpuinfo文件即可。要检查Linux系统的内存使用情况,只需查看/proc/meminfo文件的内容即可。

/opt - 可选软件

传统上,/opt 目录用来安装或存储发行版系统中不存在的第三方应用。通常的做法是将软件代码保存在opt中,然后将二进制文件链接到/bin目录中,以便所有用户都可以运行它。

/root - root用户的主目录

还有/root目录,它作为root用户的主目录。因此,root用户的主目录在/root,而不是/home/root。不要将它与根目录(/)混淆。

/media - 可移除媒体的装入点

连接可移动媒体(如U盘、SD卡或DVD)时,会在/media目录下为它们自动创建一个目录。您可以从此目录访问可移动媒体的内容。

/mnt - 装载目录

这与/media目录类似,但mnt不是自动挂在可移动介质,而是系统管理员手动挂载文件系统。

/srv - 服务数据

/srv目录包含系统提供的服务的数据。例如:如果你运行一个http服务器,那么最好将网站数据存储在/srv目录中。

以上可以让大家对Linux系统的目录结构有个大致的了解。下图作为备忘:

各路径解释

  • . :当前目录,也可以用 ./ 表示;

  • .. :上一级目录,也可以用 ../ 表示;

  • ~ : 用户自己的宿主目录;

  • /:根目录

    • Linux文件系统树形结构的最顶端,称为 Linux 文件系统的 root,它是 Linux 文件系统的入口。所有的目录、文件、设备都在 / 之下,它是 Linux 文件系统最顶层的唯一的目录;
    • 一般建议在根目录下面只有目录,不直接存放文件;
    • 根目录是 linux 系统启动时系统第一个载入的分区,所以启动过程中用到的文件应该都放在这个分区中,其中 /etc/bin/dev/lib/sbin 这 5 个子目录都应该要与根目录连在一起,不可独立成为某个分区;
  • /bin:含了引导启动所需的命令或普通用户可能用的命令(可能在引导启动后)。这些命令都是二进制文件的可执行程序(bin是binary的简称),多是系统中重要的系统文件

  • /sbin:类似 /bin ,也用于存储二进制文件。因为其中的大部分文件多是系统管理员使用的基本的系统程序,所以虽然普通用户必要且允许时可以使用,但一般不给普通用户使用,多数管理命令默认只有管理员可以使用

  • /etc :存放着各种系统的管理和配置文件

  • /root:超级用户 root 的家目录

  • /lib:根文件系统上的程序所需的共享库,存放了根文件系统程序运行所需的共享文件。 这些文件包含了可被许多程序共享的代码,以避免每个程序都包含有相同的子程序的副本,故可以使得可执行文件变得更小,节省空间。

    • /lib/modules :包含系统核心可加载各种模块,尤其是那些在恢复损坏的系统时重新引导系统所需的模块(例如网络和文件系统驱动)。
  • /boot:目录存放引导加载器(bootstrap loader)使用的文件,包括开机启动加载程序的核心文件;(如kernel和grub)

  • /mnt :临时挂载用的设备挂载点;(如磁盘分区,网络共享)

  • /media:移动存储设备默认挂载点;(如光盘)

  • /opt:额外所安装的应用程序目录,有些软件包我们可以将它安装在该目录中;(一般为空,某些应用软件安装需要这个目录)

  • /tmp:临时文件存放区域,默认被设置了粘滞位,存放程序在运行时产生的信息和数据

  • /dev:设备文件目录,即设备驱动程序,用户通过这些文件访问外部设备。比如,用户可 以通过访问/dev/mouse来访问鼠标的输入,就像访问其他文件一样,设备文件分为 2 种类型:字符设备文件和块设备文件

    • /dev/console:系统控制台,也就是直接和系统连接的监视器;
    • /dev/hd:IDE设备文件
    • /dev/sd:sata、usb、scsi等设备文件
    • /dev/fd:软驱设备文件
    • /dev/tty:虚拟控制台设备文件
    • /dev/pty:提供远程虚拟控制台设备文件
    • /dev/null:数据”黑洞”,所有写入该设备的信息都将消失,如当想要将屏幕上的输出信息隐藏起来时,只要将输出信息输入到 /dev/null 中即可;
  • /home:默认存放用户的宿主目录(除了 root 用户)

    • /home/~/.bashrc:提供 bash 环境中所需使用的别名;
    • /home/~/.bash_profile:提供 bash 环境所需的变量;
    • 一般先执行 .bashrc 后,才会再执行 .bash_profile
    • /home/~/.bash_history:用户历史命令文件,记录用户曾经输入过的所有命令;(默认为1000条,可以通过 HISTSIZE 变量更改)
    • /home/~/.bash_logout:当用户注销的同时,系统会自动执行 .bash_logout 文件,如果管理员需要记录用户注销的一些额外记录、动作或其他信息,就可以利用这个机制去完成;
  • /lost+found:当系统在运行时,有时会无法避免宕机、断电或不正常重启动,在这样的情况下,当系统重新启动时,发现某些文件写入未完成或其他问题产生,一般会使用 fsck 进行文件修复,而这些被修复或救回的文件,就会被放在这个目录下,只要是一个文件系统,系统就会自动在该文件系统所在的目录下建立 lost+found 目录

  • /sys:虚拟文件系统,被建立在内存中,是在2.6版的kernel之后才被加入到正式的文件系统中,以分类的方式将系统的信息存放在这个目录中,以方便linux用户通过不同的分类找出系统相关的信息;

  • /proc:虚拟文件系统,此目录是 kernel 加载后,在内存里面建立的一个虚拟目录,有专属的文件系统,主要提供系统一些实时的信息,此目录下不能建立和删除文件;(某些文件可以修改);/proc 主要作用可以整理为:

    • 整理系统内部的信息;

    • 存放主机硬件信息;

    • 调整系统执行时的参数;

    • 检查及修改网络和主机的参数;

    • 检查及调整系统的内存和性能;

    • /proc 下常用的信息文件有:

      • /proc/cpuinfo:cpu的硬件信息,如类型、厂家、型号和性能等
      • /proc/devices:记录所有在 /dev 目录中相关的设备文件分类方式
      • /proc/filesystems:当前运行内核所配置的文件系统
      • /proc/interrupts:可以查看每一个IRQ的编号对应到哪一个硬件设备
      • /proc/loadavg:系统”平均负载”,3个数据指出系统当前的工作负载
      • /proc/dma:当前正在使用的DMA通道
      • /proc/ioports:将目前系统上所有可看到的硬件对应到内存位置的分配表的详细信息呈现出来
      • /proc/kcore:系统上可以检测到的物理内存,主机内存多大,这个文件就有多大
      • /proc/kmsg:在系统尚未进入操作系统阶段,把加载 kernel 和 initrd 的信息先记录到该文件中,后续会将日志信息写入/var/log/message文件中
      • /proc/meminfo:记录系统的内存信息
      • /proc/modules:与lsmod命令查看到的模块信息完全一致
      • /proc/mtrr:负责内存配置的机制
      • /proc/iomem:主要用于储存配置后所有内存储存的明细信息
      • /proc/partitions:这个文件可以实时呈现系统目前看到的分区
      • /proc/数字目录:数字目录很多,它们代表所有目前正在系统中运行的所有程序
      • /proc/bus:有关该主机上现有总线的所有信息,如输入设备、PCI接口、PCMCIA扩展卡及USB接口信息
      • /proc/net:存放的都是一些网络相关的虚拟配置文件,都是ASCII文件,可以查看(与ifconfig、arp、netstat等有关)
      • /proc/scsi:保存系统上所有的scsi设备信息(包括sata和usb设备的信息)
      • /proc/sys :存放系统核心所使用的一些变量,根据不同性质的文件而存放在不同的子目录中,可以通过/etc/sysctl.conf文件设置和更改其默认值;变量时实时的变更,有很多设置很象是开关,设置后马上生效;
      • /proc/tty:存放有关目前可用的正在使用的tty设备的信息
      • /proc/self:存放到查看/proc的程序的进程目录的符号连接,当2个进程查看proc时,这将会是不同的连接;主要便于程序得到它自己的进程目录;
      • /proc/stat:系统的不同状态信息;
      • /proc/uptime:系统启动的时间长度;
      • /proc/version:系统核心版本;
  • /usr:安装除操作系统本身外的一些应用程序或组件,一般可以认为linux系统上安装的应用程序默认都安装在此目录中

    • /usr/bin:一般用户有机会使用到的程序,或者该软件默认就是要让所有用户使用才会放在该目录中

    • /usr/sbin:一些系统有可能会用到的系统命令,与 /sbin 比起来,都是一些较次要的文件;

    • /usr/etc:自行安装或非系统主要的配置文件目录;

    • /usr/games:只要是电脑游戏相关的软件,就都安装到这个目录;

    • /usr/include:存放的文件都是一些系统中用户所会使用到的C语言header文件,保存的都是”.h”的文件;

    • /usr/lib:存放一些函数库、执行文件及连接文件,特别的是,存放在这里面的文件都是不希望直接被用户或shell脚本所使用的文件,在/usr/lib中有非常多的子目录,每一个软件都有其各自所需的函数库;

    • /usr/libexec:这个目录下的文件及文件夹应该都可以放置在/usr/lib下;

    • /usr/local :linux系统中安装的共享软件程序最好的方式是安装在

      /usr/local 下,按照linux标准目录结构,新建立的软件都应该放在/usr/local下;

      • /usr/local/bin:存放软件执行文件的目录;
      • /usr/local/sbin:同样存放软件执行文件的目录,但此目录专门针对系统所使用的文件;
      • /usr/local/lib:软件相关的函数库;
      • /usr/local/share:当文件性质不好归属时就会放在此,man手册就放在这个目录下;
      • /usr/local/src:所安装软件的源代码放置在此;
    • /usr/share :此目录都是一些共享信息,最常被用到的就是

      /usr/share/man 这个目录, /usr/share 里的信息时跨平台的;

      • /usr/share/doc:放置一些系统帮助文件的地方;
      • /usr/share/man:manpage的文件存放目录,也是使用man查看手册页时查询的路径;
    • /usr/src:主要储存内核源代码的文件;

    • /usr/X11R6:存放一些X windows系统的相关文件;

  • /var:动态文件或数据存放目录,默认日志文件都存放在这个目录下,一般建议把此目录单独划分一个分区;

    • /var/empty:默认是sshd程序用到的这个目录,当建立ssh连接,ssh服务器必须使用该目录下的sshd子目录
    • /var/ftp:ftp服务器软件一般默认会将匿名登陆的用户的宿主目录;
    • /var/lib:该目录下存放很多与应用程序名称同名的子目录,每个子目录下都是应用执行的状态信息;
    • /var/lock:每个服务一开始都会在这个目录下产生一个该服务的空文件,主要是避免服务启动冲突;
    • /var/log:常用目录,专门用来存放所有日志文件的目录,里面存放很多系统、软件、用户等相关的日志信息;里面有一些文件是比较常用的;
      • lastlog:记录用户最后一次登录的信息,使用lastlog命令读取;
      • message:记录系统的几乎所有信息,主要包括启动信息,syslogd服务记录的信息等;
      • wtmp:记录所有用户登陆及注销的信息,使用last命令读取;
      • secure:记录登录系统访问数据的文件,如ssh pop3 telnet ftp等都会记录在此文件中
      • btmp:记录失败的用户登录
      • boot.log:记录开机或一些服务启动时所显示的启动和关闭信息
      • /var/log/maillog/var/log/mail/*:记录邮件访问或往来的用户信息
      • cron: 记录 crontab 例行性服务的内容
      • dmesg:开机引导日志信息
      • sudolog:纪录使用sudo发出的命令
      • /var/run:此目录中的大部分文件都记载目前系统正在执行程序的PID值,每一个文件都是以个独立的PID记录;此目录下存放一个特殊文件utmp,此文件记录目前谁在使用系统,必须使用utmpdump命令才能看到其中的内容;
    • /var/spool:里面主要都是一些临时存放,随时会被用户所调用的数据;打印机、邮件、代理服务器等假脱机目录存放在该目录下;
    • /var/tmp:专门为了一些应用程序在安装或执行时,需要在重启后使用的某些文件时,能将该文件暂时存放在这个目录中,完成后再行删除;

查看文件

cat

Linux cat 命令用于获取文件内容并输出到其他设备上(或者文件中),所以有时候也会用于合并文件。

语法

1
cat [-AbeEnstTuv] [--help] [--version] fileName

参数说明:

参数 说明
-n--number 1 开始对所有输出的行数编号
-b--number-nonblank -n 相似,只不过对于空白行不编号
-s--squeeze-blank 当遇到有连续两行以上的空白行,就代换为一行的空白行
-v--show-nonprinting 使用 ^M- 符号,除了 LFD 和 TAB 之外
-E--show-ends 在每行结束处显示 $
-T--show-tabs TAB 字符显示为 ^I
-A, --show-all 等价于 -vET
-e 等价于”-vE“选项
-t 等价于”-vT“选项

例子

把文档 file1 中的内容加上行号后,保存到文档 file2 中:

1
$ cat -n file1 > file2

把两个文件:file1 和 file2 中的内容加上行号(空白行不加)之后合并输出到文件 file3 中:

1
$ cat -b file1 file2 >> file3

由于cat可以输出并重写文档中的内容,所以也可以用来清空文档内容,将一个空内容输出到文件中即可。例如清空 /opt/test.txt 文件中的内容:

1
$ cat /opt/null > /opt/test.txt

cat 也可以用来制作镜像文件。例如要制作软盘的镜像文件,将软盘放好后输入:

1
$ cat /dev/fd0 > OUTFILE

相反的,如果想把 image file 写到软盘,输入:

1
$ cat IMG_FILE > /dev/fd0

将part_开头的文件合并为一个大文件

1
$ cat part_* > merge_file.txt

more

more 命令类似 cat ,不过会以一页一页的形式显示,更方便使用者逐页阅读,而最基本的指令就是按空白键(space)就往下一页显示,按 b 键就会往回(back)一页显示,而且还有搜寻字串的功能(与 vi 相似),使用中的说明文件,请按 h

语法

1
more [-dlfpcsu] [-num] [+/pattern] [+linenum] [fileNames..]

参数说明

参数 说明
-num 一次显示的行数
-d 提示使用者,在画面下方显示 [Press space to continue, ‘q’ to quit.] ,如果使用者按错键,则会显示 [Press ‘h’ for instructions.] 而不是 ‘哔’ 声
-l 取消遇见特殊字元 ^L(送纸字元)时会暂停的功能
-f 计算行数时,以实际上的行数,而非自动换行过后的行数(有些单行字数太长的会被扩展为两行或两行以上)
-p 不以卷动的方式显示每一页,而是先清除萤幕后再显示内容
-c 跟 -p 相似,不同的是先显示内容再清除其他旧资料
-s 当遇到有连续两行以上的空白行,就代换为一行的空白行
-u 不显示下引号 (根据环境变数 TERM 指定的 terminal 而有所不同)
+/pattern 在每个文档显示前搜寻该字串(pattern),然后从该字串之后开始显示
+num 从第 num 行开始显示
fileNames 欲显示内容的文档,可为复数个数

例子

1
2
# 逐页显示 testfile 文档内容,如有连续两行以上空白行则以一行空白行显示。$ more -s testfile
# 从第 20 行开始显示 testfile 之文档内容。$ more +20 testfile

常用操作命令

命令 说明
Enter 向下n行,需要定义。默认为1行
Ctrl+F 向下滚动一屏
空格键 向下滚动一屏
Ctrl+B 返回上一屏
= 输出当前行的行号
:f 输出文件名和当前行的行号
V 调用vi编辑器
!命令 调用Shell,并执行命令
q 退出more

less

less 与 more 类似,less 可以随意浏览文件,支持翻页和搜索,支持向上翻页和向下翻页。

语法

less [参数] 文件

参数说明

参数 说明
-b <缓冲区大小> 设置缓冲区的大小
-e 当文件显示结束后,自动离开
-f 强迫打开特殊文件,例如外围设备代号、目录和二进制文件
-g 只标记最后搜索的关键词
-i 忽略搜索时的大小写
-m 显示类似more命令的百分比
-N 显示每行的行号
-o <文件名> 将less 输出的内容在指定文件中保存起来
-Q 不使用警告音
-s 显示连续空行为一行
-S 行过长时间将超出部分舍弃
-x <数字> 将”tab”键显示为规定的数字空格
/字符串 向下搜索”字符串”的功能
?字符串 向上搜索”字符串”的功能
n 重复前一个搜索(与 / 或 ? 有关)
N 反向重复前一个搜索(与 / 或 ? 有关)
b 向上翻一页
d 向后翻半页
h 显示帮助界面
Q 退出less 命令
u 向前滚动半页
y 向前滚动一行
空格键 滚动一页
回车键 滚动一行
[pagedown] 向下翻动一页
[pageup] 向上翻动一页

例子

1
2
3
# 查看文件$ less log2013.log# ps查看进程信息并通过less分页显示ps -ef |less
# 查看命令历史使用记录并通过less分页显示$ history | less22 scp -r tomcat6.0.32 root@192.168.120.203:/opt/soft23 cd ..24 scp -r web root@192.168.120.203:/opt/25 cd soft26 ls……省略……
# 浏览多个文件$ less log2013.log log2014.log

说明:

输入 :n后,切换到 log2014.log

输入 :p 后,切换到log2013.log

备注

  1. 全屏导航
命令 说明
ctrl+F 向前移动一屏
ctrl+B 向后移动一屏
ctrl+D 向前移动半屏
ctrl+U 向后移动半屏
  1. 单行导航
命令 说明
j 向前移动一行
k 向后移动一行
  1. 其它导航
命令 说明
G - 移动到最后一行
g - 移动到第一行
q / ZZ - 退出 less 命令
  1. 其它有用的命令
命令 说明
v 使用配置的编辑器编辑当前文件
h 显示 less 的帮助文档
&pattern 仅显示匹配模式的行,而不是整个文件
  1. 标记导航
  • 当使用 less 查看大文件时,可以在任何一个位置作标记,可以通过命令导航到标有特定标记的文本位置:
  • ma - 使用 a 标记文本的当前位置
  • ‘a - 导航到标记 a 处

tail

tail 命令可用于查看文件的内容,有一个常用的参数 -f 常用于查阅正在改变的日志文件。

tail -f filename 会把 filename 文件里的最尾部的内容显示在屏幕上,并且不断刷新,只要 filename 更新就可以看到最新的文件内容。

语法

tail [参数] [文件]

参数

命令 说明
-f 循环读取
-q 不显示处理信息
-v 显示详细的处理信息
-c<数目> 显示的字节数
-n<行数> 显示文件的尾部 n 行内容
--pid=PID 与-f合用,表示在进程ID,PID死掉之后结束
-q,--quiet,--silent 从不输出给出文件名的首部
-s,--sleep-interval=S 与-f合用,表示在每次反复的间隔休眠S秒

例子

1
2
# 要显示 notes.log 文件的最后 10 行,请输入以下命令:$ tail notes.log         # 默认显示最后 10 行
# 要跟踪名为 notes.log 的文件的增长情况,请输入以下命令:$ tail -f notes.log

此命令显示 notes.log 文件的最后 10 行。当将某些行添加至 notes.log 文件时,tail 命令会继续显示这些行。显示一直继续,直到您按下(Ctrl-C)组合键停止显示。

1
2
# 显示文件 notes.log 的内容,从第 20 行至文件末尾:$ tail -n +20 notes.log
# 显示文件 notes.log 的最后 10 个字符:$ tail -c 10 notes.log

查看日志

查看日志常用命令

tail

-n 是显示行号;相当于nl命令;例子如下:

tail -100f test.log 实时监控100行日志

tail -n 10 test.log 查询日志尾部最后10行的日志;

tail -n +10 test.log 查询10行之后的所有日志;

跟tail是相反的,tail是看后多少行日志;例子如下:

head -n 10 test.log 查询日志文件中的头10行日志;

head -n -10 test.log 查询日志文件除了最后10行的其他所有日志;

cat

tac是倒序查看,是cat单词反写;例子如下:

cat -n test.log |grep "debug" 查询关键字的日志

应用场景

应用场景一

按行号查看—过滤出关键字附近的日志

  • cat -n test.log |grep "debug" 得到关键日志的行号
  • cat -n test.log |tail -n +92|head -n 20 选择关键字所在的中间一行. 然后查看这个关键字前10行和后10行的日志:
  • tail -n +92 表示查询92行之后的日志
  • head -n 20 则表示在前面的查询结果里再查前20条记录

应用场景二

根据日期查询日志

  • sed -n '/2014-12-17 16:17:20/,/2014-12-17 16:17:36/p' test.log

特别说明:上面的两个日期必须是日志中打印出来的日志,否则无效;

grep '2014-12-17 16:17:20' test.log 来确定日志中是否有该 时间点

应用场景三

日志内容特别多,打印在屏幕上不方便查看

  • 使用more和less命令,

    如: cat -n test.log |grep "debug" |more 这样就分页打印了,通过点击空格键翻页

  • 使用 >xxx.txt 将其保存到文件中,到时可以拉下这个文件分析

    如:cat -n test.log |grep "debug" >debug.txt

文件基本操作

cp

cp 命令主要用于复制目录或者普通文档(为方便表达,本文中所说的 “文件” 均为普通文档。)。

语法

1
cp [options] source dest

参数说明

参数 说明
-a 通常用于复制目录,保留链接和文件属性,并复制目录下的所有内容。相当于 dpr 三个参数的组合;
-d 复制时保留链接(类似于windows系统中的快捷方式);
-f 覆盖已经存在的目标文件(没有提示);
-i 也是覆盖已经存在的目标文件,但是会给出提示,提示用户是否确认要覆盖。
用户输入 y 指令的时候,目标文件将被覆盖,否则操作会撤销;
-l 不复制文件,只是生成链接文件(即快捷方式);
-p 该参数的作用是,除复制文件的内容外,还把修改时间和访问权限也复制到新文件中;
-r 若给出的源文件是一个目录文件,则将复制该目录下所有的子目录和文件。

例子

将目录 test/ 下的所有文件复制到新目录 test2下:

1
$ cp –r test/ test2

注意:用户使用 cp 命令复制目录时,必须使用参数 -r 或者 -R ,以将目录下的子目录和文件也同步复制。

mv

mv 命令用于移动文件,将文件或目录移动到其它位置,如果是源地址和目标地址相同,则会将文件改名。

语法

1
mv [options] source dest

参数说明

参数 说明
-b 当目标文件或目录存在时,在执行覆盖前,会为其创建一个备份;
-f 如果指定移动的源目录或文件与目标的目录或文件同名,不会询问,直接覆盖旧文件;
-i -f 参数功能类似,只是在将文件覆盖之前会给出提示,让用户确认。
输入 y 表示直接覆盖,输入 n 表示取消该操作;
-n 不要覆盖任何已存在的文件或目录,对于已经存在的文件,则会直接跳过;
-u 当源文件比目标文件新或者目标文件不存在时,才执行移动操作。

mv 命令在使用的时候,对于目的文件和源文件,区分是文件还是目录,执行结果是不一样的,例如:

  1. 将源文件名 source_file 改为目标文件名 dest_file

    1
    mv source_file(文件) dest_file(文件)
  2. 将文件 source_file 移动到目标目录 dest_directory 中

    1
    mv source_file(文件) dest_directory(目录)
  3. 移动目录

    若目录名 dest_directory 已存在,将 source_directory 移动到目录名 dest_directory 中;

    若目录名 dest_directory 不存在则 source_directory 改名为目录名 dest_directory

    1
    mv source_directory(目录) dest_directory(目录)
  4. 错误操作

    1
    mv source_directory(目录) dest_file(文件)

例子

  1. 将文件 file1 改名为 file2:
1
$ mv file1 file2
  1. 将 test 目录放入 test2 目录中。注意,如果 test2目录不存在,则该命令将 test改名为 logs。
1
$ mv test/ test2
  1. 将 /opt/logs下的所有文件和目录移到当前目录下,命令行为:
1
$ mv /opt/logs/*  .

移动隐藏文件

1
mv * .[^.]* <destination_directory>

解释

1、mv命令的最后一个参数是要移动文件的目标位置;
2、第一个 * 匹配除了隐藏文件的所有文件;
3、隐藏文件使用 .[^.]* 匹配
4、匹配隐藏文件用 .[^.]* 为什么不用 .*: .* 会匹配目录 ...
5、.[^.]* 的意思是:以 . 开头,加不是 . 的一个任意字符,再加其他任意字符

参数补充

参数说明:

参数 说明
-b 当目标文件或目录存在时,在执行覆盖前,会为其创建一个备份。
-i 如果指定移动的源目录或文件与目标的目录或文件同名,则会先询问是否覆盖旧文件,
输入 y 表示直接覆盖,输入 n 表示取消该操作。
-f 如果指定移动的源目录或文件与目标的目录或文件同名,不会询问,直接覆盖旧文件。
-n 不要覆盖任何已存在的文件或目录。
-u 当源文件比目标文件新或者目标文件不存在时,才执行移动操作。

rm

英文全拼:remove, 命令用于删除一个文件或者目录。

语法

1
rm [options] name...

参数

参数 说明
-i 删除前逐一询问确认。
-f 即使原档案属性设为唯读,亦直接删除,无需逐一确认。
-r 将目录及以下之档案亦逐一删除。

例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#删除文件可以直接使用rm命令,若删除目录则必须配合选项"-r"
$ rm test.txt
rm:是否删除 一般文件 "test.txt"? y


$ rm homework
rm: 无法删除目录"homework": 是一个目录


$ rm -r homework
rm:是否删除 目录 "homework"? y


# 删除当前目录下的所有文件及目录,命令行为:
rm -r *

文件一旦通过rm命令删除,则无法恢复,所以必须格外小心地使用该命令。

rmdir

英文全拼:remove directory)命令删除空的目录

语法

1
rmdir [-p] dirName

参数

参数 说明
-p 当子目录被删除后使它也成为空目录的话,则顺便一并删除。

例子

1
2
3
4
5
# 将工作目录下,名为 AAA 的子目录删除 :
$ rmdir AAA

# 在工作目录下的 BBB 目录中,删除名为 Test 的子目录。若 Test 删除后,BBB 目录成为空目录,则 BBB 亦予删除。
$ rmdir -p BBB/Test

touch

Linux touch 命令可用于修改系统中文件时间属性,比如文件的存储、读取时间和修改时间。如果文件不存在,系统会创建一个新的文件。

使用touch命令后,可以执行 ls -l 命令可以显示档案的时间记录。

语法

1
touch [-acfm] [-d<日期时间>] [-r<参考文件或目录>] [-t<日期时间>] [--help] [--version] [文件名称]

参数说明

参数 说明
a 修改文件的读取时间
m 重新设置文件的修改时间
c 假如目的文件不存在,不会建立新的文件,与 --no-create 的效果一样。
f 一般不使用,该参数是为了与其他 unix 系统的相容性而保留。
r 使用参考文件的时间记录,与 --file 的效果一样。
d 设定时间与日期,可以使用各种不同的格式。
t 设定文件的时间记录,格式与 date 指令相同。
--no-create 不会建立新文件。
--help 显示帮助。
--version 显示版本信息。

例子

使用命令 “touch“ 修改文件”filename”的时间属性为当前系统时间:

1
2
#修改文件的时间属性
$ touch filename

首先,使用ls命令查看filename文件的属性,如下所示:

1
2
3
4
5
#查看文件的时间属性
$ ls -l filename

#原来文件的修改时间为16:09
-rw-r--r-- 1 hdd hdd 55 2011-08-22 16:09 filename

执行指令”touch“修改文件属性以后,并再次查看该文件的时间属性,如下所示:

1
2
3
4
5
6
7
8
# 修改文件时间属性为当前系统时间
$ touch filename

#查看文件的时间属性
$ ls -l filename

#修改后文件的时间属性为当前系统时间
-rw-r--r-- 1 hdd hdd 55 2011-08-22 19:53 filename

使用指令 touch 时,如果指定的文件不存在,则将创建一个新的空白文件。例如,在当前目录下,使用该指令创建一个空白文件”file”,输入如下命令:

1
2
#创建一个名为“file”的新的空白文件 
$ touch file

mkdir

mkdir 是每个Linux用户都应该知道的基本Linux命令之一。你可以使用mkdir创建新目录(文件夹)。

在本文中将介绍mkdir命令。

mkdir 命令是为数不多的没有太多选项的Linux命令之一。这使得它的使用非常简单。

这是它的语法:

1
mkdir [option] directory_name_or_path

下面我们来看一下怎么使用。

创建新目录

要创建新目录,使用mkdir命令(不带任何参数):

1
mkdir new_dir

这样会在当前目录下新建一个名为 new_dir 的目录。可以使用ls命令查看:

1
2
3
4
5
$ ls
$ mkdir new_dir
$ ls -l
total 4
drwxrwxr-x 2 abhishek abhishek 4096 May 14 16:15 new_dir

你还可以指定要创建新目录的路径。

1
2
3
4
5
6
7
8
9
10
11

$ ls
new_dir
$ mkdir new_dir/another_new_dir
$ tree
.
└── new_dir
└── another_new_dir


2 directories, 0 files

创建多个目录

还可以使用一个命令创建多个目录:

1
mkdir new_dir_1 new_dir_2 new_dir_3

使用上面的命令创建的新目录,都在同一个路径下(即当前路径)。另外,你还可以创建嵌套目录,下面我们来介绍如何创建嵌套目录。

创建嵌套目录

您可以使用选项 -p 来创建嵌套目录结构。如果父目录不存在,将会自动创建。当你要创建目录结构或要确保目录路径存在时,这尤其有用。

1
2
3
4
5
6
7
8
9
10
11
12
$ mkdir -p dir1/dir2/dir3/dir4
$ tree
.
├── dir1
│ └── dir2
│ └── dir3
│ └── dir4
└── new_dir
└── another_new_dir


6 directories, 0 files

也可以对单个目录使用 -p 选项。如果要创建的目录已经存在了,那就会跳过,而且不报错:

1
2
3
4
5
6
7
$ mkdir new_dir
mkdir: cannot create directory ‘new_dir’: File exists
$ mkdir -p new_dir
$ ls -l
total 8
drwxrwxr-x 3 abhishek abhishek 4096 May 14 16:39 dir1
drwxrwxr-x 3 abhishek abhishek 4096 May 14 16:16 new_dir

创建具有特定权限的目录

默认情况下,shell 的 umask 控制对新建目录的权限。如果希望对新创建的目录拥有不同的文件权限,你可以先创建,然后使用chmod命令更改权限。当然,还有一种更好的办法,就是使用 -m 选项。

假设要对要创建的目录拥有766权限,可以使用如下命令:

1
mkdir -m 766 new_directory

pwd

显示当前目录(Print working directory)

pwd 命令打印你当前的工作目录,也就是说,它输出你当前正在使用的目录的路径。有两个选项:

  • --logical 用于显示带有任何符号链接的位置
  • --physical 用于在解析符号链接后显示你的位置。

文件进阶操作

ln

链接是对另一个文件的引用,它为同一文件提供多个名称,并允许它们同时位于两个或多个位置。

有两种类型的链接:

  • 软连接:也称为符号链接,原始文件的快捷方式;
  • 硬链接:这将指向原始文件的内存位置。

下图显示了两种链接的工作方式:

硬链接和软链接都是使用 ln 命令创建的,本文将会介绍如何使用 ln 命令在 Linux 中创建各种类型的链接。

ln 命令示例

ln 命令的语法很简单:

1
ln [option] target_file link_name

下面我们通过例子来具体看一下。

创建指向文件的硬链接

创建指向文件的硬链接,可在不添加任何选项的情况下使用 ln 命令,如下:

1
ln target_file link_name

创建指向文件的软连接

要创建指向文件的软连接,使用 ln 命令的 -s 选项:

1
ln -s target_file link_name

ls -l 命令的输出列表中,大多数 LInux 终端都会以不同颜色显示软链接及其指向的目标;同时链接都会以 l 开头,而不是普通文件的 -,这也是识别链接的一种方式。

创建指向目录的软链接

创建指向目录的软链接与创建指向文件的软链接方法相同,将文件名替换为目录名即可:

1
ln -s target_directory link_name

你可能会注意到了,在 Linux 终端中,软链接和硬链接的颜色是不同的,一般情况下,无法创建指向目录的硬链接

更新已有的软链接(或硬链接)

链接是可以被覆盖的。默认情况下,如果你使用一个已有的链接指向一个新文件,会报错:

1
ln: failed to create symbolic link 'soft-link-to-file': File exists

要覆盖现有链接,有两种方式(即 ln 命令的两个选项):

  • -i:系统会询问你是否要覆盖现有链接;
  • -f:强制覆盖现有链接,不会给确认信息。

比如,我们要强制覆盖一个现有链接,看下面的例子:

1
ln -sf new_file existing_soft_link

在这里需要注意,如果是要覆盖一个软链接的话,需要添加 -s 选项,否则会将软链接转换为硬链接。

通过链接链获取原始文件

通常情况下,使用 ls -l 命令来查看文件的时候,链接会显示它所指向的文件。

但如果存在链接链的话,则不会显示原始文件。例如,创建指向文件的链接,然后创建指向第一个链接的另一个链接;在长列表的输出中,第二个链接将指向第一个链接。

要从链接链中找到原始文件,可以使用 readlink -f 命令,如下所示:

1
readlink -f soft_link

选项 -f 表示 follow,即 follow the chain。

为什么会需要链接

上面我们介绍了如何创建链接,接下来我们再来了解下链接的实际用途。

假设我们下载了一个包含有代码和可执行文件的软件,然后我们将整个软件放在了 /opt 目录中。但是如果想要从任何路径下都可以运行该程序,那需要将可执行文件放到 /usr/bin 目录下。

如果我们将可执行文件放到 /usr/bin 目录下以后,它可能不会正常运行,因为它需要访问某些代码(即随同文件一起被下载的那些代码),但是在 /usr/bin 目录下无法找到这些代码文件。这种情况下,我们就可以在 /usr/bin 目录中创建指向该可执行文件的链接,而不是把可执行文件移动到该目录下。

这样,程序就可以在系统的任何地方运行,其可执行文件仍会保留在原地方。

链接是 Linux 的重要组成部分,它在应用在很多地方。在系统的 /lib 目录下,会有很多软链接存在。

split

split命令用于将一个文件分割成数个。该指令将大文件分割成较小的文件,在默认情况下将按照每1000行切割成一个小文件。

语法

1
split [--help][--version][-<行数>][-b <字节>][-C <字节>][-l <行数>][要切割的文件][输出文件名]

参数说明

参数 说明
-<行数> 指定每多少行切成一个小文件
-b<字节> 指定每多少字节切成一个小文件,二进制分割模式(支持单位:KB, MB)
--help 在线帮助
--version 显示版本信息
-C<字节> 与参数”-b“相似,但是在切割时将尽量维持每行的完整性
[输出文件名] 设置切割后文件的前置文件名, split会自动在前置文件名后再加上编号

例子

使用指令”split“将文件”README”每6行切割成一个文件,输入如下命令:

1
$ split -6 README       #将README文件每六行分割成一个文件 

以上命令执行后,指令”split“会将原来的大文件”README”切割成多个以”x”开头的小文件。而在这些小文件中,每个文件都只有6行内容。

使用指令”ls“查看当前目录结构,如下所示:

#执行ls指令查看当前目录列表

1
2
$ ls  
README xaa xad xag xab xae xah xac xaf xai
1
2
3
4
5
6
# 按行数分割
$ split -l 300 large_file.txt new_file_prefix
# 加上-d,使用数字后缀;加上–verbose,显示分割进度
$ split -l 50000 -d large_file.txt part_ –verbose
# 按字节大小分割
$ split -b 10m large_file.log new_file_prefix

此外,可以使用 split –help 或者 split –h来查看帮助信息:

1
2
3
4
$ splithelp
Usage: split [OPTION]… [FILE [PREFIX]]
Output pieces of FILE to PREFIXaa, PREFIXab, …;
default size is 1000 lines, and default PREFIX is 'x'.

文件分割后还可以合并,使用cat命令。

在 Linux 中删除文件,我们通常使用 rm 命令。除此以外,还有另外一个命令,可以用于删除文件和链接,这就是 unlink 命令。虽然它听起来像是只能删除 Linux 系统中的链接,但实际上,也可以删除文件。

Linux 系统中删除文件的过程是非常迅速的,只是一瞬间。当你删除文件时,Linux 内核发现它对应于索引节点编号 X,系统会将其从目录列表中删除文件条目,并将索引节点 X 的链接计数减少1,这时候,索引节点 X 的链接计数为0,内核会认为没有人链接到此索引节点,所以就可以安全的删除索引节点,并删除与其关联的数据块。

如前文所述,unlink 命令用于删除文件和链接,其中链接包括软链接和硬链接。它是最简单的命令之一,除了 --help 以及 --version 以外,没有任何其他选项。

使用 unlink 删除文件,可以这样:

1
unlink filename

删除链接,可以这样使用:

1
unlink link_name

删除成功后,不会有任何输出:

这就是 unlink 命令的功能,除此以外不做任何其他事情。

rm 命令可以一次删除多个文件。但是 unlink 却不能,它一次只能删除一个文件或者链接,而且,也不能使用全局模式(globbing patterns)。

如果我们尝试给定多个文件的话,它会抛出一个错误,执行失败:

1
[gliu@fedora ~]$ unlink *.txtunlink: extra operand ‘file2.txt’Try 'unlink --help' for more information.

同时删除多个链接也会如此。

GNU 实现下的 unlink 命令是无法删除目录的,如果给定的文件名称是一个目录,就会报错:

1
[gliu@fedora ~]$ unlink new_dirunlink: cannot unlink 'new_dir': Is a directory

unlink 命令使用 unlink 系统命令,而 rm 命令使用 unlinkat 系统调用,两个系统调用几乎相同。但是这两个命令之间还是有一些明显的差异。

如前文所述,unlink 命令在同一时间只能删除一个文件或链接,而 rm 命令可以删除多个unlink 命令不能删除目录,而 rm 命令能删除目录

rm 命令在执行的时候,首先会安全检查,如果你没有文件的写权限,那么系统会要求你给出写权限(sudo或者切换至管理员用户),或者使用强制删除选项 -f;而 unlink 则不会进行安全检查,直接删除文件。

另外,与 rm 不同,unlink 没有其他选项。

在某些情况下,相比于 rm,你可能更喜欢使用 unlink。比如你希望强制删除一个文件,而不考虑安全或者权限问题;或者如果删除失败(比如文件不存在)的话你希望能看到报错信息,这种情况下就可以使用 unlink。因为使用 rm -f 强制删除文件,如果文件不存在的话,不会显示任何错误信息。

stat

使用stat命令检查Linux上的文件状态

GNU coreutils包中包含的stat命令提供了各种元数据,包括文件大小、inode位置、访问权限和SELinux上下文,以及关于文件和文件系统的创建和修改时间。这是一种收集信息的便捷方法,通常需要使用多个不同的命令来获取这些信息。

在Linux中安装stat

在Linux上,你可能已经安装了stat命令,因为它是核心程序包的一部分,默认情况下通常与Linux发行版捆绑在一起。

如果没有安装stat,可以使用包管理器安装coreutils。

或者,你可以下载源代码编译coreutils, 下载地址

获取文件的状态

运行stat提供一个关于特定文件或目录的易读的输出:

1
2
3
4
5
6
7
8
9
10
$ stat planets.xml
File: planets.xml
Size: 325 Blocks: 8 IO Block: 4096 regular file
Device: fd03h/64771d Inode: 140217 Links: 1
Access: (0664/-rw-rw-r--) Uid: (1000/tux) Gid: (100/users)
Context: unconfined_u:object_r:user_home_t:s0
Access: 2021-08-17 18:26:57.281330711 +1200
Modify: 2021-08-17 18:26:58.738332799 +1200
Change: 2021-08-17 18:26:58.738332799 +1200
Birth: 2021-08-17 18:26:57.281330711 +1200

它可能很容易阅读,但仍然有很多信息。以下是stat所涵盖的内容:

参数 说明
File 文件名
Size 以字节为单位的文件大小
Blocks 硬盘上为此文件保留的块数
IO Block 文件系统块的大小
regular file 文件类型(常规文件、目录、文件系统)
Device 文件所在的设备
Inode 文件所在的索引节点号
Links 指向该文件的链接数
Access, UID, GID 文件权限、用户和组所有者
Context SELinux 上下文
Access, Modify, Change, Birth 访问、修改、更改状态和创建文件的时间戳

简洁输出

对于非常了解输出的人,或者希望使用其他实用程序(如awk)解析输出的人,可以使用 –terse(-t)选项,该选项可以格式化输出,而不使用标题或换行符。

1
2
$ stat --terse planets.xml
planets.xml 325 8 81b4 100977 100 fd03 140217 1 0 0 1629181617 1629181618 1629181618 1629181617 4096 unconfined_u:object_r:user_home_t:s0

选择自己的格式

你可以使用--printf选项和类似于printf的语法定义自己的输出格式。stat报告的每个属性都有一个格式序列(%C表示SELinux上下文,%n表示文件名,等等),因此你可以选择希望在报告中看到的内容。

1
2
3
4
5
6
$ stat --printf="%n\n%C\n" planets.xml
planets.xml
unconfined_u:object_r:user_home_t:s0
$ $ stat --printf="Name: %n\nModified: %y\n" planets.xml
Name: planets.xml
Modified: 2021-08-17 18:26:58.738332799 +1200

以下是一些常见的格式序列:

参数 说明
%a 访问权限
%F 文件类型
%n 文件名称
%U 用户名称
%u 用户ID
%g 组 ID
%w 创建时间
%y 修改时间

详情大家可以参考stat手册或者coreutils手册。

文件信息

如果你曾经尝试过解析ls -l的输出,那么你会喜欢stat命令的灵活性。你并不总是需要stat提供的所有默认信息,但是当你确实需要部分或全部信息时,该命令是很好用的。无论你是以默认格式读取其输出,还是创建自己的查询,stat命令都可以让你轻松访问有关数据的数据。

blkid

查看块设备的文件系统类型、LABEL、UUID等信息

在Linux下可以使用 blkid命令 对查询设备上所采用文件系统类型进行查询。blkid主要用来对系统的块设备(包括交换分区)所使用的文件系统类型、LABEL、UUID等信息进行查询。要使用这个命令必须安装e2fsprogs软件包。

语法

1
2
3
4
$ blkid -L | -U
$ blkid [-c ] [-ghlLv] [-o] [-s ][-t ] -[w ] [ ...]
$ blkid -p [-s ] [-O ] [-S ][-o] ...
$ blkid -i [-s ] [-o] ...

选项

参数 说明
-c <file> 指定cache文件(default: /etc/blkid.tab, /dev/null = none)
-d don’t encode non-printing characters
-h 显示帮助信息
-g garbage collect the blkid cache
-o <format> 指定输出格式
-k list all known filesystems/RAIDs and exit
-s <tag> 显示指定信息,默认显示所有信息
-t <token> find device with a specific token (NAME=value pair)
-l look up only first device with token specified by -t
-L <label> convert LABEL to device name
-U <uuid> convert UUID to device name
-v 显示版本信息
-w <file> write cache to different file (/dev/null = no write)
<dev> specify device(s) to probe (default: all devices)

Low-level probing options

参数 说明
-p low-level superblocks probing (bypass cache)
-i gather information about I/O limits
-S <size> overwrite device size
-O <offset> probe at the given offset
-u <list> filter by “usage” (e.g. -u filesystem,raid)
-n <list> filter by filesystem type (e.g. -n vfat,ext3)

实例

  1. 列出当前系统中所有已挂载文件系统的类型:

    1
    sudo blkid
  2. 显示指定设备 UUID:

    1
    sudo blkid -s UUID /dev/sda5
  3. 显示所有设备 UUID:

    1
    sudo blkid -s UUID
  4. 显示指定设备 LABEL:

    1
    sudo blkid -s LABEL /dev/sda5
  5. 显示所有设备 LABEL:

    1
    sudo blkid -s LABEL
  6. 显示所有设备文件系统:

    1
    sudo blkid -s TYPE
  7. 显示所有设备:

    1
    sudo blkid -o device
  8. 以列表方式查看详细信息:

    1
    sudo blkid -o list

mount和umount

mount

1
$ mount [-t vfstype] [-o options] device dir

特别地, 指定 NTFS

1
mount -t ntfs3 /dev/sdxY /mnt

参数讲解

  • -t vfstype 指定文件系统的类型,通常不必指定,mount 会自动选择正确的类型

    参数 说明
    iso9660 光盘或光盘镜像
    msdos DOS fat16文件系统
    vfat Windows 9x fat32文件系统
    ntfs Windows NT ntfs文件系统
    smbfs Mount Windows文件网络共享
    nfs UNIX(LINUX) 文件网络共享

    查看文件系统的类型见这里

  • -o options 主要用来描述设备或档案的挂接方式

    参数 说明
    loop 用来把一个文件当成硬盘分区挂接上系统
    ro 采用只读方式挂接设备
    rw 采用读写方式挂接设备
    iocharset 指定访问文件系统所用字符集
  • device 要挂接(mount)的设备

  • dir设备在系统上的挂接点(mount point)

卸载磁盘时报错:’Umount Target is Busy’

原因很简单,要卸载的目标设备还仍在使用中。

如果有足够的权限,任何进程都可能正在使用你即将要卸载的驱动器。为了防止数据丢失,所以系统内核不允许你将其卸载。

那么怎么解决这个问题呢?

提示:如果后台正在进行数据传输,可能会因为强制卸载驱动器而造成数据丢失。

基于某种原因,有时候我们需要强制卸载驱动器。比如因某种原因造成的驱动器没有相应。强制卸载驱动器有多种方法,比如:

  • 杀掉进程;
  • 使用强制卸载(force unmount)
  • 使用延迟卸载(lazy unmount)

我们先来看看第一种方法。

方法1:通过杀掉进程来强制卸载驱动器

这应该是强制卸载磁盘驱动器的最佳方式,因为不管怎样,你都会杀掉这个进程。

首先第一步是要找到造成该问题的进程的 PID。可以使用 lsof 命令,如下所示:

1
sudo lsof /Path/to/target

找到 pid 后,要终止这个进程就很简单了:

1
sudo kill -9 [PID]

终止进程后,再次执行磁盘驱动器 umount 命令就可以了:

方法2:强制卸载(适用于网络文件系统 Network file systems)

当处理网路文件系统的时候,强制卸载是遇到 ‘umount: target is busy’ 问题时首选的方法。但是对于本地文件系统,其结果可能会不一样。

强制卸载磁盘,可以使用 umount 命令的 -f 选项,如下所示:

1
sudo umount -f /Path/to/target

方法3:使用延迟卸载(lazy unmount)

该方法不会立刻卸载目标,而只是将其从命名空间中删除掉。当目标驱动器不被使用的时候,再将其卸载掉。使用这个方法,你可能无法确定目标是否已经被卸载掉,这就像薛定谔的卸载。我们之所以介绍这种方法,是因为它是最柔和(无害)的一种方法。

使用延迟卸载,可以在 umount 命令中添加 -l 选项,如下所示:

1
sudo umount -l /Path/to/target

上述我们介绍的三种方法中,我更倾向于使用第一种方法,即直接杀掉占用磁盘的进程。当然大家可以根据各自实际情况选择合适的方法。

grub

不显示grub启动项

方法1

启动时候一直按住shift键

以前的Ubuntu版本,启动grub的时候,有一个grub loading,press ESC to get the menu的提示,所以按ESC就可以看到grub界面

现在的Ubuntu没有了,现在的做法是,启动的时候按住shift键,就可以看到grub界面了。

(接下来就修改启动参数,加入single,然后按ctrl+x启动,就能看到一个ncurse的界面,选择drop to root prompt,就可以得到一个root的terminal然后就可以重新设置root口令了)

方法2

  1. sudo gedit /etc/default/grub

    修改如下:

    1
    2
    3
    GRUB_HIDDEN_TIMEOUT=0
    #GRUB_HIDDEN_TIMEOUT_QUIET=true
    GRUB_TIMEOUT=0
  2. sudo update-grub

说明

  1. GRUB_HIDDEN_TIMEOUT=0

    1
    2
    3
    4
    5
    6
    7
    此配置将影响菜单显示。若设置此选项,将在此时间内隐藏菜单而显示引导画面。
    菜单将会被隐藏,除非在此行开头加上一个 # 符号。(# GRUB_HIDDEN_TIMEOUT=0)。
    GRUB 2 第一次执行时将会寻找其他操作系统。若没有其他操作系统被检测到,菜单将会配置为隐藏。若辨认出其他操作系统,菜单将会显示。
    若是大于 0 的整数,系统将会依此配置的秒数暂停,但不会显示菜单。
    0 则菜单不会显示,也不会有延迟。
    使用者可以在启动时按住 SHIFT 键不放以强制显示菜单。
    启动过程中,系统将会检查 SHIFT 键状态。若无法辨识按键状态,会有一个短时间的延迟让使用者可通过按下 ESC 键来显示菜单。

2.GRUB_HIDDEN_TIMEOUT_QUIET=true

1
2
true 不显示倒计时。屏幕将会是空白的。
false 在 GRUB_HIDDEN_TIMEOUT 中配置的时间,空白屏幕上会有一个倒数计时器。

3.GRUB_TIMEOUT=10

1
2
3
此命令将顺从 GRUB_HIDDEN_TIMEOUT 配置,除非 GRUB_HIDDEN_TIMEOUT 被注释掉(#)。若 GRUB_HIDDEN_TIMEOUT 启用,则当菜单显示时,GRUB_TIMEOUT 将会只执行一次。
配置此值为 -1 将会导致菜单一直显示,直到用户选择。
GRUB 2 菜单默认为隐藏,除非其他操作系统被系统检测到。若没有其他操作系统,此行将会被注释掉,除非使用者修改它。为了在每次启动时显示菜单,去掉此行的注释并使用 1 或更大的值。

references