linux期末考试知识点总结
期末知识点总结
第一章 linux操作系统简介
?考点
1.什么是自由软件?
答:自由软件是指其使用者可以自由使用、复制、散布、研究、改写、再利用的软件。有以下四个自由:
- 不论目的如何,有使用该软件的自由。
- 有研究该软件如何运作的自由,并且可以改写该软件来满足使用者自身的需求。
- 有取得该软件源码的自由。
- 有改善再利用该软件的自由,并且可以发表改写版供公众使用。
2.linux操作系统的特点有哪些?
答:Linux操作系统是一个自由软件,允许用户自由修改和分发系统,具有开放性、多用户多任务、有良好的用户界面、丰富的网络功能、安全稳定、可移植、支持多文件系统的特点。
3.常见的linux发行版本有哪些?
答:有Red Hat,Ubuntu,OpenSuse,CentOS,Fedora。
第二章 linux常用命令
2.1 常用简单命令
data
命令:显示系统当前日期和时间。
pwd
命令:显示当前工作路径。
cd
命令:切换当前路径。
cal
命令:显示日历,公元1~9999年中的某年某月的日历。
#不带参数默认显示当前月份日历
[root@master ~]# cal
May 2025
Su Mo Tu We Th Fr Sa
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
#指定显示1998年2月的日历
[root@master ~]# cal 12 1998
December 1998
Su Mo Tu We Th Fr Sa
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
who
命令:显示当前已经登录到系统的所有用户名、登录终端、登录时间。
wc
命令:统计给定文件的行数、字数、字符数。
- -l 表示统计行数(line)。
- -w 表示统计单词数(word)。
- -c 表示统计字符数(char)。
[root@master test]# wc -lwc 1.txt
1 1 10 1.txt
uname
命令:显示操作系统的当前信息。
[root@master test]# uname
Linux
[root@master test]# uname -a
Linux master 3.10.0-1160.119.1.el7.x86_64 #1 SMP Tue Jun 4 14:43:51 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux
clear
命令:刷新屏幕,清空屏幕上的所有字符。
logout
命令:注销登录信息,退出系统,回到当前登录页面。
shutdown
命令:关闭操作系统,相同的命令还有poweroff
,``init 0`。
2.2 命令高级操作
命令补全:Tab键。
使用历史命令:history
命令,或者上下箭头。
输入/输出重定向:
?将命令的输入、输出或错误信息重定向到文件、设备或其他命令,而非默认的终端(屏幕或键盘)。
#输入重定向
< 从文件读取输入
#输出重定向
> 覆盖目标文件(若文件已存在,则清空后写入)
>> 将命令的输出追加到文件的末尾,而不是覆盖文件内容。
2> 将命令的错误输出重定向到文件(覆盖)。
&> 将命令的标准输出和错误输出同时重定向到文件。
管道:
?可以将一个命令的输出作为另一个命令的输入,从而将多个简单命令连接在一起实现复杂的功能。
[root@master test]# ls
1.txt 2.txt
[root@master test]# ls | cat *.txt
123456789
111
2.3 文件操作命令
显示
cat
命令:显示文件内容。
[root@master test]# cat 1.txt
123456789
qqqqqqqq
#带行号显示文件内容 -n
[root@master test]# cat -n 1.txt
1 123456789
2 qqqqqqqq
more
命令:分屏显示大文件,当满一屏后停下来,屏幕底部给出提示信息,显示该文件的百分比:--More--(XX%)
- 空格键 显示下一屏内容。
- B键 显示上一屏内容。
- Enter键 显示下一行内容。
- Q键 退出more命令。
head
命令:显示文件的开头内容,默认显示头10行的内容。
#显示/etc/passwd文件前20行内容,每行都加行号 (使用管道)
cat -n /etc/passwd | head -20
tail
命令:显示文件的尾部内容,默认显示末尾10行的内容。
#显示/etc/passwd文件13-23行的内容,每行都加行号
cat -n /etc/passwd | head -13 | tail -23
拷贝
cp
命令:复制文件或目录,也可以重命名。
- -f 强制复制文件或目录,不论是否存在。
- -i 覆盖文件前先询问用户。
- -l 对源文件建立硬链接,而非复制文件。 cp -l 源文件 硬链接名
- -s 对源文件建立符号链接,而非复制文件。 cp -s 源文件 软链接名
- -R/r 递归处理指定目录下的所有文件和子目录。
搬移
mv
命令:移动文件或目录,也可以重命名,同样的有-i,-f参数。
删除
rm
命令:删除文件或目录,参数有-i,-f,-r。
列表
ls
命令:显示文件列表(list)
- -a 显示所有的文件和目录,包括带.开头的隐藏文件。
- -l 以长格式(详细信息)显示目录下的文件列表,包括权限、所有者、大小、修改时间等。
- -r 以文件名反序排列。
- -t 以文件和目录的更新时间排序。
- -R 递归显示指定目录下所有的文件和子目录。
切换
cd
命令:切换工作目录。
- cd ~ 返回用户主目录。
- cd / 进入根目录。
- cd ../ 返回上级目录。
- cd ../.. 返回上两级目录。
建立空文件
touch
命令:创建新的空文件或者改变已有文件的时间标签。
- 当文件不存在时,创建文件。
- 当文件存在时,更新文件的时间。
[root@master test]# ls -l
total 8
-rw-r--r-- 1 root root 19 May 7 15:20 1.txt
-rw-r--r-- 1 root root 5 May 7 15:00 2.txt
[root@master test]# touch 3.txt
[root@master test]# ls -l
total 8
-rw-r--r-- 1 root root 19 May 7 15:20 1.txt
-rw-r--r-- 1 root root 5 May 7 15:00 2.txt
-rw-r--r-- 1 root root 0 May 7 15:50 3.txt
[root@master test]# touch 1.txt
[root@master test]# ls -l
total 8
-rw-r--r-- 1 root root 19 May 7 15:50 1.txt
-rw-r--r-- 1 root root 5 May 7 15:00 2.txt
-rw-r--r-- 1 root root 0 May 7 15:50 3.txt
查看文件类型
file
命令:显示文件类型。
查找
find
命令:在目录中查找文件。
- -name 指定文件名字符串,可以匹配*和?
- -type 指定文件类型,f为普通文件,d为目录,l为符号链接,p为命名管道,s为套接文件。
- -user 指定拥有者名称。
- -group 指定群组名称。
查找字符串
grep
命令:匹配关键字信息,查找的对象是纯文本文件。
- -i 忽略字符大小写差别。
- -n 标出行号。
- -v 反转查找,即查找不包含所查字符串的行。
文本排序
sort
命令:将文件进行排序,不改变排序的对象,只输出排序的结果,想要改变文件,可以进行重定向。
- -r 以相反的顺序来排序。
- -f 忽略大小写。
- -n 以数值来排序。
目录
mkdir
命令:创建目录。
- -p 一并建立上层目录。mkdir -p dir1/dir2
- -m 建立目录的同时设置权限。mkdir -m 744 dir
rmdir
命令:删除空目录。
- -r 强制删除目录及目录中的文件和子目录。
- -p 递归删除其上层空目录。
打包压缩
tar
命令:打包文件或目录。
- tar -czvf:压缩。tar -czvf 压缩包名 文件(*.c)
- tar -xzvf:解包。
2.4 用户和组管理命令
配置文件
/etc/passwd
文件:核心的用户账户数据库文件,存储了所有用户账户的基本信息。
[root@master ~]# cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
用户名:口令:用户ID:组ID:注释性描述:主目录:登录shell
- 口令字段用“x”填充,真正的口令经过加密保存在/rtc/shadow中。
- 用户ID是一个整数,root用户的ID为0,系统用户ID为1~999,普通用户ID从1000开始。
- 主目录是用户登录系统后的初始工作目录。
/etc/shadow
文件:存储加密密码和账户安全信息(如密码过期时间),仅 root 可读。
/etc/group
文件:存储用户组信息,与 /etc/passwd
的 组ID 字段关联。
[root@master ~]# cat /etc/group
root:x:0:
bin:x:1:
daemon:x:2:
组名称:组密码:组ID:组用户列表
- 组用户列表中,不同用户之间用逗号隔开。
etc/gshadow
文件:存储用户组密码、组管理员和附加用户列表。
[root@master ~]# cat /etc/gshadow
root:::
bin:::
daemon:::
组名称:组密码:组管理员账号:组用户列表
命令
useradd
命令:添加用户账号,并设置用户名、用户组、主目录、登录shell。
useradd [选项] 用户名
选项 | 说明 | 示例 |
---|---|---|
-u UID | 指定用户 ID(默认从 1000 开始分配,避免与系统用户冲突)。 | useradd -u 2000 alice |
-g 组名或组ID | 指定用户的主组(必须已存在)。 | useradd -g developers bob |
-G 附加组名或组ID | 指定用户的附加组(多个组用逗号分隔)。 | useradd -G wheel,admin carol |
-c "注释" | 添加用户描述(如全名)。 | useradd -c "Alice Johnson" alice |
-d 家目录路径 | 指定用户家目录(默认 /home/用户名 )。 | useradd -d /opt/data/alice alice |
-s Shell路径 | 指定用户登录 Shell(如 /bin/bash 、/sbin/nologin )。 | useradd -s /bin/zsh zoe |
-m | 创建用户家目录(若未指定 -d ,则默认在 /home/用户名 )。 | useradd -m dave |
-M | 不创建用户家目录(与 -m 相反)。 | useradd -M service_user |
-p 加密密码 | 直接指定加密后的密码(不推荐,密码应通过 passwd 单独设置)。 | useradd -p '$6$...' alice |
-e 过期日期 | 设置账户过期日期(格式 YYYY-MM-DD )。 | useradd -e 2024-12-31 alice |
-f 密码过期宽限期 | 设置密码过期后账户被禁用的天数(-1 表示永不禁用,0 表示立即禁用)。 | useradd -f 7 alice |
passwd
命令:管理用户密码。
passwd [选项] 用户名
选项 | 说明 | 示例 |
---|---|---|
无选项 | 当前用户修改自身密码(需输入旧密码)。 | passwd |
用户名 | root 用户修改其他用户的密码(无需旧密码)。 | sudo passwd alice |
-l | 锁定用户账户(禁止登录)。 | sudo passwd -l alice |
-d | 删除用户密码(使账户无需密码即可登录,不安全,慎用)。 | sudo passwd -d alice |
-S | 显示用户密码状态(是否锁定、过期时间等)。 | passwd -S alice |
-e | 强制用户下次登录时修改密码(立即过期)。 | sudo passwd -e alice |
userdel
命令:删除用户账号。
userdel [选项] 用户名
选项 | 说明 | 示例 |
---|---|---|
-r | 删除用户家目录和邮件池(通常位于 /home/用户名 和 /var/mail/用户名 )。 | sudo userdel -r alice |
-f | 强制删除用户(即使用户已登录或进程正在运行,慎用)。 | sudo userdel -f alice |
usermod
命令:修改账户属性。
-l 新用户名 旧用户名
:修改用户名。-u UID
:修改用户 ID(UID)。-g 主组
:修改用户的主组。-G 附加组列表
:修改用户的附加组(多个组用逗号分隔)。-a -G 附加组
:追加用户到附加组(不替换原有附加组)。-d 新家目录 [-m]
:修改家目录,-m
可自动移动原目录内容。-s 新 Shell
:修改用户的登录 Shell。-c "备注信息"
:修改用户的描述信息。-e 过期日期
:设置账户过期日期(格式如YYYY-MM-DD
)。-L
:锁定用户账户,禁止登录。-U
:解锁用户账户,允许登录。
groupadd
命令:添加用户组账号。
groupdel
命令:删除用户组。
groupmod
命令:修改用户组属性。
su
命令:切换当前用户身份到其他用户。
sudo
命令:以root身份执行命令。
2.5 网络管理命令
配置网络
ifconfig
命令:配置和显示linux内核中网络接口的网络参数。
选项 | 说明 | 示例 |
---|---|---|
-a | 显示所有网络接口(包括未启用的) | ifconfig -a |
[接口名] | 仅显示指定接口的信息(如eth0、lo) | ifconfig eth0 |
up | 启用指定网络接口 | ifconfig eth0 up |
down | 禁用指定网络接口 | ifconfig eth0 down |
address IP | 设置接口的IPv4地址 | ifconfig eth0 192.168.1.100 |
netmask MASK | 设置子网掩码 | ifconfig eth0 netmask 255.255.255.0 |
broadcast IP | 设置广播地址 | ifconfig eth0 broadcast 192.168.1.255 |
hw ether MAC | 修改接口的MAC地址 | ifconfig eth0 hw ether 00:11:22:33:44:55 |
-s 或 -v | 显示简洁统计信息(-s )或详细信息(-v ) | ifconfig -s 或 ifconfig -v eth0 |
显示主机名称
hostname
命令:显示或设置主机名。
选项 | 说明 | 示例 |
---|---|---|
无选项 | 显示当前系统主机名 | hostname |
[名称] | 更改主机名 | hostname linux-1 |
查看网络状态
netstat
命令:查看网络系统的状态信息。
选项 | 说明 | 示例 |
---|---|---|
无选项 | 显示所有活动连接(包括监听和非监听端口) | netstat |
-a | 显示所有连接和监听端口(包括TCP和UDP) | netstat -a |
-t | 仅显示TCP连接 | netstat -t |
-u | 仅显示UDP连接 | netstat -u |
-l | 仅显示监听中的端口 | netstat -l |
-c | 持续列出网络状态(每秒刷新一次) | netstat -c |
-r | 显示内核路由表 | netstat -r |
-p | 显示进程ID和程序名(需要root权限) | sudo netstat -p |
-s | 显示网络工作信息统计表(按协议分类) | netstat -s |
测试网络主机是否联通
ping
命令:测试主机之间的网络联通性,通过向被测试的目标主机地址发送ICMP报文并接收回应报文来测试当前主机和目标主机之间的网络连接状态。
选项 | 说明 | 示例 |
---|---|---|
-c COUNT | 发送指定数量的ICMP请求后停止(默认无限发送,需手动终止) | ping -c 4 example.com (发送4次后退出) |
-i INTERVAL | 设置发送请求的时间间隔(秒,默认1秒,需root权限可设小于0.2秒) | ping -i 2 192.168.1.1 (每2秒发送一次) |
-s PACKET_SIZE | 指定发送的ICMP数据包大小(字节,默认56字节,实际ICMP报文为64字节,含8字节ICMP头) | ping -s 100 example.com (发送100字节的数据包) |
-v | 详细输出(显示额外调试信息) | ping -v 192.168.1.1 |
-r | 记录路由过程 | ping -r www.baidu.com |
发消息/广播
write
命令:给其他用户发送实时消息,要求该用户必须登录系统。
write 用户名
[root@master ~]# write tiger
write: tiger is not logged in
[root@master ~]# write tiger
Hello tiger,I'm root.
^D
输入要发送的信息后,需要用Ctrl+D来结束。
wall
命令:以广播的方式给所有用户发送实时消息(write all)。
wall 消息内容
如果消息较多,可以先将消息保存在文件里,然后以文件的形式发送。
设置是否接收消息
mesg
命令:设置是否接收来自其他用户的消息。
查看当前状态:直接输入 mesg
(不带参数)会显示当前终端的消息接收状态(is y
或 is n
)。
mesg y
:允许其他用户向当前终端发送消息。
mesg n
:禁止其他用户向当前终端发送消息。
2.6 进程管理命令
查看进程
ps
命令:查看当前系统的进程状态。
选项 | 说明 | 示例 |
---|---|---|
-e | 显示所有进程,显示每个进程所用的环境变量(包括其他用户的进程) | ps -e |
-f | 显示进程的详情信息(包括UID、PID、PPID等) | ps -f |
-u | 显示指定用户的进程(默认当前用户) | ps -u root |
-r | 仅显示运行中的进程 | ps -r |
-l | 以长格式显示进程列表(含优先级、NI值等) | ps -l |
-x | 显示无控制终端的进程(如守护进程) | ps -x |
-p PID | 显示指定PID的进程 | ps -p 1234 |
-C | 显示指定命令名的进程(如nginx ) | ps -C nginx |
-aux | 显示所有用户的所有进程(BSD风格,包含详细信息) | ps -aux |
-ef | 显示完整格式的所有进程(System V风格) | ps -ef |
显示进程树
pstree
命令:以树的方式显示进程与子进程之间的关系。
[root@master ~]# pstree
systemd─┬─2*[agetty]
├─auditd───{auditd}
├─chronyd
├─containerd───14*[{containerd}]
├─crond
├─dbus-daemon
├─dockerd───11*[{dockerd}]
├─filebeat───12*[{filebeat}]
├─gssproxy───5*[{gssproxy}]
├─irqbalance
├─java───36*[{java}]
├─lvmetad
├─master─┬─pickup
│ └─qmgr
├─polkitd───6*[{polkitd}]
├─rpcbind
├─rsyslogd───2*[{rsyslogd}]
├─sshd───sshd───bash───pstree
├─systemd-journal
├─systemd-logind
├─systemd-udevd
└─tuned───4*[{tuned}]
实时显示进程
top
命令:实时查看进程占用系统资源的情况,可以按使用系统资源进行排序。
[root@master ~]# top
#第一行(任务队列信息) 启动时间 登录用户 负载均衡平均值 过去1分钟,5分钟,10分钟
top - 10:52:00 up 14 days, 16:51, 1 user, load average: 0.00, 0.01, 0.05
#第二行(进程) 僵尸进程数
Tasks: 98 total, 2 running, 96 sleeping, 0 stopped, 0 zombie
#CPU状态 用户空间占比 内核占比 空闲CPU占比 虚拟机占比
%Cpu(s): 0.3 us, 0.5 sy, 0.0 ni, 99.2 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
#内存状态 缓存的内存量
KiB Mem : 15901800 total, 13691596 free, 726928 used, 1483276 buff/cache
#Swap交换分区
KiB Swap: 0 total, 0 free, 0 used. 14772204 avail Mem
#系统状态信息 优先级
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
7557 root 20 0 483188 41236 20640 S 2.0 0.3 122:24.52 filebeat
418 root 20 0 0 0 0 S 0.3 0.0 8:42.01 xfsaild/dm-0
1 root 20 0 52068 4272 2660 S 0.0 0.0 5:04.03 systemd
2 root 20 0 0 0 0 S 0.0 0.0 0:00.14 kthreadd
4 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 kworker/0:0H
进程优先级
nice
命令:改变程序执行的优先级。应用程序优先级范围是-20~19,数字越小,优先级越高。
- -n 指定程序或命令运行的优先级。 nice -n 19 ./test
renice
命令:允许用户修改一个正在运行进程的优先级(只能改变自己进程的优先级)
- -n 指定程序或命令运行的优先级。
- -g 指定进程组ID。
- -p 改变指定PID程序的优先级。
- -u 指定开启进程的用户名。
#改变指定进程的优先级
[root@master ~]# renice -n 1 -p 2740
杀死进程
kill
命令:终止、暂停或恢复进程。
选项 | 说明 | 适用场景 |
---|---|---|
-2 | 终端中断信号(等同Ctrl+C ) | 优雅终止前台进程 |
-9 | 强制终止进程(立即终止,无清理) | 进程无响应时使用 |
-15 | 默认信号,请求进程正常终止(允许清理资源) | 推荐优先使用的终止方式 |
-18 | 恢复被暂停的进程 | 配合-19使用 |
-19 | 暂停进程(不可捕获或忽略) | 临时停止进程 |
查看后台任务,前台/后台切换
job
命令:用于查看后台运行的进程。
- +表示当前作业。
- -表示上一个作业。
#创建sleep进程,持续时间10秒,使用&命令将其切换到后台运行
root@master ~]# sleep 10 &
[1] 7760
#当前任务是1号作业
[root@master ~]# jobs
[1]+ Running sleep 10 &
#执行vi &命令,将vi切换到后台运行
[root@master ~]# vi &
[2] 8004
#当前任务为2号作业
[root@master ~]# jobs
[1]- Running sleep 10 &
[2]+ Stopped vi
fg
和bg
命令:fg用于将后台作业恢复到前台运行,bg用于将暂停的作业放到后台继续运行。
[root@master ~]# sleep 10 &
[1] 7760
[root@master ~]# fg 1
[root@master ~]# sleep 50
^Z //使用ctrl+z挂起该进程
[1]+ Stooped sleep 50
[root@master ~]# jobs
[1]+ Stopped sleep 50
[root@master ~]# bg 1
-bash: bg: job 1 already in background
计划任务命令
?考试重点!
at
命令:用于指定在未来某一时间执行一个任务,只能被执行一次。
选项 | 说明 | 示例 |
---|---|---|
at [时间] | 在指定时间安排任务。时间可以是绝对时间(如14:30 、2025-05-09 10:00 )或相对时间(如now + 1 hour 、tomorrow 15:00 )。 | at 14:30 回车,输入要执行的命令,最后按Ctrl + D 提交任务。 |
-f [文件] | 从指定文件中读取要执行的命令。 | at -f /path/to/commands.txt now + 30 minutes 30分钟后执行/path/to/commands.txt 文件中的命令。 |
-l | 列出当前用户已安排的所有at 任务。 | at -l 显示当前用户已安排的任务列表,包括任务ID、执行时间和队列。 |
-c [任务ID] | 显示指定任务ID的详细内容(即要执行的命令)。 | at -c 123 显示任务ID为123的详细命令内容。 |
-r [任务ID] | 删除指定任务ID的任务。 | at -r 123 删除任务ID为123的任务。 |
-m | 任务执行完成后,向用户发送邮件通知。 | at -m 16:00 /path/to/script.sh 在16:00执行/path/to/script.sh 脚本,并在完成后发送邮件通知。 |
-q [队列] | 指定任务执行的队列(默认队列为a )。 | at -q b 18:00 /path/to/task.sh 在18:00将任务/path/to/task.sh 放入队列b 中执行。 |
crontab
命令:定时执行工具,可以使系统周期性地执行某项任务。cron的配置文件是/etc/crontab
[root@master ~]# cat /etc/crontab
#前三行是有关设置cron任务运行的环境变量
SHELL=/bin/bash #指定系统使用的shell环境
PATH=/sbin:/bin:/usr/sbin:/usr/bin #定义执行命令的路径
MAILTO=root #定义cron的输出发送给谁
# For details see man 4 crontabs
# Example of job definition: crontab文件格式
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# | | | | |
# * * * * * user-name command to be executed
命令 | 说明 | 示例 |
---|---|---|
crontab -e | 编辑当前用户的crontab 文件(默认使用vi 或nano 编辑器)。 | crontab -e |
crontab -l | 列出当前用户的所有定时任务。 | crontab -l |
crontab -r | 删除当前用户的所有定时任务(谨慎使用!)。 | crontab -r |
crontab -u [用户名] | 编辑或管理其他用户的crontab (需root权限)。 | sudo crontab -u alice -e |
常用时间表达式
表达式 | 说明 | 示例 |
---|---|---|
* | 每单位时间都执行 | * * * * * → 每分钟执行 |
*/n | 每n 单位时间执行一次 | */5 * * * * → 每5分钟执行 |
a,b,c | 在指定时间点执行 | 0,15,30 * * * * → 每小时的0分、15分、30分执行 |
a-b | 在时间范围内执行 | 0 9-17 * * * → 每天9:00到17:00的整点执行 |
@reboot | 系统启动时执行一次 | @reboot /path/to/script.sh |
2.7 帮助命令
man
命令:(manual的缩写),使用语法格式为 man [选项] 命令
- -a 在所有man的帮助手册中搜索
- -p 指定内容时使用分页程序
- -f 显示给定命令的简短描述信息
- -m 指定man手册搜索的路径
--help
命令:使用语法格式为 命令 --help
?本章习题
1.如何把两个文件合并成一个文件?
答:使用cat命令,cat file1.txt file2.txt > file.txt
,或者使用>>重定向,cat file1.txt >> file2.txt
2.如何统计当前在线人数?
答:使用who | wc -l
或者users | wc -w
3.linux的用户账号和组账号是怎么保存的?
答:用户账号保存在/etc/passwd
中, 存储用户基本信息(用户名、UID、GID、家目录、默认Shell等),密码以占位符 x
标记,实际密码加密存储在 /etc/shadow
中。
组账号保存在/etc/group
中,存储组信息(组名、GID、组用户列表)。
4.使用useradd命令添加一个用户,linux文件系统有哪些地方发生了变化?
答:/etc/passwd
文件会新增一行记录,包含新用户的用户名、密码占位符(x
)、用户ID(UID)、主组ID(GID)、用户描述、家目录路径以及默认的Shell等信息。
/etc/shadow
文件会新增一行,记录新用户的加密密码、密码过期策略等信息。
/etc/group
文件会更新相应的组信息,添加新组或更新用户所属的组。
系统会在/home
目录下创建新用户的家目录(如/home/username
),并复制默认配置文件到新用户的家目录中。
?5.什么是输入/输出重定向?请举例说明如何使用管道功能。
答:输入/输出重定向允许用户将命令的输入来源或输出目标从默认设备(如键盘、屏幕)重定向到文件或其他设备。管道(|
)用于将一个命令的输出直接作为另一个命令的输入,实现命令的链式处理。
举例--统计opt目录下有多少个文件和子目录并重定向到count.txt文件中:ls /opt | wc -w >count.txt
?6.管理员如何查看用户都启动了哪些进程?如果发现某个用户打开很多进程占用了大量系统资源,如何将他踢出系统?
答:使用 ps -u username
列出指定用户的所有进程,可以使用pkill -u username
结束其全部进程终并踢出系统。
第三章 Shell编程
3.1 Shell概述
Shell是用户与linux系统内核交互的接口。是一个命令行解释器,它负责解析用户输入的命令、调用系统程序、管理进程,并支持脚本编程以自动化任务。
shell的分类
常见shell:Bourne Shell简称(sh),C Shell简称(csh),Kron Shell简称(ksh),Bourne-Again Shell简称(bash)。
shell的功能
核心功能包括:解析并执行命令行指令(如调用程序、管理文件);
支持通配符与文件名扩展(简化批量操作);
提供输入/输出重定向和管道(灵活控制数据流);
支持脚本编程(通过条件、循环、函数等逻辑自动化任务);
管理进程与作业(启动/终止进程、后台运行、作业控制);
维护环境变量与别名(定制用户工作环境);
以及集成系统调用(通过 fork()
、exec()
等与内核交互)。
3.2 Shell变量
Shell环境变量
变量名 | 作用 | 典型值示例 | 适用场景 |
---|---|---|---|
PATH | 定义系统查找可执行程序的目录列表(用冒号分隔)。 | /usr/local/bin:/usr/bin:/bin | 确保命令(如 ls 、python )能在任意路径下直接调用。 |
HOME | 存储当前用户的主目录路径。 | /home/username | 脚本中快速引用用户目录(如 cd $HOME )。 |
USER | 当前登录的用户名。 | alice | 脚本中获取当前用户身份(如日志记录)。 |
PWD | 当前工作目录的绝对路径(由 Shell 动态维护)。 | /home/alice/projects | 脚本中获取当前所在目录(替代 pwd 命令)。 |
SHELL | 当前使用的 Shell 解释器路径。 | /bin/bash | 确认用户使用的 Shell 类型(如 Bash、Zsh)。 |
HOSTNAME | 存储当前主机名。 | my-server | 脚本中获取主机信息(如日志标记)。 |
PS1 | 定义命令行提示符的格式(对于root用户是“#”,普通用户是“$”)。 | # | # |
HISTSIZE | 保存历史命令记录的条数。 | 1000 | 调整历史记录容量(避免敏感命令长期保留)。 |
TERM | 指定终端类型(影响终端模拟器的行为,如颜色支持)。 | xterm-256color | 确保终端功能正常(如颜色高亮)。 |
环境变量一般大写,系统启动后自动加载,在脚本中,可以在环境变量名称之前加上$来使用这些环境变量。
修改和查看环境变量的命令:
命令 | 功能说明 | 示例 |
---|---|---|
env | 显示所有环境变量(键值对形式)。 | [root@master ~]# env TOMCAT_HOME=/opt/tomcat HOSTNAME=master TERM=xterm SHELL=/bin/bash |
set | 列出本地shell定义的所有变量(包括环境变量和局部变量)。 | [root@master ~]# set BASH=/bin/bash BASH_VERSION='4.2.46(2)-release' CATALINA_BASE=/opt/tomcat CATALINA_HOME=/opt/tomcat |
export | 设置一个新的环境变量。 | export MY_VAR="Hello, World!" |
unset | 移除环境变量。 | unset MY_VAR |
echo | 显示某个环境变量值。 | [root@master ~]# echo $PATH /usr/local/src/jdk-17.0.2/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin |
readonly | 设置制度环境变量。 | readonly READONLY_VAR="This is a readonly variable" |
Shell系统变量
Shell系统变量主要在对参数和命令返回值进行判断时使用,包括脚本和函数的参数,以及脚本和函数的返回值。
变量名 | 含义 | 示例 |
---|---|---|
$0 | 当前脚本或函数的名称。 | 如果脚本名为 test.sh ,则 $0 输出为 test.sh 。 |
$1 , $2 , ..., $n | 传递给脚本或函数的第 1 个、第 2 个、...、第 n 个参数。 | 执行 ./test.sh arg1 arg2 时,$1 为 arg1 ,$2 为 arg2 。 |
$# | 传递给脚本或函数的参数个数。 | 执行 ./test.sh arg1 arg2 arg3 时,$# 输出为 3 。 |
$@ | 传递给脚本或函数的所有参数(作为单独的字符串)。 | 执行 ./test.sh arg1 arg2 时,"$@" 展开为 "arg1" "arg2" 。 |
$* | 传递给脚本或函数的所有参数(作为一个字符串,参数间用 IFS 分隔)。 | 执行 ./test.sh arg1 arg2 时,"$*" 展开为 "arg1 arg2" (取决于 IFS)。 |
$? | 上一个命令的退出状态(0 表示成功,非 0 表示失败)。 | 执行 ls /nonexistent 后,$? 输出为非 0 值(因为目录不存在)。 |
$! | 用于获取最后一个后台进程的 PID | |
$$ | 当前进程的进程ID |
当命令行参数的个数大于9个时,可以使用shift指令将参数左移,获取第10个以后的参数。
shift指令将所有参数左移1位,$2的值覆盖$1....
可以使用shift n命令将所有参数一次性左移n位。
Shell用户自定义变量
由字母、数字、下划线组成,大小写字母有区分,使用等号赋值给用户变量(在变量 、等号和值之间不能出现空格)。 变量名=字符串
Shell变量的数学运算
Shell是解释型语言,变量默认都是字符串,若变量之间需要进行算术运算,必须使用expr和let命令实现。
加(+) 减(-) 乘(\*) 除(/)取模(%)
⚠️注意!!乘法运算符需要加转义字符,因为shell中将*默认为通配符使用。
expr
命令:可以对整数进行算术运算,在算术表达式中如果出现变量,必须在变量前加$,并且在运算符和变量之间要加空格。
[root@master test]# a=2
[root@master test]# expr 8 + $a
10
[root@master test]# expr 8 - $a
6
[root@master test]# expr 8 \* $a
16
[root@master test]# expr 8 / $a
4
如果要在Shell脚本中获取expr命令的计算结果,需要将expr命令用倒括号`括起来。
[root@master test]# cat test.sh
# !/bin/bash
a=5
b=`expr 10 \* $a`
echo "b=$b"
exit 0
[root@master test]# sh test.sh
b=50
let
命令:进行算术运算,将算术表达式跟在let命令的后面,运算符和变量之间不需要加空格。
[root@master test]# a=10
[root@master test]# let b=5+$a
[root@master test]# echo $b
15
3.3 Shell特殊字符
Shell通配符
shell通配符用于在命令行中匹配文件名的特殊字符,它们能够简化文件操作,尤其是在需要处理多个文件时。
通配符 | 说明 | 示例 |
---|---|---|
* | 匹配任意数量的任意字符(包括零个字符)。 | ls *.txt |
? | 匹配单个任意字符。 | ls file?.txt |
[ ] | 匹配括号内的任意一个字符。 | ls file[123].txt |
[! ] 或 [^ ] | 匹配不在括号内的任意一个字符(即排除括号内的字符)。 | ls file[!123].txt 或 ls file[^123].txt |
{ } | 生成多个可能的字符串组合(也称为“大括号扩展”)。 | echo file{1..3}.txt |
Shell元字符
Shell元字符用于控制命令的解析和执行方式。这些字符通常不能直接作为文件名或命令的一部分使用,除非通过引号或转义字符进行特殊处理。
元字符 | 说明 | 示例 | 示例说明 |
---|---|---|---|
; | 命令分隔符,用于在单行中执行多个命令。 | echo "Hello"; echo "World" | 依次执行 echo "Hello" 和 echo "World" ,分别输出 Hello 和 World 。 |
& | 后台执行符,用于将命令放入后台执行。 | sleep 10 & | 将 sleep 10 命令放入后台执行,用户可以继续在当前 Shell 中输入其他命令。 |
&& | 逻辑与操作符,仅当前一个命令成功执行(返回值为 0)时,才执行下一个命令。 | cd /tmp && ls | 如果成功切换到 /tmp 目录,则执行 ls 命令列出目录内容。 |
> | 输出重定向符,将命令的输出重定向到文件(覆盖文件原有内容)。 | echo "Hello" > output.txt | 将 echo "Hello" 的输出写入 output.txt 文件(覆盖原有内容)。 |
>> | 输出追加符,将命令的输出追加到文件末尾(不覆盖原有内容)。 | echo "World" >> output.txt | 将 echo "World" 的输出追加到 output.txt 文件的末尾。 |
< | 输入重定向符,从文件中读取输入,而不是从键盘。 | wc -l < input.txt | 统计 input.txt 文件中的行数(wc -l 从文件读取输入)。 |
\ | 转义字符,用于取消元字符的特殊含义,使其作为普通字符处理。 | echo "Path is /home/user" 中的 / 不需要转义,但若要输出 * 字符:echo "\*" | 输出 * 字符(而不是将其解释为通配符)。 |
= | 赋值操作符,用于给变量赋值。 | name="Alice" | 将字符串 "Alice" 赋值给变量 name 。 |
$ | 变量引用符,用于引用变量的值。 | echo "Hello, $name" | 输出 Hello, Alice (假设 name 变量已赋值为 "Alice" )。 |
() | 命令组,用于将多个命令组合在一起,作为一个整体执行(通常用于子 Shell)。 | (cd /tmp; ls) | 切换到 /tmp 目录并列出目录内容,这些操作在子 Shell 中执行,不影响当前 Shell 的工作目录。 |
{} | 大括号扩展,用于生成多个可能的字符串组合(常用于循环或批量操作)。 | echo file{1..3}.txt | 输出 file1.txt file2.txt file3.txt (不实际创建文件,仅用于字符串生成)。 |
` | ` | 逻辑或操作符,仅当前一个命令执行失败(返回值非 0)时,才执行下一个命令。 |
Shell转义字符
转义字符用于取消元字符的特殊含义,使其作为普通字符处理。
转义字符 | 说明 | 示例 | 示例说明 |
---|---|---|---|
\ | 反斜杠,用于屏蔽后续字符的特殊含义,使其作为普通字符处理。 | echo "The price is \$10" | 输出 The price is $10 ($ 被转义,不进行变量替换)。 |
touch "file\*.txt" | 创建名为 file*.txt 的文件(* 被转义,不进行通配符扩展)。 | ||
echo "Today is \$(date)" | 输出 Today is $(date) ($(date) 被转义,不执行命令替换)。 | ||
' | 单引号,用于界定字符串,在单引号内,所有字符(包括元字符)均失去特殊含义。 | echo 'Today is $(date) and the path is "/home/user"' | 输出 Today is $(date) and the path is "/home/user" (所有特殊字符均被转义,不进行任何替换或扩展)。 |
touch 'file?*.txt' | 创建名为 file?*.txt 的文件(? 和 * 被转义,不进行通配符扩展)。 | ||
" | 双引号,用于界定字符串,在双引号内,部分元字符(如 $ 、反引号、\)仍保留特殊含义,但其他元字符(如 * 、? 、[ 、] )失去特殊含义。 | echo "Hello, $USER! The files are *.txt" | 输出 Hello, [当前用户名]! The files are *.txt ($USER 进行变量替换,*.txt 不进行通配符扩展)。 |
mkdir "my folder" | 创建名为 my folder 的目录(空格被保留,不进行单词分割)。 |
3.4 shell控制语句
条件测试语句
当指定条件为真时,条件测试返回值为0;当指定条件为假时,条件测试返回值为非0。
条件测试语法有两种:
- test语法: test 操作符 文件
- []命令语法格式: [ 操作符 文件 ]
?文件测试
判断当前路径下的文件属性及类型。
操作符 | 说明 | 示例 | 示例说明 |
---|---|---|---|
-e | 检查文件或目录是否存在。 | [ -e "/path/to/file" ] | 如果 /path/to/file 存在,返回 true (退出状态码为 0)。 |
-f | 检查路径是否为普通文件(非目录、设备文件等)。 | [ -f "/etc/passwd" ] | 如果 /etc/passwd 是普通文件,返回 0 。 |
-d | 检查路径是否为目录。 | [ -d "/home" ] | 如果 /home 是目录,返回 0 。 |
-r | 检查文件是否可读。 | [ -r "/etc/passwd" ] | 如果当前用户对 /etc/passwd 有读权限,返回 0 。 |
-w | 检查文件是否可写。 | [ -w "/tmp/testfile" ] | 如果当前用户对 /tmp/testfile 有写权限,返回 0 。 |
-x | 检查文件是否可执行(对目录而言,检查是否可进入)。 | [ -x "/bin/ls" ] | 如果 /bin/ls 是可执行文件,返回 0 。 |
-s | 检查文件是否非空(大小大于 0 字节)。 | [ -s "/var/log/syslog" ] | 如果 /var/log/syslog 非空,返回 0 。 |
-L | 检查路径是否为符号链接。 | [ -L "/etc/alternatives" ] | 如果 /etc/alternatives 是符号链接,返回 0 。 |
[root@master test]# ls
1.txt 2.txt 3.txt aaa file1.txt file2.txt test.sh
[root@master test]# [ -e 4.txt ] #是否存在
[root@master test]# echo $? #显示最后一条命令退出状态
1 #0为成功
[root@master test]# [ -e file2.txt ]
[root@master test]# echo $?
0
[root@master test]# [ -d file2.txt ] #是否是目录
[root@master test]# echo $? #非0为失败
1
[root@master test]# [ -f file2.txt ] #是否是文件
[root@master test]# echo $?
0
[root@master test]# [ -s file2.txt ] #是否为空
[root@master test]# echo $?
0
[root@master test]# [ -r file2.txt ] #是否可读
[root@master test]# echo $?
0
[root@master test]# [ -w file2.txt ] #是否可写
[root@master test]# echo $?
0
[root@master test]# [ -x file2.txt ] #是否可执行
[root@master test]# echo $?
1
?字符串测试
字符串测试操作符用于比较字符串的值或检查字符串是否为空。
操作符 | 说明 | 示例 | 示例说明 |
---|---|---|---|
= 或 == | 检查两个字符串是否相等(= 和 == 功能相同)。 | [ "$str1" = "$str2" ] | 如果 $str1 和 $str2 的值相等,返回 true (退出状态码为 0)。 |
!= | 检查两个字符串是否不相等。 | [ "$str1" != "$str2" ] | 如果 $str1 和 $str2 的值不相等,返回 0 。 |
-z | 检查字符串是否为空(长度为 0)。 | [ -z "$str" ] | 如果 $str 为空字符串,返回 0 。 |
-n | 检查字符串是否非空(长度大于 0)。 | [ -n "$str" ] | 如果 $str 为非空字符串,返回 0 。 |
< | 按字典序比较两个字符串,检查第一个字符串是否小于第二个字符串(需在 [[ ]] 中使用)。 | [[ "$str1" < "$str2" ]] | 如果 $str1 按字典序小于 $str2 ,返回 0 。 |
> | 按字典序比较两个字符串,检查第一个字符串是否大于第二个字符串(需在 [[ ]] 中使用)。 | [[ "$str1" > "$str2" ]] | 如果 $str1 按字典序大于 $str2 ,返回 0 。 |
[root@master test]# a="aaa"
[root@master test]# b="bbb"
[root@master test]# c=""
[root@master test]# [ "$a" = "$b" ] #判断是否相等
[root@master test]# echo $?
1 #非0为不匹配
[root@master test]# [ "$a" != "$b" ] #判断是否不相等
[root@master test]# echo $?
0
[root@master test]# [ -z "$a" ] #判断是否为空字符串
[root@master test]# echo $?
1
[root@master test]# [ -z "$c" ]
[root@master test]# echo $?
0
[root@master test]# [ -n "$a" ] #判断是否为非空字符串
[root@master test]# echo $?
0
[root@master test]# [ -n "$c" ]
[root@master test]# echo $?
1
[root@master test]# [[ "$a" < "$b" ]] #判断字符串a是否小于字符串b
[root@master test]# echo $?
0
[root@master test]# [[ "$a" > "$b" ]] #判断字符串a是否大于字符串b
[root@master test]# echo $?
1
?数值测试
数值测试操作符用于比较两个整数的值(如是否相等、大于、小于等)。
操作符 | 说明 | 示例 | 示例说明 |
---|---|---|---|
-eq | 检查两个整数是否相等(equal)。 | [ "$a" -eq "$b" ] | 如果 $a 等于 $b ,返回 true (退出状态码为 0)。 |
-ne | 检查两个整数是否不相等(not equal)。 | [ "$a" -ne "$b" ] | 如果 $a 不等于 $b ,返回 0 。 |
-gt | 检查第一个整数是否大于第二个整数(greater than)。 | [ "$a" -gt "$b" ] | 如果 $a 大于 $b ,返回 0 。 |
-lt | 检查第一个整数是否小于第二个整数(less than)。 | [ "$a" -lt "$b" ] | 如果 $a 小于 $b ,返回 0 。 |
-ge | 检查第一个整数是否大于或等于第二个整数(greater than or equal)。 | [ "$a" -ge "$b" ] | 如果 $a 大于或等于 $b ,返回 0 。 |
-le | 检查第一个整数是否小于或等于第二个整数(less than or equal)。 | [ "$a" -le "$b" ] | 如果 $a 小于或等于 $b ,返回 0 。 |
?逻辑操作符
逻辑操作符用于组合多个条件表达式,以实现更复杂的逻辑判断。
操作符 | 说明 | 示例 | 示例说明 |
---|---|---|---|
&& | 逻辑与(AND),当前面的命令或条件为 true 时,才执行后面的命令或判断后面的条件。 | [ "$a" -eq 10 ] && [ "$b" -gt 5 ] | 如果 $a 等于 10 且 $b 大于 5,则整个表达式返回 true 。 |
-o | 逻辑或(OR),当前面的命令或条件为 false 时,才执行后面的命令或判断后面的条件。 | [ "$a" -ne 10 ] && [ "$b" -gt 5 ] | 如果 $a 不等于 10 或 $b 大于 5,则整个表达式返回 true 。 |
! | 逻辑非(NOT),对条件取反。 | ! [ "$a" -eq 10 ] | 如果 $a 不等于 10,则整个表达式返回 true 。 |
() | 圆括号,将表达式分组,优先得到结果。括号前后有空格,并使用转义字符 \( 和 \) | [ \( 5 -gt 0 -a 5 -lt 10 \) ] | 如果5大于0小于10,则整个表达式返回true 。 |
⚠️圆括号 ()
在 Shell 中通常用于创建子 Shell 或命令分组。
[root@master test]# [ \( 5 -gt 0 -a 5 -lt 10 \) ]
[root@master test]# echo $?
0
if条件语句
?简单if语句
if开始,fi结束。if-else结构
[root@master test]# cat test.sh
# !/bin/bash
str1="hello"
str2="world"
if [ "$str1" = "$str2" ]; then
echo "字符串相等"
else
echo "字符串不相等"
fi
exit 0
[root@master test]# sh test.sh
字符串不相等
?多路if elif语句
[root@master test]# cat test.sh
# !/bin/bash
str1="hello"
str2="world"
if [ "$str1" = "$str2" ]; then
echo "字符串相等"
elif [ "$str1" != "$str2" ]; then
echo "字符串不相等"
fi
exit 0
[root@master test]# sh test.sh
字符串不相等
select语句
用户可以从一组不同的值中进行选择。
主要特征:没有echo指令,自动用1、2、3、4等数字列出菜单;没有read指令,自动输入;没有赋值指令,自动输入数字后赋值字符串给变量。
[root@master test]# cat test.sh
#!/bin/bash
options=("选项1" "选项2" "退出")
PS3="请选择: " #设置select 菜单的提示符(默认为 #?)
select opt in "${options[@]}";
do #do用于循环结构
echo "你选择了选项:$opt"
break
done
exit 0
[root@master test]# sh test.sh
1) 选项1
2) 选项2
3) 退出
请选择: 1
你选择了选项:选项1
case语句
基本格式:
case value in
pattern1)
语句1;;
pattern2)
语句2 ;;
esac
value是一个变量,pattern是正则表达式,case语句会将value与pattern的每个值都进行匹配,当匹配成功时,执行其后的语句,当遇到;;时,跳出case语句。
⚠️注意:变量取值的后面关键字为in;每一个分支必须以右括号结束;每一个case子句必须以两个分号结束;以关键字case开头,以esac结尾;匹配模式可以使用[]来表示一个连续的范围,例如[0-9];匹配模式由多个模式组成时,用|分开,各模式的关系为或。
?case
语句中的范围匹配在Shell中是按字符串比较的,而不是按数字比较的。故而可以有[0-9],但是不要写[10-100],这样会无法匹配。
#!/bin/bash
options=("选项1" "选项2" "退出")
PS3="请选择: "
select opt in "${options[@]}";
do #do一般用于循环结构
case $opt in
"选项1")
echo "你选择了选项1"
;;
"选项2")
echo "你选择了选项2"
;;
"退出")
break
;;
*)
echo "无效输入"
;;
esac
done
例:用户从键盘输入一个字符,并判断该字符是否为字母、数字或者其他字符,输出相关提示信息。
[root@master test]# cat test.sh
#!/bin/bash
read -p "请输入一个字符:" key
case $key in
[a-z] | [A-Z])
echo "这是一个字母。";;
[0-9])
echo "这是一个数字。";;
*)
echo "这是其他特殊字符。";;
esac
[root@master test]# sh test.sh
请输入一个字符:1
这是一个数字。
[root@master test]# sh test.sh
请输入一个字符:q
这是一个字母。
[root@master test]# sh test.sh
请输入一个字符:~
这是其他特殊字符。
for语句
?列表for循环语句
[root@master test]# cat test.sh
#!/bin/bash
options=("选项1" "选项2" "退出")
for opt in "${options[@]}" #注意这里的写法
do
echo $opt
done
[root@master test]# sh test.sh
选项1
选项2
退出
指定列表的长度和步长。{start..end..step}
?例:计算100以内奇数的和。
[root@master test]# cat test.sh
#!/bin/bash
sum=0
for number in {1..100..2}
do
sum=$((sum + number)) #$(( )) 算术运算的语法结构,可以在脚本中直接进行整数运算,不支持浮点数
done
echo "100以内的奇数和为:$sum"
[root@master test]# sh test.sh
100以内的奇数和为:2500
?不带列表的for循环语句
不带列表的for循环一般都是通过命令行来传递参数。
for var
语句相当于for var in $*
[root@master test]# cat test.sh
#!/bin/bash
for number
do
echo $number
done
[root@master test]# sh test.sh 1 2 3
1
2
3
?类似于C语言的for循环语句
例:求1-100的和。
[root@master test]# cat test.sh
#!/bin/bash
sum=0;
for((i=0;i<=100;i++))
do
sum=$((sum+i))
done
echo "1-100的和是$sum"
[root@master test]# sh test.sh
1-100的和是5050
while语句
?利用计数器控制的while循环
例:计算100以内的奇数和。
[root@master test]# cat test.sh
#!/bin/bash
sum=0
i=1
while((i<=100))
do
sum=$((sum+i))
i=$((i+2))
done
echo "100以内的奇数和为$sum"
[root@master test]# sh test.sh
100以内的奇数和为2500
?通过结束标志控制的while循环
设置一个特殊的数据值来结束while循环。
例:猜字谜游戏
#!/bin/bash
n=4
read -p "请输入你猜测的数字(0-9):" number
case $number in
[0-9])
;;
*)
echo "请输入(0-9)之间的数字!!!"
read number
;;
esac
while [ "$number" -ne "$n" ]
do
if [ "$number" -lt "$n" ]; then
echo "猜小了,请重新猜测。"
read number
elif [ "$number" -gt "$n" ]; then
echo "猜大了,请重新猜测。"
read number
fi
done
echo "恭喜你,猜对了!"
break和continue语句
break
语句用于跳出整个循环体,continue
语句用于跳出当前循环。
例:选择数字0-5,并且输出对应的结果。
[root@localhost test]# cat test.sh
#!/bin/bash
while true
do
read -p "input a number(0-5):" number
case $number in
[0-5]) echo "your number is $number.";;
*) echo "please input a number."
break
;;
esac
done
[root@localhost test]# sh test.sh
input a number(0-5):1
your number is 1.
input a number(0-5):2
your number is 2.
input a number(0-5):7
please input a number.
例:输入一组数,打印除了值为4以外的所有数。
[root@localhost test]# cat test.sh
#!/bin/bash
for i in {0..5}
do
if [ "$i" -eq 4 ];then
continue
else echo "$i"
fi
done
[root@localhost test]# sh test.sh
0
1
2
3
5
?本章习题
1.shell脚本的执行方式有哪些?
答:
2.shell的系统变量、环境变量和用户自定义变量的区别是什么?
答:
3.shell编程,判断一个文件是不是块或字符设备文件,如果是则将其复制到/dev目录下。
答:
[root@localhost test]# cat test1.sh
#!/bin/bash
#$#表示传递给脚本的参数的个数
if [ $# -ne 1 ]; then
echo "用法: $0 <文件名>"
exit 0
fi
file=$1
# 检查文件是否存在
if [ ! -e "$file" ]; then
echo "错误: 文件 '$file' 不存在"
exit 0
fi
# 判断文件类型
if [ -b "$file" ]; then
echo "检测到块设备文件: $file"
elif [ -c "$file" ]; then
echo "检测到字符设备文件: $file"
else
echo "错误: '$file' 不是块设备或字符设备文件"
exit 0
fi
# 确认操作
read -p "确认要将此$type文件复制到/dev目录吗?(y/n) " confirm
if [ "$confirm" != "y" ] && [ "$confirm" != "Y" ]; then
echo "操作已取消"
exit 0
fi
# 执行复制操作
#&&:这是一个逻辑与运算符,表示只有当前面的命令cp执行成功(即返回值为0)时,才会执行后面的命令。
#||:这是一个逻辑或运算符,表示只有当前面的命令cp执行失败(即返回值非0)时,才会执行后面的命令。
cp -v "$file" /dev/ && echo "复制成功" || echo "复制失败"
[root@localhost test]# sh test1.sh test.sh
错误: 'test.sh' 不是块设备或字符设备文件
4.shell编程,通过条件测试判断当前用户是否拥有某个文件的读权限。
答:
[root@localhost test]# cat test2.sh
#!/bin/bash
# 检查参数数量
if [ $# -ne 1 ]; then
echo "用法: $0 <文件名>"
exit 0
fi
file=$1
# 检查文件是否存在
if [ ! -e "$file" ]; then
echo "错误: 文件 '$file' 不存在"
exit 0
fi
# 检查文件是否可读
if [ -r "$file" ]; then
echo "当前用户对文件 '$file' 有读权限"
else
echo "当前用户对文件 '$file' 没有读权限"
fi
[root@localhost test]# sh test2.sh
用法: test2.sh <文件名>
[root@localhost test]# sh test2.sh 1.sh
错误: 文件 '1.sh' 不存在
[root@localhost test]# sh test2.sh test1.sh
当前用户对文件 'test1.sh' 有读权限
5.shell编程,利用两层循环打印出乘法口诀表。
答:
[root@localhost test]# cat test4.sh
#!/bin/bash
for((i=1;i<=9;i++))
do
for((j=1;j<=i;j++))
do
product=$((i * j))
printf "%d*%d=%-2d " $j $i $product
done
echo
done
[root@localhost test]# sh test4.sh
1*1=1
1*2=2 2*2=4
1*3=3 2*3=6 3*3=9
1*4=4 2*4=8 3*4=12 4*4=16
1*5=5 2*5=10 3*5=15 4*5=20 5*5=25
1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36
1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49
1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64
1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81
6.shell编程,接收用户输入数字,如果输入的是非数字,提示“输入非数字,请重新输入!”并结束;如果是纯数字,则返回数字结果。
答:
#!/bin/bash
read -p "请输入一个数字: " number
# 使用正则表达式检查输入是否为数字
#[[ $input =~ ^[0-9]+$ ]]: 使用正则表达式检查input是否只包含数字。
#^ 表示字符串的开始。
#[0-9] 表示一个数字字符。
#+ 表示前面的字符(即数字)出现一次或多次。
#$ 表示字符串的结束。
if [[ $number =~ ^[0-9]+$ ]]; then
echo "输入的数字是: $m=number"
else
echo "输入非数字,请重新输入!"
fi
7.shell编程,接收用户输入的数字,判断该数字是否是闰年。
答:要判断一个年份是否是闰年,可以使用以下规则:
如果年份能被4整除但不能被100整除,则是闰年。
如果年份能被400整除,则是闰年。
[root@localhost test]# cat test5.sh
#!/bin/bash
read -p "请输入年份:" year
if [[ ! $year =~ ^[0-9]+$ ]]; then
echo "输入非数字,请重新输入!"
exit 0
fi
if (( year % 4 == 0 && year %100 != 0)) || (( year % 400 == 0)); then
echo "$year是闰年"
else
echo "$year不是闰年"
fi
[root@localhost test]# sh test5.sh
请输入年份:2020
2020是闰年
[root@localhost test]# sh test5.sh
请输入年份:2021
2021不是闰年
8.shell编程,接收用户输入的数字,判断该数字是否为质数。
答:要判断一个数字是否为质数,需要检查该数字是否只能被1和它本身整除。
[root@localhost test]# cat test6.sh
#!/bin/bash
read -p "请输入数字:" number
if [[ ! $number =~ ^[0-9]+$ ]];then
echo "请输入数字!!!"
read number
fi
if (( number < 2 )); then
echo "$number不是质数"
exit 0
fi
# 判断是否为质数
is_prime=1
for (( i=2; i*i<=number; i++ )); do
if (( number % i == 0 )); then
is_prime=0
break
fi
done
# 输出结果
if (( is_prime == 1 )); then
echo "$number是质数"
else
echo "$number不是质数"
fi
[root@localhost test]# sh test6.sh
请输入数字:~
请输入数字!!!
1
1不是质数
[root@localhost test]# sh test6.sh
请输入数字:2
2是质数
[root@localhost test]# sh test6.sh
请输入数字:4
4不是质数
[root@localhost test]# sh test6.sh
请输入数字:9
9不是质数
9.shell编程,循环接收用户输入的学生成绩(百分制),若成绩小于60,则输入“不及格”;若成绩大于等于60,输出“及格”,按Q或q键退出。
答:
[root@localhost test]# cat test7.sh
#!/bin/bash
while true
do
read -p "请输入成绩(0-100)或者按(Q/q键退出):" score
if [[ "$score" == "Q" || "$score" == "q" ]]; then
echo "退出程序。"
break
fi
if [[ ! $score =~ ^[0-9]+$ ]]; then
echo "请输入数字."
continue
fi
# 判断成绩是否在0-100范围内
if (( score < 0 || score > 100 )); then
echo "成绩必须在0到100之间,请重新输入。"
continue
fi
if (( score >= 60 )); then
echo "及格"
else
echo "不及格"
fi
done
[root@localhost test]# sh test7.sh
请输入成绩(0-100)或者按(Q/q键退出):-1
请输入数字.
请输入成绩(0-100)或者按(Q/q键退出):100
及格
请输入成绩(0-100)或者按(Q/q键退出):100000
成绩必须在0到100之间,请重新输入。
请输入成绩(0-100)或者按(Q/q键退出):20
不及格
请输入成绩(0-100)或者按(Q/q键退出):60
及格
10.shell编程,循环接收某门课程的成绩,计算用户已输入成绩的最高分、最低分、平均分,按P或p键输出计算结果,按Q或q键退出。
答:
root@localhost test]# cat test8.sh
#!/bin/bash
total=0
count=0
max=0
min=100
echo "请输入某门课程的成绩,输入 P 或 p 键输出计算结果,输入 Q 或 q 键退出:"
while true; do
read -p "请输入成绩(0-100):" input
# 检查用户是否想输出结果
if [[ "$input" == "P" || "$input" == "p" ]]; then
if (( count == 0 )); then
echo "暂无成绩输入。"
else
average=$((total / count))
echo "最高分: $max"
echo "最低分: $min"
echo "平均分: $average"
fi
continue
fi
# 检查用户是否想退出
if [[ "$input" == "Q" || "$input" == "q" ]]; then
echo "退出程序。"
break
fi
# 检查输入是否为数字
if [[ ! $input =~ ^[0-9]+$ ]]; then
echo "输入无效,请输入一个数字或 P/p/Q/q。"
continue
fi
# 判断成绩是否在0-100范围内
if (( input < 0 || input > 100 )); then
echo "成绩必须在0到100之间,请重新输入。"
continue
fi
# 更新成绩统计
(( total += input ))
(( count += 1 ))
# 更新最高分和最低分
if (( count == 1 )); then
max=$input
min=$input
else
if (( input > max )); then
max=$input
fi
if (( input < min )); then
min=$input
fi
fi
done
[root@localhost test]# sh test8.sh
请输入某门课程的成绩,输入 P 或 p 键输出计算结果,输入 Q 或 q 键退出:
请输入成绩(0-100):-1
输入无效,请输入一个数字或 P/p/Q/q。
请输入成绩(0-100):1000
成绩必须在0到100之间,请重新输入。
请输入成绩(0-100):100
请输入成绩(0-100):100
请输入成绩(0-100):100
请输入成绩(0-100):p
最高分: 100
最低分: 100
平均分: 100
请输入成绩(0-100):q
退出程序。
第四章 linux常用开发工具
4.1 linux编程环境及工具
linux操作系统上的程序设计要经过编辑源程序、源程序预处理、编译生成目标文件、连接生成可执行程序这几个步骤。
4.2 vi编辑器
vi编辑器是linux系统最常见的文本编辑器,vi编辑器有三种工作模式:命令模式、输入模式、底行命令模式。
?命令模式
在任何状态下按Esc键都可以回到命令模式,在命令模式下用户通过输入命令的方式,可以完成字符串检索、文本恢复、修改、替换、行结合、光标定位等功能。
- a 输入模式,在光标后输入文本。
- A 输入模式,光标移动到所在行尾。
- i 输入模式,在光标之前输入文本。
- I 输入模式,光标移动到所在行首。
- dd 删除光标所在行。
- 数字+dd 删除光标所在行开始的后面几行,行数由数字决定。
- /字符串 向下检索字符串。
- ?字符串 向上检索字符串。
- yy 复制光标所在行。
- 数字+yy 复制光标所在行开始的后面几行,行数由数字决定。
?底行命令模式
进入底行命令模式的方法是在命令模式下输入:紧接着输入底行命令并按Enter键,执行所输入的命令。
- :w 保存编辑后的内容。
- :q 退出vi编辑器。
- :wq 保存并退出。
- :q! 强制退出,不保存。
- :数字 光标移到到数字指定的行。
4.3 GCC编辑器
可以编译用C、C++等语言编写的程序。通过GCC编译器可以完成预处理、编译、优化、链接、生成可执行的二进制代码。
- -c 只生成目标文件.o文件,不链接。
- -E 只进行预处理,不编译。
- -g 在编译的时候,产生调试信息。
- -o 指定输出的可执行文件名称。
- -S 生成汇编文件.s文件。
4.4 GDB调试工具(略)
第五章 文件系统与操作
5.1 磁盘的结构
?磁盘的物理结构
磁盘主要是由磁盘盘片、传动手臂、磁头与主轴电动机以及传动轴所组成。一个磁盘可以有一个或多个盘片,每个盘片上下都会有一个磁头用来读写数据。
还有诸多概念:磁道、柱面、扇区、磁头....
?linux文件系统目录
?重点!!
linux操作系统目录为树形结构,文件系统只有一个根目录(通常用/表示)目录结构如下:
[root@localhost ~]# cd /
[root@localhost /]# ls
bin boot dev etc home lib mnt opt proc root sbin srv sys tmp usr var
目录 | 说明 |
---|---|
根目录:/ | 根目录位于linux系统目录结构的顶层,根目录下一般只存放目录,不存放文件。 |
/bin | 命令文件目录,包含了系统管理员及普通用户使用的重要命令和二进制可执行文件。 |
/boot | 存放系统的内核文件以及引导装载程序文件。 |
/dev | 设备文件目录,存放linux系统下的设备文件,访问该目录下的某个文件,相当于访问某个设备。 |
/etc | 系统配置文件目录,存放系统大部分的配置文件和子目录。包括inittab、init.d、sysconfig |
/home | 系统默认的用户宿主目录。 |
/lib | 系统使用的函数库目录,存放了各种编程语言库。 |
/mnt | 用来临时挂载文件系统。 |
/opt | 给主机额外安装软件所摆放的目录。 |
/proc | 虚拟文件系统,它提供了关于系统内核和运行中进程的信息。 |
/root | 系统管理员root的宿主目录。 |
/sbin | 放置系统管理员使用的可执行命令。 |
/srv | 服务启动之后需要访问的数据目录。 |
/tmp | 存放临时文件目录。 |
/usr | 应用程序存放目录。 |
/var | 放置系统执行过程中经常变化的文件。 |
?inode索引节点 略
5.2 linux文件系统
?常用文件系统
ext2文件系统、ext3文件系统、Swap文件系统、VFAT、NFS、XFS、ISO 9660、proc、虚拟文件系统。
?对文件系统的操作
fdisk磁盘分区、mkfs格式化命令、mount挂载命令。
5.3 linux文件类型和权限
?文件类型
普通文件:类似-rwxrwxrwx的文件,第一个符号为-的文件介绍普通文件。包括文本文件、二进制文件、数据文件。
目录文件:类似drwxr-xr-x的文件,第一个字符是d,可以利用其构成我呢见系统的分层树形结构。
设备文件:分为块设备、字符设备。块设备可以随机读写,最常见的是磁盘,字符设备允许IO传送任意大小的数据,最常见的是打印机和终端。
?链接文件:类似lrwxrwxrwx的文件,第一个字符是l,被链接的文件可以存放在相同或者不同的目录上。文件的链接就是给文件起一个或多个名字,有硬链接和软链接两种形式。
- 硬链接:硬链接是指向文件数据(inode)的另一个文件名。它是一个指向文件系统中实际数据的指针,而不是指向文件名的指针。
ln 文件 链接名
- 软链接:又叫符号链接。软链接是一个特殊的文件,它包含了对另一个文件或目录的路径引用。类似于 Windows 中的快捷方式。
ln -s 文件 链接名
- 区别1:硬链接和原始文件共享同一个 inode,删除原始文件后,只要硬链接仍然存在,文件数据就不会被删除。软连接有自己的 inode,它存储的是目标文件或目录的路径。删除原始文件后,软连接会变成“悬空链接”,指向一个不存在的路径。
- 区别2:硬链接不能跨越不同的文件系统,软连接可以跨越不同的文件系统。
- 区别3:硬链接不能链接目录,软链接可以链接目录。
?文件的权限
?考试重点!!!
linux有三种类型的用户:文件所有者、同组用户、其他用户。
每一文件或目录的访问权限都有三组,每组用3位表示:①文件属主的读、写、执行权限。②和属主同组的用户的读、写、执行权限。③系统中其他用户的读、写、执行权限。
[root@localhost test]# ls -l
总用量 36
#访问权限 链接数 属主 属组 文件长度 建立时间 文件名
-rw-r--r--. 1 root root 1048 5月 9 10:56 test1.sh
-rw-r--r--. 1 root root 396 5月 9 11:01 test2.sh
-rw-r--r--. 1 root root 343 5月 9 11:09 test3.sh
-rw-r--r--. 1 root root 144 5月 9 11:25 test4.sh
修改文件的访问权限命令:chmod
命令
chmod [who] [+|-|=] [mode] 文件名
操作对象who可以是下述字母的任一个或他们的组合。
- u 表示用户(user),即文件或目录的所有者。
- g 表示同组用户(group),即和文件属主有相同组ID的用户。
- o 表示其他用户(others)。
- a 表示所有用户(all)。
+
表示添加某个权限。-
表示取消某个权限。=
表示赋予给定权限并取消其他所有权限。
设置mode所表示的权限可以用下述字母的任意组合。
- r 可读。4
- w 可写。2
- x 可执行。1
[root@localhost test]# chmod u+x test1.sh
[root@localhost test]# ls -l
总用量 36
-rwxr--r--. 1 root root 1048 5月 9 10:56 test1.sh
-rw-r--r--. 1 root root 396 5月 9 11:01 test2.sh
-rw-r--r--. 1 root root 343 5月 9 11:09 test3.sh
[root@localhost test]# chmod 744 test2.sh
[root@localhost test]# ls -l
总用量 36
-rwxr--r--. 1 root root 1048 5月 9 10:56 test1.sh
-rwxr--r--. 1 root root 396 5月 9 11:01 test2.sh
-rw-r--r--. 1 root root 343 5月 9 11:09 test3.sh
5.4 文件操作
文件操作相关函数
open函数
pathname
是文件路径,flags
是打开模式(如O_RDONLY
、O_WRONLY
、O_RDWR
等),mode
是文件权限(用于创建文件时)。
#include <fcntl.h>
int open(const char *pathname, int flags, mode_t mode);
close函数
fd是文件描述符。
#include <unistd.h>
int close(int fd);
read函数
fd
是文件描述符,buf
是存储读取数据的缓冲区,count
是要读取的字节数。
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
write函数
fd
是文件描述符,buf
是包含要写入数据的缓冲区,count
是要写入的字节数。
ssize_t write(int fd, const void *buf, size_t count);
chmod函数
pathname
是文件路径,mode
是新的权限模式。
#include <sys/types.h>
#include <sys/stat.h>
int chmod(const char *pathname, mode_t mode);
chown函数
pathname
是文件路径,owner
是新的所有者ID,group
是新的组ID。
int chown(const char *pathname, uid_t owner, gid_t group);
lseek函数
移动文件指针函数,fd
是文件描述符,offset
是偏移量,whence
是基准点(如SEEK_SET
、SEEK_CUR
、SEEK_END
)。
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
creat函数
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
int creat(const char *pathname, mode_t mode);
remove函数
删除文件
#include <stdio.h>
int remove(const char *pathname);
?本章习题
1.请列出Linux操作系统的主要目录,并说明该目录的功能是什么。(注:请至少列出10个要目录)
答:
目录 | 说明 |
---|---|
根目录:/ | 根目录位于linux系统目录结构的顶层,根目录下一般只存放目录,不存放文件。 |
/bin | 命令文件目录,包含了系统管理员及普通用户使用的重要命令和二进制可执行文件。 |
/boot | 存放系统的内核文件以及引导装载程序文件。 |
/dev | 设备文件目录,存放linux系统下的设备文件,访问该目录下的某个文件,相当于访问某个设备。 |
/etc | 系统配置文件目录,存放系统大部分的配置文件和子目录。包括inittab、init.d、sysconfig |
/home | 系统默认的用户宿主目录。 |
/lib | 系统使用的函数库目录,存放了各种编程语言库。 |
/mnt | 用来临时挂载文件系统。 |
/opt | 给主机额外安装软件所摆放的目录。 |
/proc | 虚拟文件系统,它提供了关于系统内核和运行中进程的信息。 |
/root | 系统管理员root的宿主目录。 |
/sbin | 放置系统管理员使用的可执行命令。 |
/srv | 服务启动之后需要访问的数据目录。 |
/tmp | 存放临时文件目录。 |
/usr | 应用程序存放目录。 |
/var | 放置系统执行过程中经常变化的文件。 |
2.什么是符号链接?什么是硬链接?区别是什么?
答:
硬链接:硬链接是指向文件数据(inode)的另一个文件名。它是一个指向文件系统中实际数据的指针,而不是指向文件名的指针。ln 文件 链接名
软链接:又叫符号链接。软链接是一个特殊的文件,它包含了对另一个文件或目录的路径引用。类似于 Windows 中的快捷方式。 ln -s 文件 链接名
区别1:硬链接和原始文件共享同一个 inode,删除原始文件后,只要硬链接仍然存在,文件数据就不会被删除。软连接有自己的 inode,它存储的是目标文件或目录的路径。删除原始文件后,软连接会变成“悬空链接”,指向一个不存在的路径。
区别2:硬链接不能跨越不同的文件系统,软连接可以跨越不同的文件系统。
区别3:硬链接不能链接目录,软链接可以链接目录。
3.用C语言编程,打开/etc/passwd文件,显示当前系统中已经注册的普通用户账号。
答:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LINE_LENGTH 1024
int main() {
FILE *file;
char line[MAX_LINE_LENGTH];
// 打开 /etc/passwd 文件
file = fopen("/etc/passwd", "r");
if (file == NULL) {
perror("无法打开 /etc/passwd 文件");
return EXIT_FAILURE;
}
// 逐行读取文件内容
while (fgets(line, sizeof(line), file) != NULL) {
// 解析每一行
char *username, *password, *uid, *gid, *comment, *home_dir, *shell;
username = strtok(line, ":");
password = strtok(NULL, ":");
uid = strtok(NULL, ":");
gid = strtok(NULL, ":");
comment = strtok(NULL, ":");
home_dir = strtok(NULL, ":");
shell = strtok(NULL, "\n");
// 检查 UID 是否大于或等于 1000(普通用户)
int user_id = atoi(uid);
if (user_id >= 1000) {
printf("用户名: %s\n", username);
}
}
// 关闭文件
fclose(file);
return EXIT_SUCCESS;
}
4.用C语言编程,打开用户指定的文件,将文件内容倒序后再写入该文件。
答:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void reverse_string(char *str, int length) {
int start = 0;
int end = length - 1;
while (start < end) {
char temp = str[start];
str[start] = str[end];
str[end] = temp;
start++;
end--;
}
}
int main(int argc, char *argv[]) {
if (argc != 2) {
printf("用法: %s <文件名>\n", argv[0]);
return EXIT_FAILURE;
}
FILE *file = fopen(argv[1], "r+");
if (file == NULL) {
perror("无法打开文件");
return EXIT_FAILURE;
}
// 获取文件大小
fseek(file, 0, SEEK_END);
long file_size = ftell(file);
rewind(file);
// 分配缓冲区
char *buffer = (char *)malloc(file_size + 1);
if (buffer == NULL) {
perror("内存分配失败");
fclose(file);
return EXIT_FAILURE;
}
// 读取文件内容
if (fread(buffer, 1, file_size, file) != file_size) {
perror("读取文件失败");
free(buffer);
fclose(file);
return EXIT_FAILURE;
}
// 关闭文件,以便重新打开进行写入
fclose(file);
// 倒序内容
reverse_string(buffer, file_size);
// 重新打开文件进行写入
file = fopen(argv[1], "w");
if (file == NULL) {
perror("无法打开文件进行写入");
free(buffer);
return EXIT_FAILURE;
}
// 写入倒序后的内容
if (fwrite(buffer, 1, file_size, file) != file_size) {
perror("写入文件失败");
free(buffer);
fclose(file);
return EXIT_FAILURE;
}
// 关闭文件并释放内存
free(buffer);
fclose(file);
printf("文件内容已成功倒序并写入。\n");
return EXIT_SUCCESS;
}