Linux学习笔记 #2 高级的Shell与文件管理

本文最后更新于:2023年12月30日 下午

在前文的基础上,记录了 Linux 中如何充分利用 Shell 命令,以及对文件权限的管理。

本文部分内容参考了清华 ZAH 同学的教程,部分参考了 刘遄 老师的《Linux 就该这么学》,菜鸟教程-Linux

高级的 Shell

Linux 中可以将简单的 Shell 命令组合以发挥更大的作用,常见的如:与文件读写操作有关的重定向技术、处理命令输出值的管道命令符、通配符和转义字符等。这些技巧在 Shell 脚本批处理中十分常用。

输入输出重定向

输入重定向是指把文件导入到命令中,而输出重定向则是指把原本要输出到屏幕的数据信息写入到指定文件中。

日常的学习和工作中,使用输出重定向的频率更高,所以又将输出重定向分为了标准输出重定向和错误输出重定向两种不同的技术,以及覆盖写入追加写入两种模式。

错误信息的输出对于执行一个自动化的 Shell 脚本非常有用,它可以把整个脚本执行过程中的报错信息都记录到文件中,便于安装后的排错工作。

对于输入重定向,格式如下:

格式功能
命令 < 文件将文件作为命令的标准输入
命令 << 分界符从键盘输入中读入两个分界符 tag 之间的内容
命令 < 文件A > 文件B将文件 A 作为命令的输入并将标准输出到文件 B

通常用输入重定向能做的事情,直接执行该命令也能做(命令通常会自带文件输入的功能),因此使用频率较低。

对于输出重定向,格式如下:

格式功能
命令 > 文件将标准输出重定向到一个文件中(清空原有文件的数据)
命令 >> 文件将标准输出重定向到一个文件中(追加到原有内容的后面)
命令 2> 文件将错误输出重定向到一个文件中(清空原有文件的数据)
命令 2>> 文件将错误输出重定向到一个文件中(追加到原有内容的后面)

上述命令中的 2 就是文件描述符(File Descriptor),必须和重定向符号紧贴才能生效。在 Linux 中有三种文件描述符:

  • 0 表示标准输入(STDIN), <<< 的默认输入
  • 1 表示标准输出(STDOUT),>>> 的默认输出
  • 2 表示标准错误输出(STDERR),通常需要重定向才能显示
  • & 放在 > 前可以同时表示标准输出和标准错误输出,意味着所有输出都会被重定向

有时候会看见把 2>&1 放在命令的最后的用法,表示「将标准错误输出重定向到标准输出」,其中 & 的作用是合并命令,如果只保留 2>1 则会将标准错误输出重定向到名为 1 的文件中。

一个容易混淆的 & 用法是将其放在命令的最后,此时表示「在后台运行命令」。它允许你在执行命令后立即返回到终端或命令行界面,而不必等待命令完成。这对于运行长时间任务或需要持续运行的程序很有用。

管道命令符

管道命令符 | 用于把前一个命令原本要输出到屏幕的信息当作后一个命令的标准输入,就像一个「管道」连接了两条命令一样,其本质是创建一个临时文件用以读写。

下面用一些例子来展示管道命令符的巧妙之处:

1
2
3
4
5
$ grep /sbin/nologin /etc/passwd | wc -l 	# 抓取文件中含 /sbin/nologin 的行,统计行数
$ ls -lah /etc/ | more # 罗列目录下的文件信息,用翻页的形式查看
$ ls -lah usr/bin | grep echo # 罗列目录下的文件信息,抓取 echo 文件
$ ps aux | grep bash # 显示全部进程,抓取 bash 的进程信息
$ python run.py | tee -a run.log # 将函数的标准输出附加到 log 文件

此外,管道命令符在一条命令中还可以多次复用,完成更复杂的工作。

