我个人接触 Linux 比较早,最开始喜欢研究网络安全相关的话题,所以第一次使用的 Linux 系统是 Kali Linux,虽然现在有很多的 Linux 发行版本,但大多都是还是使用命令行进行操作的。和 MacOS 不同 Linux 大部分软件生态还是没有 Apple MacOS 完整,这里只的是图形界面和第三方公司开发的软件,而且大部分软件都是一些命令行下的软件,作为一名开发者都有必要掌握一些基础的 Linux 操作命令,这些都是类 Unix 系统,大部分基础命令是相通的,所以介绍同样常用的命令。


代替鼠标的命令

在 Windows 很少有人使用的 DOS 命令行进行操作,但是在 Linux 下最为常见的是使用命令行,当然 Windows 也可以完全使用的 CMD 命令进行操作来控制电脑,但是大部分人还是使用视窗界面和鼠标。如果计算机操作系统没有图形化界面那么估计到现在还没有普及起来呢。

最为常见为目录切换和文件查看,文件和目录创建、文件移动和文件复制、文件下载和文件编辑等操作,下面介绍:

# 使用 cd 可以切换目录
cd /home/auula
# 返回上一层目录
cd ..
# 使用相对路径切换
cd ../../xxx
# 快速返回到家目录
cd ~

创建文件和创建目录:

# 创建一个文件
touch Hello.java
# 更新一些文件最后访问时间
touch -d Hello.java
# 创建一个目录
mkdir /home/xxxx
# 递归创建目录
mkdir -p /home/a/b/c

文件移动和创新命名都为同一个 mv 命令:

# 将目录a到b中
mv /aaaxx/a /bbbxx/b
# 重新命名
mv a.tar b.tar

文件复制操作:

