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: 驱动器
它就像一个倒置的树结构,最顶层是 /
称为文件系统的根
其中较为常用和重要的一些子目录如下
- 📁
/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 的文件系统中游弋 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
可基于关键词在文件系统中进行检索
locate nmap
注意
命令 locate
是基于一个索引数据库进行搜索的,但是该数据库并不会及时更新,所以文件系统新增的文件其索引可能要等待几分钟或几个小时才会被添加到数据库中。
所以要根据场景来判断是否使用该命令进行搜索
命令 whereis
查找二进制文件,返回该文件所在的目录,以及相应的手册页面文件的路径(如果存在手册页面时)
命令 which
在 Linux 系统环境变量 PATH
中查找二进制文件,返回环境变量中所存储的路径
提示
在命令行界面执行命令时,Linux 会基于环境变量 PATH
所存储的路径来寻找到对应二进制文件(程序)
环境变量 PATH
至少包含 /usr/bin
目录,有时候会包含 /usr/sbin
和其他目录
命令 find
是一个更强大灵活的搜索工具,可以设置很多参数,以定制搜索范围。
该命令的一般语法
# 搜索 directory 目录及其子目录的内容
# 还可以设置一系列的参数 options expression
find directory options expression
在根目录 /
开始
# 在根目录 `/` 开始搜索
# 参数 -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
对上一个命令的结果进行筛选
# 只显示 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
用于复制文件到指定的路径(目录)下,如果指定路径是以文件名结束的,则会同时进行重命名操作(这是可选操作)
# 将名为 `odlfile` 的文件复制到指定的目录 `/root/newdirectory` 并重命名为 `newfile`
cp oldfile /root/newdirectory/newfile
移动和重命名文件
命令 mv
将文件(剪切)移动到新路径(目录)下
提示
因为 Linux 系统并没有提供对文件直接进行重命名的命令,但可以利用命令 mv
移动文件来实现重命名的效果,只需要保证移动的目标路径和当前目录的路径相同,并在移动的同时重命名文件的名称即可
# 将名为 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
可以对所展示的文件内进行筛选,只显示含有关键字的特定行,通过管道 |
操作配合显示文件内容的命令来使用
# 查看文件,并筛选只显示带有关键字 "output" 那些行
cat /etc/snort/snort.conf | grep output
搜索替代内容
命令 sed
基于关键字(或正则表达式)对文件内容进行搜索匹配,并对匹配的内容进行操作,一般用于替换文本内容
sed s/mysql/MySQL/g /etc/snort/snort.conf > snort2.conf
说明
命令 s
表示 search 搜索,用 /
斜杆分隔需要搜索的关键字,接着用 /
斜杠分隔的是需要将匹配的内容替换为什么文本
命令 g
表示 global 全局,指搜索匹配对全文都有效。而如果不使用该命令,则命令 sed
的默认行为是,仅仅寻找并替换第一个匹配的内容;而如果不是命令 g
而是一个数值 n
,则表示仅仅寻找并替换第 n
个匹配的内容
然后用重定向符 >
将替换后的全文内容保存到另一个文件中
分析和管理网络
查看网络接口
命令 ifconfig
查询当前激活的网络,打印出相关的信息
提示
系统有不同的网络连接,该命令就会显示不同的内容
# 示例
>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 地址、所处的模式等
# 示例
> 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 是一项非常有用的绕过网络访问控制技术。
# 先使用命令 `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 地址
# 为 `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 信息
# 使用命令 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--
# 使用命令 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 中搜索该软件项目,使用以下命令进行下载
git clone project_github_url.git
查询安装包
在下载安装软件前,可以先使用以下命令在软件列表存储库 repository(本地的缓存)进行搜索,以检查是否有相应的软件包以供下载
apt-cache search package_name
说明
不同的 Linux 发行版会预装着不同的软件,而保存着这些软件列表信息的服务器称为 repositories 存储库。
一般不同的发行版都有维护着自己的存储库,这些软件列表虽然大同小异,但是使用其他发行版的软件列表,可能会导致安装的软件无法与系统配合工作,因为即使不同发行版的软件列表包含相同的软件,但是软件的版本也可能不同。
但是有时候发行版本身的软件列表并不完整,无法搜索到所需的软件,可能需要添加其他发行版的软件列表存储库,作为额外的后备选择。
在 📄 /etc/apt/sources.list
文件中添加后备的软件列表存储库,在安装软件时,会安装 sources.list
文件所列出的存储库顺序,依次搜索,直到找到可安装的软件为止。
但不推荐添加 testing 测试中、experimental 实验、unstable 不稳定类型的软件列表
提示
(不同 Linux 发行版)软件列表存储库 repository 是会定期更新,但是这些更新并不会自动推送同步到你操作系统本地的缓存中,需要手动调用以下命令来更新本地的软件列表
apt-get update
安装软件包
使用以下命令从软件存储库中下载并安装软件包
apt-get install package_name
在执行命令过程中,当软件包下载完成后会在命令行中显示一段提示,键入 y
以确认执行安装步骤
删除软件包
使用以下命令从电脑删除已安装的软件包
apt-get remove package_name
在执行命令过程中,当搜集完软件相关信息后会在命令行中显示一段提示,键入 y
以确认执行删除步骤
说明
在移除软件包过程中,可能会在终端看到提示输出,要同时删除一些其他的软件。
这是因为 Linux 为了让软件更小,会将依赖包差分为一个个小的程序,这样其他的软件就可以共享这些程序了。
如果这些依赖包只是当前目标软件所需要的,那么在删除目标软件时,这些依赖包也会被删除
注意
移除操作并不会删除软件包的相关配置文件,因为考虑到以后你可能要重新安装该软件包,所以将其保留,便于之后安装软件时做到开箱即用(无需再进行配置)
如果希望删除软件包时,同时将相关配置文件也删除,可以使用参数 purge
# 参数 purge 意为纯净、净化
# 所以采用该参数删除软件包时,会将配置文件也同时删除
apt-get purge package_name
升级软件包
使用以下命令升级电脑已安装的软件包
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 系统管理员,或文件所有者,则可以使用以下命令将文件的所有权「转移」给其他(单个)用户
# 将文件 /tmp/bobsfile 的所有权「转移」给用户 bob
chown bob /tmp/bobsfile
命令 chgrp
可以将文件的所有权「转移」给指定的群组(一类用户)
检查权限
命令 ls 后添加参数 -l 可列出文件和目录的详细信息,其中包含权限信息
该命令的输出结果中依次显示的信息:
- 该条目的类型
提示
如果是文件,则以 -
表示;如果是目录,则以 d
表示(单词 directory 的缩写),这是最常见的两种类型
- 文件或目录的权限,分别列出文件的所有者、当前用户群组、其他用户的权限
说明
依次列出三种用户的读取权限、写入权限、执行权限。
如果拥有权限就用相应的字母表示(r
表示读取权限,w
表示写入权限、x
表示执行权限),如果并不拥有对应的权限就用 -
表示(占位符)
一般只有二进制的可执行文件或脚本文件,用户才可能拥有 x
执行权限
- 文件或目录的链接数量
- 文件或目录的创建者/拥有者
- 文件或目录创建者所在的群组
- 文件或目录的大小(以字节 bytes 为单位)
- 文件或目录的创建(或最后修改)时间
- 文件或目录的名称
更改权限
命令 chmod
改变用户的权限
只能由 root 系统管理员,或文件(目录)的拥有者才可以更改文件的权限约束
提示
命令 chmod
是单词 change mode 的缩写
可以使用八进制数值语法来改变权限,这种方法是同时针对三类不同的用户(文件或目录的拥有者、拥有者所在的用户群组、其他用户)设置权限约束的
# 用 3 个八进制数值来设置文件(针对三类不同的用户)的权限约束
chmod octal_syntax file
说明
在计算机系统内部使用二进制来表示数据,对于权限的也是通过二进制 1
或 0
来表示权限的激活或失效状态。
文件对于一个用户的 rwx
权限约束需要 3 位二进制数字来表示,共有 8 种状态,所以可以简化为使用 1 位八进制的数字来表示
八进制 octal 由 0
至 7
共八种数字构成,满八进一
二进制 | 权限约束 rwx | 八进制 |
---|---|---|
000 | --- | 0 |
001 | --x | 1 |
010 | -w- | 2 |
011 | -wx | 3 |
100 | r-- | 4 |
101 | r-x | 5 |
110 | rw- | 6 |
111 | rwx | 7 |
使用 3 个二进制的数字或 1 个八进制的数字表示文件或目录针对一个用户的权限约束
所以当文件(或目录)要表示拥有者、当前用户组、其他用户(这三类不同用户)的权限约束时,需要使用 3 个八进制的数字
例如要为 📁 /etc/hosts
文件针对三类不同的用户,都设置为具有完全的权限时,可以用数字 777
(八进制)表示
chmod 777 /etc/hosts
也可以使用 UGO 语法来改变权限,这种方法是针对某一类用户(文件或目录的拥有者、拥有者所在的用户群组、其他用户,这三种用户任一)设置权限约束
# 为某一类用户设置权限约束
chmod ugo_syntax file
说明
以上命令中 ugo_syntax
是由三部分构成的:
- 首先取
u
、g
、o
任一值,以指定需要为哪一类用户设置权限
其中u
表示文件所有者,是单词 user(或 owner)缩写;g
表示拥有者所在的用户群组,是单词 group 缩写;o
表示其他用户,是单词 others 缩写 - 然后跟着取以下三个操作符之一,以表示添加还是删除操作特定的权限:
-
操作符:表示移除特定的权限+
操作符:表示添加特定的权限=
操作符:表示设置特定的权限
操作符=
是覆盖操作,将指定用户的权限设置为符号=
后所指定的权限;而操作符+
和-
是追加操作,从原有权限里添加或删除指定的权限 - 最后是需要设置的权限名称,可以是
rwx
中任一字母(或字母的组合)
例如要为 📁 /etc/hosts
文件针对其他用户 o
添加写入权限
chmod o+w /etc/hosts
提示
如果希望使用 UGO 语法同时对两个或以上的用户设置权限,可以将多个 ugo_syntax
用逗号 ,
分隔
# 为 hosts 文件同时针对用户群组和其他用户设置写入权限
chmod g+w,o+w /etc/hosts
默认权限
为了保证系统的安全,Linux 默认为文件设置权限为 666
(八进制),为所有目录设置权限 777
(八进制)。所以默认情况下,新下载的文件对于所有用户都是无法运行的(会弹出 "Permission denied"
的警告),而新建的目录则任何用户都可以读取和修改。
可以使用以下命令让拥有者(当前登录系统的用户)拥有所有权限,这样就可以运行下载的文件了
chmod 766 file_path
为了让系统更安全,还可以通过设置 umask 参数来修改文件和目录的默认权限
umask 所设置的 3 个(八进制)数字是作为减数(八进制运算),即从默认的权限里移除 umask 值所对应的权限,然后将得到新的值作为新建文件或目录的权限预设值
说明
mask 掩码,屏蔽之意
例如大部分基于 Debian 的 Linux 发行版的 umask 预设值都是 022
,则最终的权限(示意图如下)文件的拥有者只有可读和写入权限,用户群组和其他用户则只有可读权限
New files | New directories | 说明 |
---|---|---|
666 | 777 | Linux 原始的默认权限 |
-022 | -022 | umask |
644 | 755 | 最终的权限 |
每一个用户都可以在 📁 /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
输出的查询结果进行筛选,找到符合特定关键词的进程
# 从所有进程中筛选出具有关键字 msfconsole 的进程
ps aux | grep msfconsole
说明
因为对 ps
的输出结果进行筛选,所以得到的最终结果一般不带表头,因为那一行一般不会与关键字匹配
进程排序
说明
因为命令 ps
会按照进程的启动时间先后列出,而内核会在进程启动时给它们分配 PID,所以看起来就像命令 ps
的输出结果默认按照 PID 排序
命令 top
也是查看所有进程,但是会按照资源占用大小进行排序(最大占用率的进程先列出),并每 10 秒刷新一次,按 q
键结束命令
注意
虽然监听列出的是所有活跃的进程,但是页面不可滚动,只能显示一屏高度的占用率最大的进程,并且动态更新
可以通过该命令来监控系统的资源利用情况,类似于 Windows 系统的资源管理器
可以按下 H
键或 ?
键来启用交互式命令行的设置页面,阅读里面的帮助文档可以知道如何对命令 top 进行配置。
要退出交互式命令行的设置页面可按下 q
键或 Esc
键返回监控页面
改变进程优先级
系统中同时运行着很多进程,它们会相互竞争资源,内核会决定这些它们之间的优先级,可以使用命令来设置「建议」进程的优先级。
通过一个数值,称为 nice 值,来表示进程的优先级高低,其范围是 -20
到 +19
,默认值是 0
进程的 nice 值与优先级
说明
nice 其含义是「友善」,是对其他用户而言,你的进程有多友善。
所以设置的数值是「友善值」,当数值越高,表示该进程的优先级别越低,所占用的资源就可能越低,相应地对于其他用户而言,该进程就越「友善」;反之该数值越低,其优先级就越高。
当一个进程启动时,它会继承其父进程的 nice 值,并根据进程的所有者(或 root 超级用户)的设置,来修改进程的 nice 值
有两个命令可以用于修改进程的优先级,但是其作用和语法略有不同
命令 nice
用于启动一个程序,并改变相应进程的优先级
# 语法
nice -n number program
其中参数 -n
指定一个数值 number
,之后的参数 program
是需要修改优先级的程序文件。
该命令是在程序启动时,基于默认值再加上所设置的相对值(对应于单词 by),来设置进程的优先级
命令 renice
用于在进程运行过程中,修改它的优先级
# 语法
renice number PID
在命令 renice
后所设置的数值 number
是 nice 值的绝对值(对应于单词 to),范围是 -20
到 19
,由于使用 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 所指定的进程
# 通过 PID 指定需要停止的进程
kill -signal PID
(可选)参数 -signal
用于配置不同的数值选项,对应于不同的 kill signal 停止标志信号,即通过不同的方式来停止进程
共有 64 种 kill signal 停止标志信号(在命令中以 -signal
不同的数字选项来表示),以下表格列出了几种常用的标志信号,及其对应的进程停止方式:
标志信号名称 | 数值选项 | 注释 |
---|---|---|
SIGHUP | 1 | 这是挂起 HUP hang up 标志信号。重启指定的进程 |
SIGINT | 2 | 这是中断 INT interrupt 标志信号。这是一个「较弱」的信号,即不能确保可以停止进程,但是一般情况下都是可行的 |
SIGQUIT | 3 | 这是称为 core dump 核心转储的标志信号。它会终止进程,并将进程的相关信息存储在内存中,然后将此信息保存在当前工作目录的一个名为 core 的文件中 |
SIGTERM | 15 | 这是终止 TERM terminate 标志信号。这是命令 kill 的默认标志信号 |
SIGKILL | 9 | 这是完全终止 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
停止通过进程名称所指定的进程
# 通过进程名称指定需要停止的进程
killall -9 zombieprocess
后台运行进程
在命令的最后添加 &
符号,让命令程序在后台运行,这对于需要长时间运行的命令程序是更高效的执行方式,不必依赖占用当前打开的终端
所以按下 Enter
键后,终端并不会被运行的命令「占用」,终端会再显示一个命令提示符,可以继续接受输入新的命令
提示
可以使用命令 fg
将后台运行的进程移到「前台」(当前的终端)显示
# 语法
fg %job_id
命令 fg
默认将最近启动的后台命令移到前台
如果后台有多个命令在运行,可以先通过命令 jobs
查看当前在后台运行的所以命令程序。每一行表示一个在后台运行的命令程序,在每一行的开头都有一个数字序号 num
,可以通过这个序号,使用命令 fg %num
指定将哪个进程移到前台
定时执行程序
命令 at
适用于设置一个只执行一次的任务,它会在预设的时间执行作业
# 执行该命令时需要设置一个时间
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>
让用户输入需要在未来执行的程序
# 模拟设置定时执行程序的流程
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
键可以退出
# 通过逐行查看的交互模式来查看环境变量
set | more
也可以通过管道操作与命令 grep
配合使用,对所有环境变量进行筛选,只显示符合关键词的环境变量
# 实例
set | grep HISTSIZE
说明
环境变量 HISTSIZE
用于设置终端的历史记录文件可存储的最大命令数,默认值是 1000
,即最多可以存储 1000 条输入的命令,用户可以通过键盘的 UP
向上键和 DOWN
向下键来翻看复用命令的历史记录
修改环境变量
注意
在修改环境变量的值之前,最好将原始值备份保存到一个文件中,以便之后恢复操作
以下是使用命令 echo
和重定向符号 >
将一个环境变量的值保存到指定的文件的示例
# 将环境变量 HISTSIZE 的值保存到 ~/valueofHISTSIZE.txt 文件中
echo $HISTSIZE> ~/valueofHISTSIZE.txt
也使用类似的方法,将所有环境变量保存到文件中
set > ~/allENV.txt
对于只有一个值的环境变量,可以在终端通过直接赋值的方式来修改环境变量的值。
例如不希望系统记录已输入的命令,则可以在终端为环境变量 HISTSIZE
重新赋值,将其设置为 0
HISTSIZE=0
但是该操作是临时的,只会对当前会话有效(即当前的终端有效,重启或打开一个新的终端,该环境变量会使用回默认值)
如果希望将当前的修改永久保存下来,可以使用命令 export
将当前的环境变量的值导出到系统保存下来,这样就会永久更改环境变量的值,在其他环境中也能使用该值。
# 将当前(终端)会话所设置的 HISTSIZE 环境变量值导出到系统中保存
export HISTSIZE
以下介绍一些常见的重要环境变量,可以通过修改这些环境变量以定制操作系统的行为
PATH
在命令行界面运行程序时,终端会到特定的目录里寻找相应的程序并调用它。环境变量 PATH
就是用于指定这些目录的
提示
可以使用以下命令查看 PATH
环境变量的值
echo $PATH
# 返回的示例值 /usr/local/sbin:usr/local/bin:/usr/sbin:/sbin/bin
# 该环境变量的值一般包含多个值,采用 `PATH=value1:value2:value3` 的形式,每个值(目录)以 `:` 冒号分隔
系统的大多数可执行程序都在目录都在 /usr/local/sbin
或 usr/local/bin
里,这两个文件夹就包含在环境变量 PATH
的默认值中
如果程序所在的目录不包含在默认 PATH
变量值中,而且该目录也没有在安装程序时添加到 PATH
,而且如果终端当前工作目录不是该程序所在的目录,则在终端通过相应的命令运行程序时,就会返回 command not found
错误警告
以上这个问题可以通过将程序所在的目录添加环境变量 PATH
来解决
# 该命令相当于将环境变量原有的值 `$PATH` 追加上 `newhackingtool` 目录,构成新的值,再整体赋予给环境变量
PATH=$PATH:/root/newhackingtool
注意
为了安全起见,请在修改 PATH
环境变量前,将原始值备份存储在一个文件中
谨记以上的示例,在修改 PATH
环境变量时,要以追加的方式,而不是覆盖的方式
添加过多的目录到 PATH
环境变量可能导致终端执行命令的速度减低,因为它可能需要遍历这些目录来寻找程序
BASH 脚本
shell 是用户和操作系统之间的交互接口,它允许用户操作系统的文件,执行命令,运行程序等。在 Linux 平台中有一系列的 shell 软件,例如 Z shell、C shell 等,其中 bash shell 是最常见的,可以运行在几乎所有的 Linux 和 UNIX 发行版中。
bash 除了可以运行任何被终端支持的命令(如系统命令、应用程序相关命令等)以外,它还支持一些内置的命令。
以下是一些在 bash 里常用的命令
命令 | 作用 |
---|---|
: | 返回 0 或 true |
. | 执行脚本 |
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 脚本示例内容
#! /bin/bash
# This is my first bash script. Wish me luck.
echo "Hello, HackersArise!"
说明
在脚本开头的那一行,是为了指定操作系统使用哪一个解释器 interpreter 来解析当前的脚本,它由标识符 shebang #!
井号和感叹号组成,然后用空格间隔,并写上要调用的解释器(程序的路径)
然后就是有一行注释,注释的语法是在每一行前使用 #
井号,并用空格间隔。一般注释的作用是告诉使用者,该脚本的作用等。解释器在解析脚本时,会忽略掉注释的内容。
最后是一个简单的命令操作,命令 echo
将该命令后的内容回显(重复输出)到显示器上
注意
如果希望回显的内容是文本字符串,需要使用双引号 ""
将内容包括起来
新创建的脚本默认是无法执行的,即使执行脚本的用户是文件所有者,可以通过命令 ls -l
查看文件的权限,会看到脚本文件的默认权限是 rw--r--r--
,即所有的用户都没有执行权限
需要通过命令 chmod
来更改脚本文件的权限
# 为文件所有者、用户组、其他用户都添加执行权限
# 使用八进制数值语法来改变权限
chmod 755 script_file
# 使用 UGO 语法来改变权限
chmod u+x,g+x,o+x script_file
最后直接在终端输入脚本文件的路径,即可运行脚本
推荐
虽然可以只输入文件名来执行脚本,但是终端会在整个文件系统中寻找脚本,可能会运行其他非预期的同名的脚本,所以推荐在执行脚本时,采用相对路径或完整的路径,指明要执行的脚本文件的具体位置
# 假设脚本文件就在当前工作目录
# 使用相对路径来运行脚本文件
./example.sh
允许使用者与脚本交互是十分有用的特性,例如允许用户输入一些参数,来决定脚本程序如何运行。其中需要使用命令 read
来读取用户的输入,使用变量来保存用户输入值。
说明
变量是一个位于内存的存储区域,它可能存储一些文本或数值,其内容是可变的,因此称为「变量」
以下是一个运行用户输入变量的实例
#! /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 的缩写),该参数也可以在预览归档文件(读取其中包含的原文件清单)时使用
# 将 file_1、file_2、file_3 这三个文件归档为一个 archive_files.tar 文件
tar -cvf archive_files.tar file_1 file_2 file_3
注意
使用命令 tar
将文件归档会让总体积增大,所以该过程并没有进行压缩操作,这对于小文件而言很明显,但是如果归档的文件较大时,这种体积的变化其实并不明显
使用命令 tar -tvf
在不提取 tar 包的情况下,预览其中包含的原文件清单,显示原始的文件(名称、权限、大小等)相关信息
# 预览归档文件所包含的原文件
tar -tvf archive_files.tar
使用命令 tar -xvf
从归档文件提取出原始的文件到当前目录,其中使用了 3 个参数:参数 v
和 f
作用参考上一个命令的说明,参数 x
是从归档文件提取出原文件(参数 x
是单词提取 extract 的缩写)
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
会替代原文件
# 使用 gzip 压缩名为 file_name 的文件
# 使用通配符 * 表示文件为任何拓展名都可以
gzip file_name.*
使用命令 gunzip
解压缩文件,最后原文件会替代压缩文件
# 使用 gzip 解压名为 file_name.tar.gz 的压缩文件
gunzip file_name.tar.gz
提示
命令 gunzip
还支持解压缩 *.zip
的压缩文件
bzip2
命令 bzip2
是 Linux 中另一种压缩工具
使用命令 bzip2
压缩文件,执行结果也是将压缩文件替代原文件
bzip2 file_name.*
使用命令 bunzip2
解压缩文件,最后原文件也是会替代压缩文件
bunzip2 file_name.tar.bz2
compress
命令 compress
是 Linux 中另一种压缩工具
使用命令 compress
压缩文件,最后生成一个拓展名为 .tar.Z
的压缩后的文件替代原文件
compress file_name.*
使用命令 uncompress
解压缩文件,最后原文件也是会替代压缩文件
uncompress file_name.*
dd 命令
命令 dd
可以按照逐个比特位 bit-by-bit 来复制文件、文件系统,甚至整个硬盘,因此该命令可以复制已经删除(可恢复)的文件
注意
而一般的复制命令,例如 cp
,并不能复制已删除的文件
但是命令 dd
并不适用于日常的文件复制操作,因为它运行得十分缓慢,应该采用其他更方便、更高效的命令
# 语法
dd if=inputfile of=outputfile
其中有两个参数:
- 参数
if
设置 input file 来源文件 - 参数
of
设置 output file 输出的路径
还有其他多种参数可以配置,其中较为有用的是以下两种:
- 参数
noerror
忽略复制过程中的错误信息,继续复制 - 参数
bs
设置块的大小(每个块的读/写字节数),默认为 512 bytes 字节,可以更改它以加速复制。一般将其设置为设备的扇区大小,通常是 4KB(即 4096 bytes 字节)