但是,由于管道运算符实现的本质,它默认会将前者的输出作为一整个临时文件传给后者,而有时候我们却需要拆散这个文件,依次输入到后者,这时就需要这个命令:

  • xargs:代表 eXtended ARGuments,管道命令传递参数的一个过滤器,格式为:命令1 | xargs [参数] 命令2

通配符

在 Git 学习中,已经介绍了一些常用的通配符,这里附上完整表格:

通配符含义
*任意字符
?单个任意字符
[a-z]单个小写字母
[A-Z]单个大写字母
[a-Z]单个字母
[0-9]单个数字
[[:alpha:]]任意字母
[[:upper:]]任意大写字母
[[:lower:]]任意小写字母
[[:digit:]]所有数字
[[:alnum:]]任意字母加数字
[[:punct:]]标点符号

转义字符

转义字符通常用于避免命令的歧义,最常用的有如下几种:

  • 反斜杠 \:使反斜杠后面的一个保留字符变为单纯的字符。
  • 单引号 ‘’:转义其中所有的变量为单纯的字符串。
  • 双引号 “”:保留其中的变量属性,不进行转义处理。

环境变量

回归一个最本质的问题,当我们在 Shell 环境中输入一条命令时(我们知道这条命令其实是一个 C 编写的程序),Shell 是如何找到这个程序的呢?

首先,Shell 会用户是否以绝对路径或相对路径的方式输入命令(如 /bin/ls),如果是绝对路径则直接执行。如果不是,系统则需要在多个路径中查找用户输入的命令文件,而定义这些路径的变量就叫作 PATH。我们可以通过如下命令来查看:

1
2
$ echo $PATH  # 符号 $ 表示输出环境变量的值
/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/root/bin

可以看到,PATH 文件中含有多个量,都是这条命令可能存放的位置,于是解释器会在这些位置中逐个查找。

当然,为了 Linux 这样庞大系统的运行,类似的环境还有许多,我们可以使用 env 命令来查看所有环境变量。这里列出常用的一些变量:

变量名称含义
HOME用户的主目录(即家目录)
SHELL用户在使用的 Shell 解释器名称
HISTSIZE输出的历史命令记录条数
HISTFILESIZE保存的历史命令记录条数
MAIL邮件保存路径
LANG系统语言、语系名称
RANDOM生成一个随机数字
PS1Bash 解释器的提示符
PATH定义解释器搜索用户执行命令的路径

PATH 是最重要的一个环境变量,许多黑客会在 /tmp 中存放一个与 ls 或 cd 同名的木马文件,再把路径加入 PATH。

文件权限管理

Linux 作为一个多用户、多任务的操作系统,具有很好的稳定性与安全性,在幕后保障 Linux 系统的安全则是一系列复杂的配置工作。这里暂不介绍用户身份相关的命令,只介绍文件权限与归属

目录详解

Unix/Linux 中,一切皆文件。涉及权限操作时,不可避免地要接触各个目录,这里简单介绍一些常用目录的作用:

树状目录结构

系统启动项

  • /boot:存放的启动 Linux 时使用的内核文件,包括连接文件以及镜像文件。

  • /etc:表示 Etcetera,存放所有的系统需要的配置文件子目录列表

指令集合

  • /bin:存放着最常用的程序和指令,如 ls 就是在 /bin/ls 目录下的。

  • /sbin:表示 Super User,只有系统管理员能使用的程序和指令。

账户

  • /root:系统管理员的用户主目录。

  • /home:用户的主目录,以各个用户的账号命名,支持多用户

  • /usr:表示 Unix Shared Resources,用户的很多应用程序和文件都放在这个目录下,类似 Windows 下的 Program Files 目录。

    • /usr/bin:系统用户使用的应用程序与指令。
    • /usr/sbin:超级用户使用的比较高级的管理程序和系统守护程序。
    • /usr/src:内核源代码默认的放置目录。