# 将a.txt文件复制到b目录中
cp /xxxx/a.txt /xxx/b
# 使用递归复制
cp -r /xxx/aaa/*.txt /xxx/bbb/

从远程的网络服务器上下载程序压缩包,可以有很多种方式,最常见上 wget:

# wget 下载文件 -b 后台运行 -c 支持断点续传
wget -b -c https://blog.ibyte.me/mirror/trojan-install.sh

查看当前工作目录的位置,和当前命令下有什么文件:

# 当前位置信息
pwd
# 查看当前目录下有什么文件,包括隐藏文件
ls -al

查看某个文件内容,如果文件内容太多可以分页查看:

# 查看某个文件的内容
cat /xxx/Hello.java
# 通过分页查看某个文件的内容
more /xxx/Hello.java

当在一个多层次顶层目录中,查看当前目录下的所有子目录:

# 查看当前目录,打印目录结构树
tree .

查看文件属性信息和文件夹属性信息:

# 查看文件属性信息
file Hello.java
# stat 查看文件夹和文件信息
stat directory

对文本文件内容高级操作:

# 查看文件的行数和字节树
wc -l /etc/passwd
# 替换文件内容的字符串
cat Hello.java | tr S X

对文件内容进行匹配过滤,和比较两个文件内容差异:

# 查看符合批评 root 字符串的内容
cat /etc/shadow | grep root
# 查看两个文件内容的差异
diff  -brief a.java b.java

在 Linux 系统中所有的东西都被抽象成了文件,所以如果要删除某个文件得注意!删除文件和目录命令如下:

# 删除某个目录,如果目录中有其他文件夹和文件会交互式删除
rm /xxxx
# 强制删除,通配符
rm -rf /xxxx/*.go

在 Linux 中安装软件传统的方式上通过源代码的方式进行编译安装,这种方式要求管理员自己解决各个软件包的依赖关系,还有一种方式采用的不同 Linux 发行版本中提供软件包管理工具来管理软件。目前为两大主流的发行版本,基于 Debian 和 Redhat 版本的,对于量大不同的包管理工具 deb 和 rpm,这里为主要介绍 rpm 的方式:

# 安装某个 rpm 软件包
rpm -ivh xxxx.rpm
# 查找安装目录
rpm -ql package | grep bin
# 查找某个全包名
rpm -qa | grep java
# 卸载某个软件包
rpm  -y remove package 

在命令行模式没有图形化界面来查看时间,如果需要查看当前系统时间,可以使用 date 命令:

# 格式化输出当前系统时间
date "+%Y-%m-%d %H:%M:%S %p"
# 当前已经过去多少天
date "+%j"
# 设置当前系统时间
date -s "20221101 8:30:00" 
# 设置时区
timedatectl set-timezone Asia/Shanghai

在磁盘上查找某个文件,有时候不知道文件存放在哪里,或者只记得文件的某个名称:

# 在某个目录下查询一个以Match开头的.java 源文件
find /xxx -name "Match*.java"

此种查询方式效率很低,另外一种方式上通过 locate 命令,此命令会先对目录和文件建立索引,在进行查询:

# 在运行 locate 命令之前先要建立索引
updatedb
# 在使用 locate 命令查找
locate wheris

在 Linux 中的软件都是带有命令本体和软件的使用文件的,要查询使用文档可以使用:

# whereis 查询 man 的命令的源代码和帮助文件
whereis man

如果需要查询某个命令本体安装路径:

# 查询某个程序的路径
which java

快速判断一个文件夹和文件是否存在,是否具备读写权限:

# 判断目录是否存在
[ -d /directory ] && echo "dir exist"
# 判断是否文件
[ -e /xxx/file.java ] && echo "file.java exist"
# 判断当前用户是否有写权限
[ -w /xxx/file.java ] && echo "file.java writeable"
# 判断当前用户是否有读权限
[ -r /xxx/file.java ] && echo "file.java readable"
# 判断当前用户是否有执行权限
[ -x /xxx/xxx.sh ] && echo "xxx.sh executable"

在括号中 [ expr ] 可以说其他支持 与、或、非 运算的表达式,例如判断一个当前登录的账号是不是超级管理员:

[ ! $USER = root ] && echo "user not administrator"

除此之外,还有支持大小比较运算:

# 等于
[ 10 -eq 10 ] && echo "equals"
# 不等于
[ 100 -ne 10 ] && echo "not equals"
# 小与
[ 10 -lt 100 ] && echo "less than"
# 大于
[ 100 -gt 10 ] && echo "greater than"
# 小于或者等于
[ 10 -le 10 ] && echo "less than & equal"
# 大于或者等于
[ 100 -ge 10 ] && echo "greater than & equal" 

要判断一个字符串是否为空:

# 判断字符串是否为空
[ -z $str ] && echo "is empty"

管道和重定向符号,将前面的程序的输出传入到下一个程序的输入:

# 将前面一个程序的输出输入下一个程序输入
cat /etc/passwd | grep root
# 将标准输出重定向到一个文件中
echo "Hello Shell" > text.txt
# 将标准错误和标准输出同时追加重定向到一个文件中
ls -l auula &>> tee.txt
# 将文本内容重定向到另外程序标准输入中
ssh root@xxxxxx < deploy.sh

查看系统进程和系统状态信息可以使用 PS 命令,大部分命令行软件运行在后台,如果想要停止运行某个软件就需要对应软件 PID ,如下:

# 显示系统中全部的进程信息
ps aux
# 以进程树的形式显示
pstree
# 返回 nginx 的任务 ID
pidof nginx
# 列出系统支持的全部信号列表:
kill -l
# 通过信号的方式控制一个进程,强制关闭进程
kill -9 1518

定时任务

说完最基本的代替鼠标操作的命令之后,介绍一下定时任务,Linux 系统主要的应用场景还是服务器端,服务器大部分不间断运行并且提供对外的服务,某些时候例如定期备份数据库,人工定期备份很麻烦这时可以使用定时任务来使用程序自动化完成。

at 命令可以用于在指定时间执行命令,at 只能适用于一种单一任务的定时器,会以 atd 守护进程的形式在后台模式运,会从任务队列里取出任务来执行。at命令的特点就是计划任务的一次性特征,一旦设置的计划任务被执行,则该任务就会被从任务列表库中删除,仅用于执行一次的工作:

# 指定一个脚本文件,并且设置执行时间
at -f task.sh 07:35
# 查看已经创建的任务
at -l
# 移除某个任务
at -d task_id
# 设置在2023年5月18日准时执行某脚本文件
at -f task.sh 05/18/2023
# 使用计划任务设置25分钟后执行某指定脚本文件
at -f task.sh now+25 min

另外一种为周期定时器,对应着某个时间段和某个时间点重复做某件事情,在物理上时间都直线运动,一直每分每秒前进,那就要设计一套规则来计算时间和时间单位。在圣经中上帝创造万物用了 7 天,所以现在用 7 天为一个星期的周期,每天 24 小时,一小时为 60 分钟,一分钟为 60 秒... 一年看 2 月份是润年还是平年,组成一个周期。周期定时器的时间设定就以此为单位,来重复某个任务,在 Linux 中有一个为 crond 命令提供此功能,crond 命令在设置的时候要提供日期占位符号:

# 每1分钟执行一次 task.sh
* * * * * task.sh
# 每小时的第3和第15分钟执行
3,15 * * * *  task.sh
# 每隔两天的上午8点到11点的第3和第15分钟执行
3,15 8-11 */2  *  * myCommand
# 每月1、10、22日的 4 : 45 重启smb
45 4 1,10,22 * * /etc/init.d/smb restart

