Linux Basics for Hackers

code

Linux Basics for Hackers

参考

Linux Basics for Hackers 主要参考前 9 章的内容

非官方中译版

Kali Linux 是一个基于 Debian 的发行版(较为普及的 Linux 发行版 Ubuntu,也是基于 Debian 构建的),它整合了很多实用的黑客工具,专为渗透测试和黑客而设计。

提示

不同的 Linux 发现版共享相同的内核(控制 CPU、RAM 等操作系统的核心),只是在图形界面的选择(GNOME、KDE 等)和整合的应用程序略有不同。

核心概念

  • 目录 directory 相对于 Windows 系统中的文件夹,是一种组织文件的方式
  • 二进制文件 是指可执行文件,类似于 Windows 系统中的可执行文件。一般在 📁 /usr/bin 和 📁 /usr/sbin 目录中
  • 大小写敏感 Linux 目录和文件夹名称对于大小写敏感
  • root 是 Linux 管理员/超级用户账户,可以在系统是执行任何操作
注意

执行常规程序时,不应该以 root 用户的身份运行。

因为以 root 身份执行程序时,程序就会获得 root 权限,可以完全控制你的系统,这样很容易受到攻击。

  • 脚本 script 一系列命令的集合,通过解释器编译后运行
  • shell 一个在 Linux 中运行命令的环境和解释器,常用的 shell 是 bash shell
  • 终端 terminal 命令行界面,可以通过快捷键 Ctrl + Alt + T 启动
提示

终端是一个软件,提供交互界面和命令行环境,供用户与 shell 进行交互

文件系统

Linux 采用逻辑文件系统。

提示

Windows 的文件系统是基于物理驱动的,其中存在分区的概念,如 C: 驱动器

它就像一个倒置的树结构,最顶层是 / 称为文件系统的根

Linux 文件系统结构示意图
Linux 文件系统结构示意图

其中较为常用和重要的一些子目录如下

  • 📁 /root root 用户的主目录
  • 📁 /bin 包含应用程序的二进制文件
  • 📁 /etc 一般包含 Linux 配置文件,这些文件用于控制程序启动时间和方式
  • 📁 /home 用户的主目录,Linux 可以配置多用户
  • 📁 /lib 包含 lib 库文件(相当于 Windows 系统中的 DLL 共享程序)
  • 📁 /mnt 将其他文件系统附加或安装到 Linux 文件系统的位置
  • 📁 /media CD 或 USB 设备连接或安装到 Linux 文件系统的位置

基础命令

一些实用的命令

参考
  • shell.how? 一个在线解析 shell 命令的网站
  • tldr pages 一个简化版的手册页面 man pages

查看当前位置

由于命令行界面 CLI 并不如图形界面 GUI 一样直观,不能直接看到当前所处的位置,需要使用一个命令来查看。

命令 pwd 返回当前所在目录系统中的位置(路径),其中开头的 / 表示根目录

查看登录用户

Linux 支持多个用户登录,可以使用一个命令来查看当前登录的用户角色。

命令 whoami 返回当前登录的用户的名称

在文件系统中游弋

需要查看文件、运行程序,都需要找到文件和程序所在的位置,因此学会在 Linux 的文件系统中游弋 navigate 很重要。

命令 cd 用以改变终端当前所在的目录系统中的位置

  • cd /the/dir/path 移动到指定路径的某个目录,其中开头的 / 表示根目录
  • cd .. 向上一级目录移动,这里使用的是相对路径。如果一直往上一级,最终可以到达 / 根目录
提示

终端提示符(在每一行,键入命令前的那一小段文字)会显示一些信息,其中包含当前终端所在的目录系统中的位置

列出目录中的内容

命令 ls 查看当前目录下所包含的文件和(直接一级)子目录

提示

和 Windows 系统里的 dir 命令类似

命令 ls 后可以添加一些有用的(switch 模式开关)参数:

  • 参数 -l 查看文件和子目录的更详细的信息,例如文件的(读写)权限、(文件所归属的)所有者、文件的大小、文件最后修改的时间等
    显示更详细的信息
    显示更详细的信息
  • 参数 -a 显示文件和子目录时,会包含隐藏的文件

获取帮助

在命令后添加参数 --help 查看相应命令的帮助文档,有些命令和程序还可以使用参数 -h参数 -? 来查看帮助文档

提示

在 Linux 命令中有一个关于参数的约定俗成的规定:

  • 参数是单词 word 时,前面使用两个连字符 --
  • 参数是单个字母 single letter,前面使用一个连字符 -

但是这个规定也不是必然的,要看命令和程序是否支持

如果希望查阅更详尽的内容,可以使用命令 man 打开命令和程序的手册页面,除了帮助文档,大部分的命令和程序还提供 manual page 手册页面

提示

在手册页面里,除了使用鼠标滚轮翻页,还可以使用键盘进行游弋:

  • 使用 Enter显示下一行
  • 使用 PG DN向下翻一页,使用 PG UP向上翻一页
  • 使用 q关闭手册,返回命令行界面

搜寻文件

在 Linux 的命令行中,有多种命令来搜寻文件

命令 locate 可基于关键词在文件系统中进行检索

bash
locate nmap
注意

命令 locate 是基于一个索引数据库进行搜索的,但是该数据库并不会及时更新,所以文件系统新增的文件其索引可能要等待几分钟或几个小时才会被添加到数据库中。

所以要根据场景来判断是否使用该命令进行搜索

命令 whereis 查找二进制文件,返回该文件所在的目录,以及相应的手册页面文件的路径(如果存在手册页面时)

命令 which 在 Linux 系统环境变量 PATH 中查找二进制文件,返回环境变量中所存储的路径

提示

在命令行界面执行命令时,Linux 会基于环境变量 PATH 所存储的路径来寻找到对应二进制文件(程序)

环境变量 PATH 至少包含 /usr/bin 目录,有时候会包含 /usr/sbin 和其他目录

命令 find 是一个更强大灵活的搜索工具,可以设置很多参数,以定制搜索范围。

该命令的一般语法

bash
# 搜索 directory 目录及其子目录的内容
# 还可以设置一系列的参数 options expression
find directory options expression

在根目录 / 开始

bash
# 在根目录 `/` 开始搜索
# 参数 -type 的值为 f 表示搜索的是普通文件
# 参数 -name 的值为 apache2 表示搜索的文件名为 apache2
find / -type f -name apache2
# 参数 -user 的值为 root 表示搜索文件拥有者为 root 的文件
# 参数 -perm 的值为 -4000 表示搜索文件的权限为 4000(八进制的值,可以包括 `SUID` 或 `SGID` 位)的文件
find / -user root -perm -4000
注意

命令 find 默认采用严格匹配模式(匹配规则包含文件名称和拓展名的约束),可以通过通配符 wildcards 来实现模糊匹配模式

常用的通配符有 *.,?[],这和正则表达式类似

  • 通配符 ? 表示一个字符
  • 通配符 [] 用于匹配在括号中出现的内容
  • 通配符 * 应该是最常用的,它表示任何长度的字符,也可以表示无

对结果筛选

命令 grep 基于关键词对结果进行筛选 filter

该命令一般和管道操作配合使用

说明

管道 pipe 是指在 Linux(Windows 系统也是)允许我们将上一个命令的输出作为下一个命令的输入,这个操作流程称为 pipe 管道

命令 | 用于连接两个操作,这个符号 | Enter上方