其他

  • 外部文件管理:/dev、/media、/mnt,挂载外部设备,如 U盘,光驱等。
  • 临时文件:/run,存储系统运行信息;/tmp,存储用户临时信息。
  • 运行过程项:/var,存放日志等;/proc,管理内存空间,系统内存的映射。
  • 扩展目录:/src,存放服务启动后需要提取的数据,不用服务器就是空。

权限类型

在 Linux 系统中,每个文件和目录都有归属的所有者和所属组,并且规定了其所有者所属组以及其他人所拥有的可读取(r)、可写入(w)、可执行(x,代表 execute)的权限。

这三个权限对于文件和目录的含义各不相同:

权限文件目录
读取(r)能读取文件能够读取目录内的文件列表
写入(w)能编辑、新增、修改、删除文件能够在目录内新增、删除、重命名文件
执行(r)能运行一个脚本程序能够进入该目录

三类对象,三种权限,总共需要九个标志位来限定一个文件或目录的权限范围,为了区分文件和目录等,还有一个附加标志位。权限的表示就分为字符表示和数字表示两种:

文件权限的字符与数字表示

数字表示即在字符对应的二进制位填写 1 或 0,表示授权或未授权,转换为十进制就是 4、2、1。

下面以一个例子来说明这两种表示法:现在有这样一个文件,其所有者拥有可读、可写、可执行的权限,其文件所属组拥有可读、可写的权限;其他人只有可读的权限。

  • 字符表示:rwxrw-r--
  • 数字表示:111110100764

那么现在我们用 ls -l 查看文件的信息:

通过ls命令查看到的文件属性信息

这些信息依次为:文件类型与权限;硬链接数;所有者;所有组;文件大小(字节);最后修改时间;文件名。

文件类型有 7 种,最常见的是 - 表示普通文件,d 表示目录文件。

硬链接数,对于普通文件,表示指向存储数据块中该文件的链接数(相当于 Windows 的快捷方式);对于目录文件,表示所在子目录级数

在复杂的实际情况中,单纯设置 rwx 权限已无法满足需求,因此还有 SUID、SGID 与 SBIT 三个特殊权限位,这里不多赘述。

修改权限

通常来讲,修改权限的操作有以下两个:

  • chmod:代表 Change mode,格式为 chmod [参数] 文件名称。其中参数为数字表示的权限。

  • chown:代表 Change owner,格式为 chown 所有者:所有组 文件名

样例功能
chmod +x script.sh给脚本添加可执行权限(默认对于任何人)
chmod 777 a.txt赋予所有人完整权限
chmod 000 a.txt赋予最小权限,只有 root 才能操作
chown root:root a.txt修改所有者和所有组为 root

此外,它们还有一个特别的共性,就是针对目录进行操作时需要加上大写参数 -R 来表示递归操作,即对目录内所有的文件进行整体操作。

管理员权限

Linux 系统为了安全性考虑,使得许多系统命令和服务只能被 root 管理员来使用,通过一些命令可以切换或暂时切换 root 权限。

  • su:代表 Swap user,不退出登录的情况下,切换用户身份,格式为 su - 用户名称

注意到命令中间有个 - 符号,这意味着完全切换到新的用户,即把环境变量信息也变更为新用户的相应信息,而不是保留原始的信息。用户名称可以是普通用户,也可以是 root。由普通用户切换至 root 需要输入管理员密码

1
2
$ su - root
Password: #此处输入管理员密码
  • sudo:代表 Superuser do,给普通用户提供额外的权限,格式为 sudo [参数] 用户名称

最常用的是为当前用户暂时提供 root 权限,此时不需要输入管理员密码,只需要当前用户密码。该命令可以避免显式输入管理员密码,但有效时间仅有 5 分钟。当然 sudo 命令也需要 root 的允许。

1
2
$ sudo su
Password: #此处输入当前用户密码

此外,sudo 还可加在其他命令前面,以获取高权限的执行,常用的有包管理命令。


Linux学习笔记 #2 高级的Shell与文件管理
https://hwcoder.top/Linux-Note-2
作者
Wei He
发布于
2021年9月9日
许可协议