权限管理

大家都说 Linux 系统比 Windows 安全,哪这里的安全体现在哪里?Linux 最初的版本是类似于 Unix 系统设计的,而 Unix 是一个多用户的操作系统,在同一时刻有多个用户可以登录到操作系统中完成任务,那么多个用户如何保证各自的文件安全性呢? 最初的设计者将引入了权限系统概念,权限系统可以帮助 Root 超级管理员用户管理其他用户的权限,在 Linux 系统中所有的东西皆为文件,对这些文件设置权限,就可以让多个用户之间保持某个规则来访问。

Linux 权限系统设计为:用户权限、所属组权限、其他权限;这 3 组权限都属于权限位都是一样的,分别为: R 可读 、W 可写 、 X 可执行,对应目录来说如果没有可执行权限,用户不能进入该目录,有读权限也只能文件列表。

权限位对应数字
R4
W2
X1

这是最基础的权限位,例如一个文件所有权限位为 rwx-r-x-rwx 换成数字表示为 757,下面介绍基于这些的身份权限操作:

# 查看当前用户是谁
who
# 查看当前用户的信息
id user_id
# 向系统中添加一个名为 user1 用户,并且设置默认的家目录和默认用户ID
useradd -d /home/directory_u1 user1 -u 8888
# 修改某个用户信息,将 user1 加入 root 扩展组,并且禁止用户登陆
usermod -G root -L user1
# 修改某个用户的密码
echo "New Passwd" | passwd --stdin user1
# 锁定用户,解锁 -u
passwd -l user1
# 查询密码状态
passwd -S user1
# 删除一个用户,并且删除用户家目录
userdel -r user1

以上为最基础的用户管理命令,默认创建的用户都有一个默认的与用户名同名的组名,一个用户可以是多个组称之为扩展组,如何创建一个组?默认使用 groupadd 命令即可:

# 创建一个组
groupadd www
# 将 nignx 用户添加到 www 组
usermod -G www nginx
# 更改用户组 ID
groupmod -g 6666 www
# 删除一个用户组
groupdel www
# 查看用户组是否被删除
cat /etc/group | grep www
# chown 和 chmod 都属于文件权限控制命令,chown 更能快捷修改文件所有者和所属组
chown nignx:www /wwwroot

除此之外还有还有超级权限位,默认的用户、所属组、其他组的权限位无法满足一些需求的时候就会使用到超级权限位,例如 SUID 、 SGID 、SBIT 权限位。

  • SUID 权限位可以让一个原本不属于该用户的文件能拥有属于该文件的权限,例如 ls -l /etc/passwd 让普通用户自己可以修改自己的密码。
  • SGID 权限位可以让用户临时获得文件所属组的权限,例如创建新文件会自动将其归属到对应目录到所属组中。
  • SBIT 权限位,很多第三方翻译成了 粘滞 Sticky Bit 位这是不正确的!应该叫保护位,设置了该权限位的目录,下的文件是无法被其他人删除的只能被所有者删除,例如 /tmp 目录。

这三组最高权限位的关系是:SUID = 2^2 、SGID = 2^1 、SBIN = 2^0 ,操作命令:

# 设置 SUID
chmod u+s xxx
# 设置 SGID
chmod g+s xxx
# 设置 SBIN
chmod o+t xxx
# 全部组应用规则
chmod a+x xxx