例如通过命令 ps 当前系统运行的进程 processes,并使用参数 aux(这是 BSD 风格的参数,不带连字符 -)指定显示所有用户所拥有的线程,再通过管道 | 和命令 grep 对上一个命令的结果进行筛选

bash
# 只显示 apache2 相关的进程
ps aux | grep apache2

修改目录和文件

在操作文件系统中有一类很重要的操作是修改目录和文件,包括新建、复制、(剪切)移动、重命名、删除等,当然还包括修改文件内容。

新建文件

有多种方式创建新文件

命令 cat 一般用于展示文件的内容,但也可以用于创建小型(内容简单的)文件。

提示

命令 cat 对应于单词 concatenate,意为将小片段的内容组合在一起

而对于大型的(内容较长的)文件,推荐使用文本编辑器(如 vim、emacs、leafpad、gedit 或 kate)进行编辑和创建,而不是直接在命令行直接创建,因为使用编辑器可以更高效。

  • 命令 cat 后直接紧跟着一个文件名,其作用是展示文件内容(而不是创建一个新文件)
  • 命令 cat 后如果是重定向符号 > 并指向一个文件名,其作用是新建一个文件(如果当前目录下有同名文件,就会覆盖原有的文件
    按下 Enter执行该命令后,命令行提示符就会消失,变成文本输入提示光标,此时可以开始键入文本内容,完成后按下 Ctrl + D以退出,这样内容就会保存在文件中
  • 命令 cat 后如果使用两个重定向符号 >> 并指向一个文件名,其作用是在文件后追加内容

命令 touch 后紧跟着一个文件名,原本的作用是修改文件的元信息(如文件的创建,更新时间等),如果文件并不存在,该命令的默认行为就是创建一个文件

命令 mkdir 创建一个新目录

提示

命令 mkdir 对应于单词 make directory

复制文件

命令 cp 用于复制文件到指定的路径(目录)下,如果指定路径是以文件名结束的,则会同时进行重命名操作(这是可选操作)

bash
# 将名为 `odlfile` 的文件复制到指定的目录 `/root/newdirectory` 并重命名为 `newfile`
cp oldfile /root/newdirectory/newfile

移动和重命名文件

命令 mv 将文件(剪切)移动到新路径(目录)下

提示

因为 Linux 系统并没有提供对文件直接进行重命名的命令,但可以利用命令 mv 移动文件来实现重命名的效果,只需要保证移动的目标路径和当前目录的路径相同,并在移动的同时重命名文件的名称即可

bash
# 将名为 newfile 的文件重命名为 newfile2
mv newfile newfile2

删除文件和目录

命令 rm 删除文件

命令 rmdir 删除目录

注意

使用命令 rmdir 删除目录时要注意该目录里的文件是否已经清空

如果还有文件在里面,就会删除失败,并触发错误,在命令行中抛出错误信息 directory is not empty

提示

如果希望强制删除非空的目录,可以在命令 rm 后使用参数 -r

但是应该谨慎使用这种方式,可能会一不小心导致误删重要的文件。

操作文件内容

Linux 中有大量的文本文件,很多时候都是与它们打交道,所以学习编辑文本的命令和编辑器十分重要。

查看文件内容

使用命令 cat 查看文件时,命令行工具界面会一次性将文件内容全部输出,这种方式对于查看(内容较多的)大文件并不友好,所以一般使用其他命令来查看文件内容。

命令 head 显示文件的前几行内容,默认是展示前 10 行内容,可以在命令后配置参数 -num 其中 num 是数值,表示只显示前 num 行的内容

命令 tail 显示文件的最后几行内容,默认是展示后 10 行内容,可以在命令后配置参数 -num 其中 num 是数值,表示显示最后 num 行的内容

提示

可以在命令后配置参数 -n+num 其中 num 是数值,表示从第 num 行开始显示到文件的最后

命令 nl 用于查看文件内容,并且会在每一行前面标注好行数

命令 more 以页为单位查看文件内容,并在左下角显示当前已查看了文件内容的百分比

该模式支持按下键盘的向上或向下键可实现翻页操作,或按下 Enter 键显示下一行。按下 q 可退出查看模式。这也是 man pages 手册页面所使用的交互方式

命令 less 和命令 more 类似,也是用于查看文件内容,在左下角高亮显示当前所查看文件的所在路径

该模式提供了更方便的功能。支持通过鼠标滚动来浏览长内容,还支持基于关键字进行筛选导航,键入 / 斜线后可以开始键入关键字,对显示内容进行筛选,然后页面就会跳转到第 1 个匹配的内容所在的位置,如果希望页面跳转到下一个匹配的内容所在的位置,可以按下 n 键。如果希望使用新的关键字进行筛选,可以再键入 / 斜线后开始键入新的关键词。如果想退出该模式,可以键入 q 并按下 Enter

过滤文本内容

命令 grep 可以对所展示的文件内进行筛选,只显示含有关键字的特定行,通过管道 | 操作配合显示文件内容的命令来使用

bash
# 查看文件,并筛选只显示带有关键字 "output" 那些行
cat /etc/snort/snort.conf | grep output

搜索替代内容

命令 sed 基于关键字(或正则表达式)对文件内容进行搜索匹配,并对匹配的内容进行操作,一般用于替换文本内容

bash
sed s/mysql/MySQL/g /etc/snort/snort.conf > snort2.conf
说明

命令 s 表示 search 搜索,用 / 斜杆分隔需要搜索的关键字,接着用 / 斜杠分隔的是需要将匹配的内容替换为什么文本

命令 g 表示 global 全局,指搜索匹配对全文都有效。而如果不使用该命令,则命令 sed 的默认行为是,仅仅寻找并替换第一个匹配的内容;而如果不是命令 g 而是一个数值 n,则表示仅仅寻找并替换第 n 个匹配的内容

然后用重定向符 > 将替换后的全文内容保存到另一个文件中

分析和管理网络

查看网络接口

命令 ifconfig 查询当前激活的网络,打印出相关的信息

提示

系统有不同的网络连接,该命令就会显示不同的内容

bash
# 示例
>ifconfig
# 侦测到的第一个网络接口名称为 eth0,其中 eth 是单词 Ethernet 以太网的缩写
# 如果有第二个网络接口,就会命名为 eth1,并依次类推(所以 Linux 系统计数是从 0 开始的)
eth0Linkencap:EthernetHWaddr 00:0c:29:ba:82:0f
# 接着显示机器所获得分配的一些地址信息:
# IP 地址 addr 192.168.181.131
# 广播地址 Bcast 192.168.181.255 用于向子网上的所有 IP 发送信息的地址
# 子网掩码 Mask 255.255.255.0 用于确定 IP 地址的哪个部分连接到本地网络
inet addr:192.168.181.131 Bcast:192.168.181.255 Mask:255.255.255.0
--snips--
# 环回地址 addr 127.0.0.1 有时候称为 localhost,其中 lo 是单词 loopback address 环回地址的缩写
# 这是个特殊的软件地址,可帮助你连接到自己的系统
# 本地主机通常用 IP 地址 127.0.0.1
# 使用 lo 可以在你的系统测试某些内容,例如 web 服务器,它本来需要部署到网络才可以工作
lo Linkencap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0
--snips--
# 无线网络接口 wlan addr 只有机器拥有无线接口或适配器时,才会出现这一项
wlan0 Link encap:EthernetHWaddr 00:c0:ca:3f:ee:02

命令 iwconfig 查询无线网络适配器的信息,如适配器的 IP 地址、MAC 地址、所处的模式等

bash
# 示例
> iwconfig
# 侦测到一个无线网络接口 wlan0
# 其中 IEEE 802.11bg 表示该设备能够支持的 802.11 IEEE 无线标准是 b 和 g
wlan0 IEEE 802.11bg ESSID:off/any
Mode:Managed Access Point: Not Associated TxPower=20 dBm
--snip--
no wireless extensions
eth0 no wireless extensions

修改网络接口

命令 ifconfig 也可以操作网络。

例如通过命令 ifconfig eth0 192.168.181.115 将指定的网络接口 eth0 的 IP 地址修改为 192.168.181.115

修改成功后并不会有任何输出,可以使用命令 ifconfig 再查看网络信息

还可以同时为指定的网络接口 eth0 修改 IP 地址、子网掩码地址、广播地址,例如命令 ifconfig eth0 192.168.181.115 netmask 255.255.0.0 broadcast 192.168.1.255

也可以使用命令 ifconfig 修改 MAC 地址(也成为 HWaddr)

说明

MAC 地址是全球唯一,并且经常被当做一种安全措施来阻击或跟踪黑客,所以地址几乎是很平常的操作,并且帮助你抵消这些安全措施。因此修改 MAC 是一项非常有用的绕过网络访问控制技术。

bash
# 先使用命令 `ifconfig eth0 down` 将网络接口关闭(`eth0` 是本示例中的网络接口)
> ifconfig eth0 down
# 然后使用命令 `ifconfig eth0 hw ether mac_addr` 更改网络接口的 MAC 地址(`hw` 表示硬件,`ether` 表示以太网 Ethernet)
> ifconfig eth0 hw ether 00:11:22:33:44:55
# 最后使用命令 `ifconfig eth0 up` 启动接口
> ifconfig eth0 up

命令 dhclient 从 DHCP 请求 IP 地址

bash
# 为 `eth0` 网络端口指定一个新的 IP 地址
> dhclient eth0
说明

DHCP 是 Dynamic Host Configuration Protocol 动态主机配置协议的缩写,该协议可以让服务器为子网上的所有机器自动分配 IP 地址。

机器通过局域网 LAN 连接到internet,必须从 DHCP 服务器获得一个 IP。

因此如果你为机器的网络接口设置一个新的静态 IP 后,必须再从 DHCP 服务器分配获取到一个新的(映射)IP 地址,为了实现这个步骤一般需要重启你的系统,但是也可以使用命令 dhclient 检索一个新的 DHCP 分配的 IP 地址,而不必重启你的系统。

该命令会从指定的网络接口向 DHCP 服务器发送 DHCPDISCOVER 请求,并从 DHCP 服务器获得一个 DHCPOFFER 响应,然后再通过 dhcp 请求对 DHCP 服务器确认已经收到所分配的 IP 地址

然后可以使用命令 ifconfig 查看相应的网络接口是否已经分配得到新的 IP 地址、子掩码、广播地址等。

DNS

Announce

DNS 是 DOMAIN NAME SYSTEM 域名系统的缩写,用于将域名转换为 IP 地址

命令 dig 搜集与目标域名的相关的 DNS 信息

bash
# 使用命令 dig 并添加参数 ns 查询指定域名的名称服务器的相关信息
# 其中参数 ns 是单词 nameserver 名称服务器的缩写
> dig hackers-arise.com ns
--snip--
;;QUESTION SECTION:
;hackersarise.com. IN NS
# 在输出结果的 ANSWER SECTION 部分可以查看到名称服务器的相关信息
;; ANSWER SECTION:
hackersarise.com. 5 IN NS ns7.wixdns.net.
hackersarise.com. 5 IN NS ns6.wixdns.net.
# 在输出结果的 ADDITIONAL SECTION 部分可以查看到 DNS 服务的服务器的 IP 地址
;; ADDITIONAL SECTION:
ns6.wixdns.net. 5 IN A 216.239.32.100
--snip--
bash
# 使用命令 dig 并添加参数 mx 查询指定域名的电子邮件服务器的相关信息
# 其中参数 mx 是单词 mail exchange server 电子邮件服务器的缩写
> dig hackers-arise.com mx
--snip--
;;QUESTION SECTION:
;hackersarise.com. IN MX
# 在输出结果的 AUTHORITY SECTION 部分可以查看到
;; AUTHORITY SECTION:
hackersarise.com. 5 IN SOA ns6.wixdns.net. support.wix.com 2016052216 10800
3600 604 800 3600
--snip--

可以通过修改 📄 /etc/resolv.conf 文件 来设置所使用的 DNS 服务器。

默认采用的是本地的 DNS 服务器,该服务器的 IP 地址是类似 192.168.181.2 的形式,可以通过修改该文件来设置使用其他的 DNS 服务器,例如 Google 提供的公共 DNS 服务器(其 IP 地址是 8.8.8.8

提示

如果文件中包含多个 DNS 服务器,则会依次顺序查询,直至查询到目标域名所对应的 IP 地址为止

如果使用 DHCP,则该服务会自定对 DNS 进行设置,因此在更新 DHCP 时会重置机器的 DNS 设置(即 /etc/resolv.conf 文件的内容)

Host

一个名为 📄 /etc/hosts 文件,其作用和 DNS 服务器类似,也是用作域名和 IP 地址的映射,因此可以通过修改该文件来自定义一些域名和 IP 地址的映射关系。

当浏览器要访问一个域名时,会先在 hosts 文件里进行查找,如果没有查找到域名所对应的 IP 地址映射,再去查询 DNS 服务器。

注意

请确保在修改 hosts 文件时,分隔 IP 地址和域名时,采用 Tab 键(而不是空格键)

安装和删除软件

软件包 software package 是指一系列的程序集合。因为一些软件需要依赖其他软件才能运行,你可能需要下载一个软件包,其中包含了目标软件和它的依赖,然后将它们一次性安装,并通过脚本来依次加载运行。

软件包管理器

在基于 Debian 的 Linux 发行版中,默认的软件管理器是 apt

说明

apt 是单词 Advanced Packaging Tool 的缩写

命令 apt-get 使用 apt 来下载安装软件包,或更新升级软件

提示

也可以使用 GUI 图形界面来管理和安装软件包,例如 Synaptic 和 Gdebi。

对于一些新发布的开源软件(或版本),可能未及时添加到软件列表存储库中,还可以在 Github 中搜索该软件项目,使用以下命令进行下载

bash
git clone project_github_url.git

查询安装包

在下载安装软件前,可以先使用以下命令在软件列表存储库 repository(本地的缓存)进行搜索,以检查是否有相应的软件包以供下载

shell
apt-cache search package_name
说明

不同的 Linux 发行版会预装着不同的软件,而保存着这些软件列表信息的服务器称为 repositories 存储库。

一般不同的发行版都有维护着自己的存储库,这些软件列表虽然大同小异,但是使用其他发行版的软件列表,可能会导致安装的软件无法与系统配合工作,因为即使不同发行版的软件列表包含相同的软件,但是软件的版本也可能不同。

但是有时候发行版本身的软件列表并不完整,无法搜索到所需的软件,可能需要添加其他发行版的软件列表存储库,作为额外的后备选择。

在 📄 /etc/apt/sources.list 文件中添加后备的软件列表存储库,在安装软件时,会安装 sources.list 文件所列出的存储库顺序,依次搜索,直到找到可安装的软件为止。

但不推荐添加 testing 测试中、experimental 实验、unstable 不稳定类型的软件列表

提示

(不同 Linux 发行版)软件列表存储库 repository 是会定期更新,但是这些更新并不会自动推送同步到你操作系统本地的缓存中,需要手动调用以下命令来更新本地的软件列表

bash
apt-get update

安装软件包

使用以下命令从软件存储库中下载并安装软件包

bash
apt-get install package_name

在执行命令过程中,当软件包下载完成后会在命令行中显示一段提示,键入 y 以确认执行安装步骤

删除软件包

使用以下命令从电脑删除已安装的软件包

bash
apt-get remove package_name

在执行命令过程中,当搜集完软件相关信息后会在命令行中显示一段提示,键入 y 以确认执行删除步骤

说明

在移除软件包过程中,可能会在终端看到提示输出,要同时删除一些其他的软件。

这是因为 Linux 为了让软件更小,会将依赖包差分为一个个小的程序,这样其他的软件就可以共享这些程序了。

如果这些依赖包只是当前目标软件所需要的,那么在删除目标软件时,这些依赖包也会被删除

注意

移除操作并不会删除软件包的相关配置文件,因为考虑到以后你可能要重新安装该软件包,所以将其保留,便于之后安装软件时做到开箱即用(无需再进行配置)

如果希望删除软件包时,同时将相关配置文件也删除,可以使用参数 purge

bash
# 参数 purge 意为纯净、净化
# 所以采用该参数删除软件包时,会将配置文件也同时删除
apt-get purge package_name

升级软件包

使用以下命令升级电脑已安装的软件包

bash
apt-get upgrade

由于这个操作会更改系统里的软件,所以必须以管理员 root 角色登录后来才能运行,或在该命令前添加命令 sudo 以获取管理员权限

在执行命令过程中,当搜集完所需升级软件的相关信息后(所需升级、新安装、移除、不需要升级的软件包数量,所需占据的容量大小),会在命令行中显示一段提示,键入 y 以确认执行升级步骤

提示

该命令会将系统中所有可更新的软件升级到最新的版本,所以可能花费大量的时间,这时候系统可能无法正常使用

注意

区分 update 和 upgrade:

  • update 更新:仅仅是指更新软件列表(本地的缓存),这样需要升级程序时,可以进行查询比对版本号,以判断需要升级哪些软件包
  • upgrade 升级:是指将软件包从旧版本升级到新的版本

文件与目录的权限

Linux 可以设置文件和目录的访问权限,root 系统管理员(或该文件的所有者)可以赋予特定用户读取、写入或执行的权限,以避免文件和目录被查看或篡改。

提示

Linux 可以将用户归类到不同的 group 用户组,例如财务员群组、工程师群组、销售员群组等,便于赋予不同群组的用户不同的权限。而且 group 下还可以细分 group,便于更精细的权限授予控制。

root 用户默认归为 root group 组别。

当系统新增一个用户时,需要将它进行归组,以便继承相应群组的权限。

每个文件和目录都必须为使用它的不同用户指定(不同的)权限,文件和目录的常见权限有 3 种,一般用相应字母表示:

  • r 读取权限:赋予用户可以打开以查看的权限
  • w 写入权限:赋予用户可以查看并编辑的权限
  • x 执行权限:赋予用户执行文件的权限(拥有该权限的用户不一定可以查看或编辑它,一般该权限针对的是可执行的二进制文件)
说明

在设置权限约束时,一般可以对以下几类用户的权限进行配置:

  • user/owner 创建文件的用户,它是该文件的所有者
  • owning group 创建文件的用户所在群组,在配置文件约束时,可以针对该群组内的用户进行统一的权限约束
  • others 其他用户,不是文件的所有者,也不在 owning group 群组中的用户

此外还有一个特别的用户,即 root 系统管理员,它拥有几乎所有权限。

root 系统管理员可以基于不同用户的需求,修改任何文件针对不同用户的权限约束。而如果当前用户是文件的所有者(以 owner 角色登录系统),则可以修改该文件的权限约束。

所有权转移

命令 chown 可以将文件的所有权「转移」给指定的用户

如果当前用户是 root 系统管理员,或文件所有者,则可以使用以下命令将文件的所有权「转移」给其他(单个)用户

bash
# 将文件 /tmp/bobsfile 的所有权「转移」给用户 bob
chown bob /tmp/bobsfile

命令 chgrp 可以将文件的所有权「转移」给指定的群组(一类用户)

检查权限

命令 ls 后添加参数 -l 可列出文件和目录的详细信息,其中包含权限信息

查看 hosts 文件的权限
查看 hosts 文件的权限

该命令的输出结果中依次显示的信息:

  1. 该条目的类型
提示

如果是文件,则以 - 表示;如果是目录,则以 d 表示(单词 directory 的缩写),这是最常见的两种类型

  1. 文件或目录的权限,分别列出文件的所有者、当前用户群组、其他用户的权限
说明

依次列出三种用户的读取权限、写入权限、执行权限。

如果拥有权限就用相应的字母表示(r 表示读取权限,w 表示写入权限、x 表示执行权限),如果并不拥有对应的权限就用 - 表示(占位符)

一般只有二进制的可执行文件或脚本文件,用户才可能拥有 x 执行权限

  1. 文件或目录的链接数量
  2. 文件或目录的创建者/拥有者
  3. 文件或目录创建者所在的群组
  4. 文件或目录的大小(以字节 bytes 为单位)
  5. 文件或目录的创建(或最后修改)时间
  6. 文件或目录的名称

更改权限

命令 chmod 改变用户的权限

只能由 root 系统管理员,或文件(目录)的拥有者才可以更改文件的权限约束

提示

命令 chmod 是单词 change mode 的缩写

可以使用八进制数值语法来改变权限,这种方法是同时针对三类不同的用户(文件或目录的拥有者、拥有者所在的用户群组、其他用户)设置权限约束的

bash
# 用 3 个八进制数值来设置文件(针对三类不同的用户)的权限约束
chmod octal_syntax file
说明

在计算机系统内部使用二进制来表示数据,对于权限的也是通过二进制 10 来表示权限的激活或失效状态。

文件对于一个用户的 rwx 权限约束需要 3 位二进制数字来表示,共有 8 种状态,所以可以简化为使用 1 位八进制的数字来表示

八进制 octal 由 07 共八种数字构成,满八进一

二进制权限约束 rwx八进制
000---0
001--x1
010-w-2
011-wx3
100r--4
101r-x5
110rw-6
111rwx7

使用 3 个二进制的数字或 1 个八进制的数字表示文件或目录针对一个用户的权限约束

所以当文件(或目录)要表示拥有者、当前用户组、其他用户(这三类不同用户)的权限约束时,需要使用 3 个八进制的数字

例如要为 📁 /etc/hosts 文件针对三类不同的用户,都设置为具有完全的权限时,可以用数字 777(八进制)表示

bash
chmod 777 /etc/hosts

也可以使用 UGO 语法来改变权限,这种方法是针对某一类用户(文件或目录的拥有者、拥有者所在的用户群组、其他用户,这三种用户任一)设置权限约束

bash
# 为某一类用户设置权限约束
chmod ugo_syntax file
说明

以上命令中 ugo_syntax 是由三部分构成的:

  1. 首先取 ugo 任一值,以指定需要为哪一类用户设置权限
    其中 u 表示文件所有者,是单词 user(或 owner)缩写;g 表示拥有者所在的用户群组,是单词 group 缩写;o 表示其他用户,是单词 others 缩写
  2. 然后跟着取以下三个操作符之一,以表示添加还是删除操作特定的权限:
    • - 操作符:表示移除特定的权限
    • + 操作符:表示添加特定的权限
    • = 操作符:表示设置特定的权限

    操作符 = 是覆盖操作,将指定用户的权限设置为符号 = 后所指定的权限;而操作符 +- 是追加操作,从原有权限里添加或删除指定的权限
  3. 最后是需要设置的权限名称,可以是 rwx 中任一字母(或字母的组合)

例如要为 📁 /etc/hosts 文件针对其他用户 o 添加写入权限

bash
chmod o+w /etc/hosts
提示

如果希望使用 UGO 语法同时对两个或以上的用户设置权限,可以将多个 ugo_syntax 用逗号 , 分隔

bash
# 为 hosts 文件同时针对用户群组和其他用户设置写入权限
chmod g+w,o+w /etc/hosts

默认权限

为了保证系统的安全,Linux 默认为文件设置权限为 666(八进制),为所有目录设置权限 777(八进制)。所以默认情况下,新下载的文件对于所有用户都是无法运行的(会弹出 "Permission denied" 的警告),而新建的目录则任何用户都可以读取和修改。

可以使用以下命令让拥有者(当前登录系统的用户)拥有所有权限,这样就可以运行下载的文件了

bash
chmod 766 file_path

为了让系统更安全,还可以通过设置 umask 参数来修改文件和目录的默认权限

umask 所设置的 3 个(八进制)数字是作为减数(八进制运算),即从默认的权限里移除 umask 值所对应的权限,然后将得到新的值作为新建文件或目录的权限预设值

说明

mask 掩码,屏蔽之意

例如大部分基于 Debian 的 Linux 发行版的 umask 预设值都是 022,则最终的权限(示意图如下)文件的拥有者只有可读和写入权限,用户群组和其他用户则只有可读权限

New filesNew directories说明
666777Linux 原始的默认权限
-022-022umask
644755最终的权限

每一个用户都可以在 📁 /home/username/.profile 文件中设置自己的 umask 值,例如在文件中添加 umask 007 就可以将当前用户的 umask 值设置为 007

可以在终端输入命令 umask 查看当前用户的 umask 值。

临时权限

除了使用命令 chmod 修改权限,Linux 还提供了其他的方法,为普通用户(非 root 或系统管理员)提权 privilege escalation,这样可以临时获取 root 或系统管理员(或文件所有者等)的相应权限

Linux 还有 3 个特别的权限:

  • SUID bit 添加 SUID 位,以设置用户 ID,以临时获取拥有者的权限
  • SGID bit 添加 SGID 位,以设置群组 ID,以临时获取拥有者所在的群组的权限
  • sticky bit 粘滞位,比较旧的方法,现在很多 Linux 发行版都不支持了

SUID

说明

可能存在一种情况,执行一个程序时涉及到另一个文件(需要访问或修改另一个文件),一般需要运行程序的用户是 root 系统管理员才有权限完成这个操作。

但是以 root 角色来运行第三方程序这和安全原则相违背,对于一般用户而言,以非 root 角色来来执行该程序才是更常见的使用场景,因此这就会遇到权限约束,看到如「需要 root 用户才有权限执行」这一类的警告提示。

针对这种情况,文件拥有者(这里就是指程序开发者吧 😕)可以为程序文件设置 SUID,以表示任何使用者在执行该文件时,都可以**临时获取该程序文件拥有者的权限(一般就是获得 root 用户的权限)**来执行该文件,这样即使不是文件拥有者(一般指 root)的用户来使用程序也可以顺利执行

例如使用命令 passwd 可以修改密码,该程序需要访问 /etc/shadow 文件并进行修改,由于该程序设置了 SUID 位,所以即使不是 root 管理员调用该程序也可以成功运行

这样可以方便程序被一般的用户使用,不必频繁地要求用户切换到 root 用户,而这个临时获得的权限只局限于执行/运行该程序的过程,对权限范围的限定,降低权限被恶意利用的可能性

使用命令 chmod 4xxx file 为程序文件 file 设置 SUID

为程序文件设置 SUID 只需要在文件拥有者的常规权限(以 3 个八进制数字表示)前面添加 4 即可,例如一个程序文件的权限设置是 644,则使用命令 chmod 改为 4664

当程序文件设置了 SUID 时,文件拥有者的执行权限就会变成 s(而不是 x

提示

但是一般为程序文件设置 SUID 都不是普通用户可以进行的,因为程序文件的所有者一般都是 root 管理员

SGID

说明

如果一个程序在执行时,需要访问另一个文件,恰好该程序和所需要访问的文件的所有者都在同一个用户组中(如都属于 bin 用户组),且用户组的权限足够完成运行任务(例如仅需要读取权限)

则可以为程序设置 SGID,那么即使运行程序的是其他用户(不是文件拥有者,也就不会在文件拥有者的用户组中)也可以临时获取文件拥有者的用户群组的权限,该程序也可以成功运行

SUID 位和 SGID 位的作用是类似的,都是临时获取权限,但是 SUID 位只可以为执行程序文件进行设置,而 SGID 位则可以为文件或目录设置(一般用于设置目录)

SGID 位与 SUID 位相比一般是更安全的,因为获得的是(文件拥有者所在的)用户群组的权限,而不是文件拥有者的权限,一般文件拥有者的权限会更高,而所在群组的权限可能会低/少一些,而其他用户是更低的

使用命令 chmod 2xxx file_or_directory 为文件或目录设置 SGID

当程序文件设置了 SGID 时,用户群组的执行权限就会变成 s(而不是 x

提示

如果为目录设置 SGID 位,则在该目录中新建的文件会将所有权「转移」

新建文件的所有权「转移」到该目录创建者所属的群组(而不再是该文件的创建者),这样就可以让用户群组中的所有用户都可以执行新建的文件

进程管理

进程是一个正在运行的程序,它会占用资源。如终端、web 服务器、正在运行的命令程序、数据库等。

查看进程

命令 ps 查看(由当前用户所运行的)活跃的进程,它们会依据启动的先后顺序依次列出

查看由当前用户运行的活跃的进程
查看由当前用户运行的活跃的进程

说明

Linux kernel 内核是操作系统的核心,它控制着几乎所有的东西。

Linux 内核会根据进程的创建顺序,给每一个进程分配一个唯一标识符,称为 PID(是单词 process ID 的缩写)

我们就是通过这个 PID 来具体指定需要与哪一个进程仅交互的,因此 PID 十分重要

命令 ps 后添加参数 aux 查看系统中(由所有用户)启动的进程(可能有些进程在当下以停止运行了)

查看由所有用户启动的进程
查看由所有用户启动的进程

说明

在输出的结果中有一些比较重要的(列)属性:

  • USER 运行该进程的用户
  • PID 该进程的唯一标识符
  • %CPU 该进程的 CPU 占用率
  • %MEM 该进程的内存占用率
  • COMMAND 进程名称

筛选进程

使用命令 grep管道操作相配合,对命令 ps 输出的查询结果进行筛选,找到符合特定关键词的进程

bash
# 从所有进程中筛选出具有关键字 msfconsole 的进程
ps aux | grep msfconsole
说明

因为对 ps 的输出结果进行筛选,所以得到的最终结果一般不带表头,因为那一行一般不会与关键字匹配

进程排序

说明

因为命令 ps 会按照进程的启动时间先后列出,而内核会在进程启动时给它们分配 PID,所以看起来就像命令 ps 的输出结果默认按照 PID 排序

命令 top 也是查看所有进程,但是会按照资源占用大小进行排序(最大占用率的进程先列出),并每 10 秒刷新一次,按 q结束命令

注意

虽然监听列出的是所有活跃的进程,但是页面不可滚动,只能显示一屏高度的占用率最大的进程,并且动态更新

可以通过该命令来监控系统的资源利用情况,类似于 Windows 系统的资源管理器

可以按下 H ?来启用交互式命令行的设置页面,阅读里面的帮助文档可以知道如何对命令 top 进行配置。

要退出交互式命令行的设置页面可按下 q Esc返回监控页面

改变进程优先级

系统中同时运行着很多进程,它们会相互竞争资源,内核会决定这些它们之间的优先级,可以使用命令来设置「建议」进程的优先级。

通过一个数值,称为 nice 值,来表示进程的优先级高低,其范围是 -20+19,默认值是 0

mermaid

进程的 nice 值与优先级

说明

nice 其含义是「友善」,是对其他用户而言,你的进程有多友善。

所以设置的数值是「友善值」,当数值越高,表示该进程的优先级别越低,所占用的资源就可能越低,相应地对于其他用户而言,该进程就越「友善」;反之该数值越低,其优先级就越高。

当一个进程启动时,它会继承其父进程的 nice 值,并根据进程的所有者(或 root 超级用户)的设置,来修改进程的 nice 值

有两个命令可以用于修改进程的优先级,但是其作用和语法略有不同

命令 nice 用于启动一个程序,并改变相应进程的优先级

bash
# 语法
nice -n number program

其中参数 -n 指定一个数值 number,之后的参数 program 是需要修改优先级的程序文件。

该命令是在程序启动时,基于默认值再加上所设置的相对值(对应于单词 by),来设置进程的优先级

命令 renice 用于在进程运行过程中,修改它的优先级

bash
# 语法
renice number PID

在命令 renice 后所设置的数值 number 是 nice 值的绝对值(对应于单词 to),范围是 -2019,由于使用 PID 来指定要修改哪个进程的优先级,所以程序必须是要先运行的

注意

一般的进程所有者只可以降低进程的优先级(即提高 nice 值),不能增加其优先级

但对于 root 超级用户,它可以随意为任何进程设置任何值(在范围 -20+19 之间)

提示

在运行命令 top 后,按下 r进入交互式界面(后台会使用命令 renice)来调整进程的 nice 值

按下 r后会出现提示 PID to renice [default pid=xxx] 输入要修改的进程 PID(默认是第一个进程的 PID,即当前占用资源最大的进程)然后按下 Enter

然后会提示输入数值 Renice PID xxx to value 然后按下 Enter,以将进程的 nice 值设置为输入的值

在该过程中任何时候都可以按 Esc退出交互式命令行界面

使用该方式修改进程的优先级时,一般只能修改当前用户所创建的进程。如果当前登录用户并不是 root 超级用户,则同样也是不能将优先级调高(即减低 nice 值)

停止进程

命令 kill 停止通过 PID 所指定的进程

bash
# 通过 PID 指定需要停止的进程
kill -signal PID

(可选)参数 -signal 用于配置不同的数值选项,对应于不同的 kill signal 停止标志信号,即通过不同的方式来停止进程

共有 64 种 kill signal 停止标志信号(在命令中以 -signal 不同的数字选项来表示),以下表格列出了几种常用的标志信号,及其对应的进程停止方式:

标志信号名称数值选项注释
SIGHUP1这是挂起 HUP hang up 标志信号。重启指定的进程
SIGINT2这是中断 INT interrupt 标志信号。这是一个「较弱」的信号,即不能确保可以停止进程,但是一般情况下都是可行的
SIGQUIT3这是称为 core dump 核心转储的标志信号。它会终止进程,并将进程的相关信息存储在内存中,然后将此信息保存在当前工作目录的一个名为 core 的文件中
SIGTERM15这是终止 TERM terminate 标志信号。这是命令 kill默认标志信号
SIGKILL9这是完全终止 KILL 标志信号。它会将进程的资源发送到 /dev/null 这个特殊的位置来强制终止进程
说明

如果执行命令 kill 时不提供 -signal 选项,则标志信号默认为 -15,即采用 SIGTERM 标志信号

提示

也可以在运行命令 top 后,按下 k进入交互式命令行界面,来停止进程

按下 k后会出现提示 PID to signal/kill [default pid=xxx] 输入要停止的进程 PID(默认是第一个进程的 PID,即当前占用资源最大的进程)然后按下 Enter

然后会提示输入(停止标志信号所对应的)数值 Send pid xxx signal [15/sigterm](默认是 15 即采用 SIGTERM 标志信号)然后按下 Enter,以结束进程

在该过程中任何时候都可以按 Esc退出交互式命令行界面

除了通过 PID 指定需要停止的进程,还可以使用命令 killall 停止通过进程名称所指定的进程

bash
# 通过进程名称指定需要停止的进程
killall -9 zombieprocess

后台运行进程

在命令的最后添加 & 符号让命令程序在后台运行,这对于需要长时间运行的命令程序是更高效的执行方式,不必依赖占用当前打开的终端

所以按下 Enter后,终端并不会被运行的命令「占用」,终端会再显示一个命令提示符,可以继续接受输入新的命令

提示

可以使用命令 fg 将后台运行的进程移到「前台」(当前的终端)显示

bash
# 语法
fg %job_id

命令 fg 默认将最近启动的后台命令移到前台

如果后台有多个命令在运行,可以先通过命令 jobs 查看当前在后台运行的所以命令程序。每一行表示一个在后台运行的命令程序,在每一行的开头都有一个数字序号 num,可以通过这个序号,使用命令 fg %num 指定将哪个进程移到前台

定时执行程序

命令 at 适用于设置一个只执行一次的任务,它会在预设的时间执行作业

bash
# 执行该命令时需要设置一个时间
at time

其中参数 time 是设置进程在何时执行,它可以采用多种时间格式,列出一些常用的时间格式:

时间格式示例注释
at 7:20pm计划在当天晚上 7:20 运行指定的程序
at 7:20pm June 25计划在 6 月 25 日晚上 7:20 运行指定的程序
at noon计划在当天中午运行指定的程序
at noon June 25计划在 6 月 25 日中午运行指定的程序
at tomorrow计划在明天运行指定的程序
at now + 20 minutes计划从当前时间算起,20 分钟后运行指定的程序
at now + 10 hours计划从当前时间算起,10 小时后运行指定的程序
at now + 5 days计划从当前时间算起,5 天后运行指定的程序
at now + 3 weeks计划从当前时间算起,3 周后运行指定的程序
at 7:20pm 06/25/2019计划在 2019 年 6 月 25 日晚上 7:20 运行指定的程序

然后就会进入交互式命令行界面,终端会显示一个提示符 at> 让用户输入需要在未来执行的程序

bash
# 模拟设置定时执行程序的流程
kali >at 7:20am
at >/root/myscanningscript

命令 crond 则适用于设置定期执行的周期性任务

环境变量

Linux 的环境变量是指一个由字符串构成的键值对,其形式是 KEY=value,对于一个键对应于多个值的情况,其形式是 KEY=value1:value2

注意

如果在变量值中含有空格,则需要用双引号将变量值 "value" 包括起来

说明

环境变量其实有两种:

  • shell 变量:只是针对当前 shell 的变量,一般变量名采用小写形式
  • 环境变量:一般所说的环境变量都是指系统层面上的变量,构建在系统和接口上的变量,用于控制系统的外观、行为等,这些变量由子 shell 或进程继承。一般变量名采用大写形式

查看环境变量

命令 env 可以查看系统所有的默认环境变量

注意

但是命令 env 输出的结果只包含系统的默认环境变量,并不包括用户自定义的变量等

命令 set 查看所有的环境变量,包括 shell 变量、本地变量、 shell 函数(例如用户自定义的变量和命令的别名)

提示

但是命令 set 会一次性将所有的环境变量输出到终端。

可以通过管道操作命令 more 配合使用,这样就可以进入更方便的逐行查看的交互模式,按下 Enter再显示下一行,按下 q可以退出

bash
# 通过逐行查看的交互模式来查看环境变量
set | more

也可以通过管道操作命令 grep 配合使用,对所有环境变量进行筛选,只显示符合关键词的环境变量

bash
# 实例
set | grep HISTSIZE
说明

环境变量 HISTSIZE 用于设置终端的历史记录文件可存储的最大命令数,默认值是 1000,即最多可以存储 1000 条输入的命令,用户可以通过键盘的 UP 向上键 DOWN 向下键来翻看复用命令的历史记录

修改环境变量

注意

在修改环境变量的值之前,最好将原始值备份保存到一个文件中,以便之后恢复操作

以下是使用命令 echo 和重定向符号 > 将一个环境变量的值保存到指定的文件的示例

bash
# 将环境变量 HISTSIZE 的值保存到 ~/valueofHISTSIZE.txt 文件中
echo $HISTSIZE> ~/valueofHISTSIZE.txt

也使用类似的方法,将所有环境变量保存到文件中

bash
set > ~/allENV.txt

对于只有一个值的环境变量,可以在终端通过直接赋值的方式来修改环境变量的值。

例如不希望系统记录已输入的命令,则可以在终端为环境变量 HISTSIZE 重新赋值,将其设置为 0

bash
HISTSIZE=0

但是该操作是临时的,只会对当前会话有效(即当前的终端有效,重启或打开一个新的终端,该环境变量会使用回默认值)

如果希望将当前的修改永久保存下来,可以使用命令 export 将当前的环境变量的值导出到系统保存下来,这样就会永久更改环境变量的值,在其他环境中也能使用该值。

bash
# 将当前(终端)会话所设置的 HISTSIZE 环境变量值导出到系统中保存
export HISTSIZE

以下介绍一些常见的重要环境变量,可以通过修改这些环境变量以定制操作系统的行为

命令行提示符

通过环境变量 PS1 可以设置终端提示符的内容

提示

在更改 PS1 环境变量时,可以使用以下 3 个占位符,以表示保留特定信息:

  • \u 当前系统的用户名
  • \h 主机名
  • \W 当前终端所在的目录

PATH

在命令行界面运行程序时,终端会到特定的目录里寻找相应的程序并调用它。环境变量 PATH 就是用于指定这些目录的

提示

可以使用以下命令查看 PATH 环境变量的值

bash
echo $PATH
# 返回的示例值 /usr/local/sbin:usr/local/bin:/usr/sbin:/sbin/bin
# 该环境变量的值一般包含多个值,采用 `PATH=value1:value2:value3` 的形式,每个值(目录)以 `:` 冒号分隔

系统的大多数可执行程序都在目录都在 /usr/local/sbinusr/local/bin 里,这两个文件夹就包含在环境变量 PATH 的默认值中

如果程序所在的目录不包含在默认 PATH 变量值中,而且该目录也没有在安装程序时添加到 PATH,而且如果终端当前工作目录不是该程序所在的目录,则在终端通过相应的命令运行程序时,就会返回 command not found 错误警告

以上这个问题可以通过将程序所在的目录添加环境变量 PATH 来解决

bash
# 该命令相当于将环境变量原有的值 `$PATH` 追加上 `newhackingtool` 目录,构成新的值,再整体赋予给环境变量
PATH=$PATH:/root/newhackingtool
注意

为了安全起见,请在修改 PATH 环境变量前,将原始值备份存储在一个文件中

谨记以上的示例,在修改 PATH 环境变量时,要以追加的方式,而不是覆盖的方式

添加过多的目录到 PATH 环境变量可能导致终端执行命令的速度减低,因为它可能需要遍历这些目录来寻找程序

自定义环境变量

只需要在终端以 KEY=value 的形式就可以创建自定义的环境变量

同样需要通过命令 export 才可以将当前自定义的环境变量导出到系统中,永久保存

删除环境变量

命令 unset 删除环境变量

bash
# 语法
unset MYNEWVARIABLE

BASH 脚本

shell 是用户和操作系统之间的交互接口,它允许用户操作系统的文件,执行命令,运行程序等。在 Linux 平台中有一系列的 shell 软件,例如 Z shell、C shell 等,其中 bash shell 是最常见的,可以运行在几乎所有的 Linux 和 UNIX 发行版中。

bash 除了可以运行任何被终端支持的命令(如系统命令、应用程序相关命令等)以外,它还支持一些内置的命令。

以下是一些在 bash 里常用的命令

命令作用
:返回 0true
.执行脚本
bg将作业放到后台运行
break退出当前循环
cd改变工作目录
continue执行当前循环
echo回显随后的内容
eval计算随后的表达式
exec在不创建新进程的情况下执行命令
exit退出 shell
export将变量或函数导出,以便其他程序使用
fg将后台运行的作业带回到前台
getopts解析脚本的参数
jobs列出后台运行的作业
pwd显示当前工作目录
read读取标准输入的一行内容
readonly声明变量为只读
set列出所有的环境变量
shift将参数向左移动
test评估参数?
[执行测试条件
times打印用户和系统时间
trap追踪一个信号
type显示如何将每个参数解析为一个命令?
umask改变文件的默认权限
unset删除环境变量
wait等待后台进程完成
提示

需要一个文本编辑器来更高效地编写脚本,如 vi、vim、emacs、gedit、kate 等

首先要新建一个脚本文件,脚本文件使用 .sh 作为文件拓展名,这是一个约定俗成的习惯,并不强制限定,也不影响脚本文件的执行。

说明

如果省略文件的拓展名,则保存文件时,会默认保存为 shell script 脚本文件

以下是一个简单的 shell 脚本示例内容

example.sh
sh
#! /bin/bash
# This is my first bash script. Wish me luck.
echo "Hello, HackersArise!"
说明

在脚本开头的那一行,是为了指定操作系统使用哪一个解释器 interpreter 来解析当前的脚本,它由标识符 shebang #! 井号和感叹号组成,然后用空格间隔,并写上要调用的解释器(程序的路径)

然后就是有一行注释,注释的语法是在每一行前使用 # 井号,并用空格间隔。一般注释的作用是告诉使用者,该脚本的作用等。解释器在解析脚本时,会忽略掉注释的内容。

最后是一个简单的命令操作,命令 echo 将该命令后的内容回显(重复输出)到显示器上

注意

如果希望回显的内容是文本字符串,需要使用双引号 "" 将内容包括起来

新创建的脚本默认是无法执行的,即使执行脚本的用户是文件所有者,可以通过命令 ls -l 查看文件的权限,会看到脚本文件的默认权限是 rw--r--r--,即所有的用户都没有执行权限

需要通过命令 chmod 来更改脚本文件的权限

shell
# 为文件所有者、用户组、其他用户都添加执行权限
# 使用八进制数值语法来改变权限
chmod 755 script_file
# 使用 UGO 语法来改变权限
chmod u+x,g+x,o+x script_file

最后直接在终端输入脚本文件的路径,即可运行脚本

推荐

虽然可以只输入文件名来执行脚本,但是终端会在整个文件系统中寻找脚本,可能会运行其他非预期的同名的脚本,所以推荐在执行脚本时,采用相对路径或完整的路径,指明要执行的脚本文件的具体位置

shell
# 假设脚本文件就在当前工作目录
# 使用相对路径来运行脚本文件
./example.sh

允许使用者与脚本交互是十分有用的特性,例如允许用户输入一些参数,来决定脚本程序如何运行。其中需要使用命令 read 来读取用户的输入,使用变量来保存用户输入值。

说明

变量是一个位于内存的存储区域,它可能存储一些文本或数值,其内容是可变的,因此称为「变量」

以下是一个运行用户输入变量的实例

bash
#! /bin/bash
echo "What is your name?"
read name
echo "What chapter are you reading?"
read chapter
echo "Welcome" $name "to Chapter" $chapter

命令 read 临时阻断脚本的继续执行,提示并等待用户输入,然后将读取得到的键盘输入,保存到一个变量中

最后命令 echo 使用前面创建的变量,需要在变量名前添加 $ 符号,使用相应变量的值

归档与压缩

压缩文件会让文件体积更小,更容易被发送和下载。

对于一个初学者而言,可以简单地将压缩软件/算法区分为有损压缩 lossy compression无损压缩 lossless compression。在压缩算法中,其中压缩比例 compression ratio 是一个很重要的参数,当压缩比越高,意味着文件大小可以降低得越明显。

有损压缩对于减小文件大小很有效,但是会让信息的完整性有所丢失。适用于对图片、音频、视频文件进行压缩,因为人们也不易察觉图片的部分像素,或音频的部分音符的变化。一些常见的多媒体文件格式 .mp3.mp4.png.jpg 都是使用压缩算法处理后得到的。

无损压缩是为了保证数据的完整性,这对于文件和软件而言十分重要,所以不能采用有损压缩,Linux 有多种通用的程序和算法支持无损压缩。

归档

压缩的其中一个常见用途是将多个文档打包为一个文件,以便传送分享。

命令 tar 就是用作将多个文件归档 archive 为一个 *.tar 文件,该压缩归档的文件称为 archive、tar 文件或 tarball

提示

命令 tar 是单词磁带存档 tape archive 的缩写,这是指在计算机的的初始时期,使用磁带来保存数据

使用命令 tar -cvf 创建归档文件,其中使用了 3 个参数:

  • c 参数:创建一个新的归档文件(参数 c 是是单词 create 的缩写)
  • v (可选)参数:列出归档的文件清单(参数 v 是是单词 verbose 的缩写)
    提示

    如果使用了参数 v 则在命令执行完成后,会在终端输出归档/提取的原文件清单。也可以不添加该参数,这样归档/提取完成时就不会在终端输出结果

  • f 参数:将资料归档写入到后面指定的文件(参数 f 是单词 following 的缩写),该参数也可以在预览归档文件(读取其中包含的原文件清单)时使用
shell
# 将 file_1、file_2、file_3 这三个文件归档为一个 archive_files.tar 文件
tar -cvf archive_files.tar file_1 file_2 file_3
注意

使用命令 tar 将文件归档会让总体积增大,所以该过程并没有进行压缩操作,这对于小文件而言很明显,但是如果归档的文件较大时,这种体积的变化其实并不明显

使用命令 tar -tvf 在不提取 tar 包的情况下,预览其中包含的原文件清单,显示原始的文件(名称、权限、大小等)相关信息

shell
# 预览归档文件所包含的原文件
tar -tvf archive_files.tar

使用命令 tar -xvf 从归档文件提取出原始的文件到当前目录,其中使用了 3 个参数:参数 vf 作用参考上一个命令的说明,参数 x 是从归档文件提取出原文件(参数 x 是单词提取 extract 的缩写)

shell
tar -xvf archive_files.tar
# file_1
# file_2
# file_3
提示

如果当前目录已经有同名的文件,命令 tar 会用提取的文件替代已有的同名文件

压缩

Linux 有多个命令可以创建压缩文件:

  • 命令 gzip 创建 .tar.gz.tgz 压缩文件
  • 命令 bzip2 创建 .tar.bz2 压缩文件
  • 命令 compress 创建 .tar.Z 压缩文件

它们采用不同的压缩算法,有不同的压缩比例。其中命令 compress 压缩时间最快,但是压缩文件比较大;命令 bzip2 压缩时间最慢,而压缩文件较小;命令 gzip 则是在压缩时间和压缩文件之间都比较均衡

gzip

命令 gzip是 Linux 中最常见的一种压缩工具,它是单词 GNU zip 的缩写

使用命令 gzip 压缩文件,最后压缩文件 *.tar.gz 会替代原文件

shell
# 使用 gzip 压缩名为 file_name 的文件
# 使用通配符 * 表示文件为任何拓展名都可以
gzip file_name.*

使用命令 gunzip 解压缩文件,最后原文件会替代压缩文件

shell
# 使用 gzip 解压名为 file_name.tar.gz 的压缩文件
gunzip file_name.tar.gz
提示

命令 gunzip 还支持解压缩 *.zip 的压缩文件

bzip2

命令 bzip2 是 Linux 中另一种压缩工具

使用命令 bzip2 压缩文件,执行结果也是将压缩文件替代原文件

shell
bzip2 file_name.*

使用命令 bunzip2 解压缩文件,最后原文件也是会替代压缩文件

shell
bunzip2 file_name.tar.bz2

compress

命令 compress 是 Linux 中另一种压缩工具

使用命令 compress 压缩文件,最后生成一个拓展名为 .tar.Z 的压缩后的文件替代原文件

shell
compress file_name.*

使用命令 uncompress 解压缩文件,最后原文件也是会替代压缩文件

shell
uncompress file_name.*

dd 命令

命令 dd 可以按照逐个比特位 bit-by-bit 来复制文件、文件系统,甚至整个硬盘,因此该命令可以复制已经删除(可恢复)的文件

注意

而一般的复制命令,例如 cp,并不能复制已删除的文件

但是命令 dd不适用于日常的文件复制操作,因为它运行得十分缓慢,应该采用其他更方便、更高效的命令

shell
# 语法
dd if=inputfile of=outputfile

其中有两个参数:

  • 参数 if 设置 input file 来源文件
  • 参数 of 设置 output file 输出的路径

还有其他多种参数可以配置,其中较为有用的是以下两种:

  • 参数 noerror 忽略复制过程中的错误信息,继续复制
  • 参数 bs 设置块的大小(每个块的读/写字节数),默认为 512 bytes 字节,可以更改它以加速复制。一般将其设置为设备的扇区大小,通常是 4KB(即 4096 bytes 字节)

Copyright © 2024 Ben

Theme BlogiNote

Icons from Icônes