超级权限位在第一位,例如一个文件的权限是 1755 那么表示 rwxr-xr-t ,而 rwsrws-w- 表示 6772 ;另外如果一个目录没有 x 权限只有 r 权限,则表示只能读取目录里的内容,不能进入到目录中。除此之外还有一些隐藏更深的隐藏权限属性,chattr 命令其功能是用于更改文件隐藏属性,可用于针对目录和文件的隐藏权限做控制。

# 进追加的方式,并且修改之后立即同步到磁盘上
chattr +aS logging.log
# 递归设置目录,其中的子文件内容而不能新建或删除文件
chattr -R +i /root

以上权限管理命令只能针对的是用户、用户组、其他组来做权限控制,不能准确到某个特定用户身上和用户组上,针对此类需求可以使用文件访问控制列表策略,也称之为 ACL ,通过该技术可以更加精准的控制权限的分配。

# 只允许某个用户对目录有读写执行权限
setfacl -Rm u:nginx:rwx /www/wwwroot
# 允许某个组对目录有读和访问权限
setfacl -Rm g:www:rx /www/wwwroot
# 获取某个目录到 ACL 控制权限信息
getfacl -R /root > dir_root_backup.acl
# 从控制信息文件恢复 ACL 
setfacl --restore dir_root_backup.acl
# 取消某个用户的独立权限,-d 是全部清理掉
setfacl -x u:nginx /www/wwwroot

除以权限控制规则以外,默认普通用户除用户 ID 为 000 是超级管理员用户之外,其他用户在执行 sbin 系统级的命令时需要提权操作,例如 fdiks 命令对硬盘进行分区操作,这是要管理员用户才有权限执行的命令。如果普通用户要执行此类操作必须临时使用 sudo 命令获得超级权限来执行,另外一种方式为通过 visudo 命令进行配置,指定某个用户能获取什么样的命令权限。

# 例如规则: 用户名 允许操作的网段=临时拥有的身份用户 允许操作命令路径
auula   192.168.31.0/255=(root)    /usr/bin/cat,/usr/sbin/fdisk
# 检查配置 /etc/sudoers 文件配置项是否合规
visudo -c
# 配置提权时不需要输入密码
auula   ALL=(ALL)   NOPASSWD: ALL 
# 配置组规则,允许对应组旗下人员有高级权限
%www    ALL=(ALL)   ALL

文件系统

在所有的操作系统中文件系统都属于一层对于底层硬件磁盘设备的抽象,在 Linux 内核中也是这样的,内核为用户提供一层为 Virtual File System 简称为 VFS 接口,用户操作文件时实际上操作的是操作这层接口。在日常使用 Windows 和 MacOS 时感觉不到硬件变动对于文件系统影响,例如插入一个 USB 设备到电脑中,文件系统会默认将其连接上,而在 Linux 上需要人工手动分区和格式化再将其挂载到指定目录中使用。

# 挂载指定硬件设备到指定目录
mount /dev/sda3 /backup
# 查看某设备到 UUID
blkid /dev/sr0 
# 也可以通过硬件设备到唯一 ID 进行挂载
mount UUID=c6f831b1-5ede-4e06-9dd3-eecb42cc4934 /backup
# umount 可以用于卸载已经挂载的设备
umount /dev/sdb2
# 查看各个硬件设备和分区挂载的关系
lsblk
# 查看当前磁盘和分区使用状态
df -h
# 查看某个目录占用内存大小
du -sh

大部分设备一段挂载是不会变动的,但是某些情况下服务器重启会导致设备挂载也失效,这时候需要配置开机主动挂载,需要编辑 /etc/fstab 文件中配置信息。

以上是针对已经分区并且格式化好的文件系统,如果服务器新加了一块磁盘,此时就需要进行对磁盘进行分区然后使用文件系统格式化,最后挂载到指定目录才能被正常使用。分区会用 fdisk 工具进行分区,此工具目前只能适用于 MBR 的分区表,最多支持 2TB 磁盘,相当于普通服务器完全就够用的;分区完成之后会进行文件系统格式化,这里 Linux 默认提供了 mkfs 命令,次命令有很多子命令例如 mkfs.ext2 mkfs.ext3 mkfs.xfs 文件系统格式,当格式化完成之后使用 mount 挂载到指定目录即可。


挂载交换区

另外一个文件系统为交换区,可以帮助操作系统在物理内存不够情况下创建新的硬盘交换区,以此充当扩展内存使用,但是磁盘和内存读写速度有明显差距,创建 swap 分区的方式有很多,例如 fdisk 命令,也可以提供 fallocate 命令和 mkswap 命令,注意使用 fdisk 时得需要将其 partition type 修改为 82 表示为交换区格式。

# 格式化分区
mkswap /dev/sda3
# 挂载交换区
swapon /dev/sda3
# 设置开机自动挂载
echo "/dev/sda3     none    swap    defaults    0 0"   >>   /etc/fstab

网络防火墙

在 Linux 中防火墙功能可以控制网络数据包数据包的交换,也是保障服务器数据安全性方面最重要的功能,往往服务器上允许部分应用不允许被外界所访问到,这是就可以使用防火墙规则来控制了。 Linux 中的防火墙自身的流量进行过滤,防火墙底层实现基于内核的 netfilter 和 nftables 包过滤器的,而对于普通用户使用的 iptables 和 firewalld 命令只是一个便于配置过滤器规则的工具而已。

在网络层次 OSI 模型中,iptables 属于数据链路层的服务,会对网络上的流量按照规则:源地址 、 目的地址 、端口、传输协议 、服务类型信息从上至下进行规则匹配,如果匹配到了则会按照预先设置的规则来处理。

# 查看已经配置的策略
iptables -L
# 清理掉配置策略
iptables -F
# 设置把INPUT链设置默认规则为 DROP
iptables -P INPUT DROP
# 允许 INPUT  链的 ICMP 流量进入,例如允许 PING 命令样有响应
iptables -I INPUT -p icmp -j ACCEPT
# 删除刚刚给 INPUT 添加的规则,指定链和第几条
iptables -D INPUT 1
# 允许某个网段访问并且制定协议和端口
iptables -I INPUT -s 192.168.31.0/24 -p tcp --dport 22 -j ACCEPT
# 开放 HTTP 的 80 端口
iptables -I INPUT -p tcp --dport 80 -j ACCEPT
# 只接受某个网卡接口的流量
iptables -A INPUT -i eth0 -j ACCEPT
# 过滤掉转发的流量,IP 到 IP 到数据包
iptables -A FORWARD -s 192.168.1.0/24 -d 10.0.0.1/24 -j DROP
# 禁止某个端口范围进行访问
iptables -A INPUT -p udp -dport 1024:65535 -j REJECT
# 永久生效添加策略规则
iptables-save

iptabls 命令功能远不止这么多,最常用是基于 filter 功能对 chain 上的数据包进行过滤,另外一款最新的服务器设置工具是 firewall-cmd 命令,提供 GUI 和命令行版本,并且还有自动化命令参数补全功能,可以查看 firewall-cmd命令


命令行很酷

在类 Unix 系统下有很多的有趣第三方软件,例如 sl 可以跑火车,Linux 是一款类似 Unix 操作系统很多东西都是通用的,很多的第三方开发者也实现不少的命令行软件,这里我介绍几个可以能提升开发效率的命令行软件。

第一款是 cheat.sh 这是一款基于在线网络的命令行和编程案例查询工具,可以基于 curl 发起一个 http 请求到达 cheat 服务器,cheat 服务器会返回相应的结果,例如查询 kotlin 语言中的 for 循环语句怎么使用?

或者查询某个 Linux 命令不知道也什么参数和如何使用?

第二款是 wttr.in 也是基于网络服务的命令行工具,同样要使用 curl 发起一个 http 请求查询数据并且展示到终端上,例如查询上海的未来天气情况?

第三款 branch.sh 同样也是基于网络服务的命令行工具,可以使用以下命令来查看您的 Linux 系统信息,还可以测试网络带宽及硬盘读写速率,机器性能如何?

第四款为命令行下日历程序,在没有 GUI 界面下绘制日历表格,命令为 cal


其他资料

便宜 VPS vultr
最后修改:2023 年 07 月 05 日
如果觉得我的文章对你有用,请随意赞赏 🌹 谢谢 !