基础
文件系统
-
vim 中有高亮提示,vi 没有高亮
一般模式
# 复制 yy # 复制行(默认复制一行内容) 8yy # 复制8行 y$ # 复制当前光标到该行后续所有部分 y^ # 复制当前光标导改行前面所有部分 yw # 复制当前单词 # 粘贴 p # 粘贴复制的内容(默认粘贴一行) 5p # 将复制的内容粘贴5次 # 删除 dd # 删除行(默认一行) 3dd # 删除3行 d$ # 删除光标所在行后续所有部分 d^ # 删除光标所在行前面所有部分 dw # 删除当前单词 # 剪切 x # 从左向右剪切一个字母 X # 从右向左剪切一个字母 # 替换光标所在字符 r+替换后的字符 # 替换一个字符 R+替换后的字符 # 替换多个字符(esc退出) # 撤回 u # 撤回操作 # 光标移动 ^ # 移动到行头 $ # 移动到行尾 w # 跳到下一个单词头 e # 跳到下一个单词尾 b # 跳到上一个词的词头 1G # 移动到页头 数字G # 移动到目标行 G # 移动到页尾 gg # 移动到页头 数字gg # 移动到目标行 H # 移动到页头 L # 移动到页尾 # 设置行号 :set nu # 关闭行号 :set nonu
编辑模式
-
进入编辑模式按键
按键 | 功能 |
---|---|
i | 当前光标前 |
a | 当前光标后 |
o | 当前光标行的下一行 |
I | 光标所在行最前 |
A | 光标所在行最后 |
O | 当前光标行的上一行 |
命令模式
命令 | 功能 |
---|---|
/要查找的词 | n查找下一个,N查找上一个 |
:noh | 取消高亮显示 |
:set nu | 显示行号 |
:set nonu | 关闭行号 |
:s/old/new | 替换当前行匹配到的第一个old为new |
:s/old/new/g | 替换当前行所有匹配到的old为new |
:%s/old/new | 替换文档中每一行匹配到的第一个old为new |
:%s/old/new/g | 替换文档中所有old为new |
网络配置
centos:
-
查看IP
ip address
-
修改网络配置
vim /etc/sysconfig/network-scripts/ifcfg-eth0
-
将DHCP模式修改为static
-
加入修改后的ip、网关、域名解析器
-
IPADDR=10.0.0.24 GATEWAY=10.0.0.1 DNS1=10.0.0.1
-
-
重启网络服务
service network restart
-
-
查看+修改主机名
-
# 查看 hostname hostnamectl # 修改方式1 vim /etc/hostname reboot # 修改方式2 hostnamectl set-hostname 主机名 # 修改 host 文件(IP 主机名 映射表) vim /etc/hosts ip 主机名
-
远程登录
-
软件 xftp、Xshell
-
连接命令
ssh 用户名@ip
系统管理
systemctl
语法:
systemctl start|stop|restart|status 服务名
查看服务:
cd /usr/lib/systemd/system ls -al
打开关闭防火墙
systemctl status firewalld systemctl start firewalld systemctl stop firewalld
系统后台自启动
026_基础篇_系统管理(三)_配置服务开机启动和关闭防火墙_哔哩哔哩_bilibili
系统运行级别
025_基础篇_系统管理(二)_系统运行级别_哔哩哔哩_bilibili
关机重启
sync 将数据由内存同步到硬盘中 halt 停机,关闭系统,但不断电 poweroff 关机,断电 reboot 重启 shutdown -r now 立刻重启 shutdown -H 关机 -r 一分钟后重启 shutdown 默认一分钟后关机 shutdown -c 取消关机操作
实操
帮助命令
解释命令操作的含义:man 操作命令
解释内部命令的含义:help 操作命令
解释命令操作:命令 --help
快捷键
停止进程 ctrl+c
清屏 ctrl+l
相当于 clear
彻底清屏 reset
文件目录类
pwd
所在目录
cd -
回到上一次所在目录
cd
回到主目录
ls -a
显示全部文件
ls -l
长数据串列出,包含文件的属性和权限等数据
mkdir 文件夹名
创建一个文件夹
mkdir -p 文件夹1名/文件夹2名
创建文件文件夹1/文件夹2
rmdir 文件夹名
删除文件夹
rmdir -p 文件夹1名/文件夹2名
删除文件夹1/文件夹2
touch 文件名
创建文件
cp [选项] source dest
将source文件复制到dest
-
若dest是目录,则将source文件复制到dest目录下
-
若dest是文件,则使用source文件内容复制到dest文件中
-
-r 递归复制整个文件夹
-
rm [选项] deleteFile
删除文件
-r 递归删除目录中的所有内容
-f 强制执行删除操作,不进行确认
-v 显示指令执行的详细过程
mv old new
移动文件/文件夹/重命名
cat [选项] 文件名
查看文件内容,从第一行开始显示(一般用来查看小文件)
-n 显示所有行的行号,包括空行
more 文件名
查看文件内容
-
空格 下翻一页
-
Enter 下翻一行
-
q 离开more
-
Ctrl+f 下一页
-
Ctrl+b 上一页
-
= 输出当前行的行号
-
:f 输出文件名和当前行的行号
less 文件名
查看文件内容
-
空格 下一页
-
pagedown 下一页
-
pageup 上一页
-
/字串 向下搜索匹配的字串
-
n 向下查找
-
N 向上查找
-
-
?字串 向上搜索匹配的字串
-
n 向上查找
-
N 想下查找
-
-
q 退出less
echo [选项] 输出内容
-e 支持反斜线控制等转义字符
-
\ 输出\本身
-
\n 换行
-
\t tab
>
输出重定向 (覆盖写入)
>>
追加(追加写入到末尾)
-
ls -l > 文件
-
ls -al >> 文件
-
cat 文件1 >> 文件2
-
echo "内容" >> 文件
head 文件
显示文件头部内容
head -n 行数 文件
显示文件前n行内容
tail 文件
显示文件尾部内容
tail -n 行数 文件
显示文件尾部n行内容
tail -f 文件
实时追踪该文档的所有更新
-
Ctrl+s 暂停追踪文件更新
-
Ctrl+q 继续追踪文件更新
-
Ctrl+c退出追踪
ln -s [源文件/目录] [软链接名]
给原文件创造一个软链接
-
删除软链接:rm -rf 软链接名(软链接名后不能加/,加上/后会将真实目录下的文件删除)
history
查看使用命令历史
-
!+命令编号 可以直接通过命令历史编号使用命令
-
history -c 将所有命令历史删除
时间日期类
date [OPTION] ... [+FROMAT]
-d<时间字符串> 显示指定的“时间字符串”表示的时间,而非当前时间
-s<日期时间> 设置系统日期时间
<+日期时间格式> 指定显示时使用的日期时间格式
date
显示当前时间
date +%Y
显示当前年份
date +%m
显示当前月份
date +%d
显示当年是哪一天
date "+%Y-%m-%d %H:%M:%S"
显示年月日时分秒
date -d '1 days ago'
显示前一天时间
date -d '-1 days ago'
显示后一天时间
'数字 日/月/年/时/分/秒 ago'
date -s 字符串时间
设置系统时间
cal [选项]
查看日历
cal
查看当月日历
cal -y
查看当年的日历
cal 年份
查看某一年的日历
用户管理命令
useradd 用户名
添加新用户
useradd -g 组名 用户名
添加新用户到某个组
useradd -d 文件夹 用户名
创建新用户,并设置该用户的根目录
passwd 用户名
设置用户密码
id 用户名
查看用户是否存在
cat /etc/passwd
查看用户列表
su 用户名称
切换用户,只能获得用户的执行权限,不能获得环境变量
su - 用户名称
切换用户并获得该用户的环境变量和执行权限
who am i
当前窗口身份信息
whoami
当前会话身份信息
sudo 命令
设置普通用户具有root权限
vim /etc/sudoers
设置普通用户可以临时获取管理员权限
userdel 用户名
删除用户,不删除该用户的根目录
userdel -r 用户名
删除用户,且将该用户根目录删除
usermod -g 用户组 用户名
修改用户所在组
用户组管理命令
groupadd 组名
新增组
groupdel 组名
删除组
usermod -g 用户组 用户名
修改用户所在组
groupmod -n 新组名 原组名
修改组名
cat ``/etc/group
查看组信息
vim /etc/sudoers
修改用户组的权限
文件权限类
ll 或 ls -l
查看文件权限
权限:
文件类型 | 属主权限 | 属组权限 | 其他用户权限 | ||||||
---|---|---|---|---|---|---|---|---|---|
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
d | r | w | x | r | - | x | r | - | x |
目录文件 | 读 | 写 | 执行 | 读 | 写 | 执行 | 读 | 写 | 执行 |
文件类型:
-
d 目录
-
- 文件
-
l 链接文档
用户没有权限时,会出现 -
chmod
改变权限
chmod [{ugoa}(+-=){rwx}] 文件或目录
修改文件或目录的权限
u 属组
g 属组
o 其他用户
a 所有人(u、g、o的总和)
chmod [mode=421] [文件或目录]
修改文件或目录的权限
r=4 w=2 x=1
rwx=4+2+1=7
chmod -R [mode=421] 目录
将目录及其中所有文件和文件夹权限都修改
chown
改变所有者
chown [选项] [最终用户] [文件或目录]
改变文件或目录的所有者
-R 递归修改
chgrp
改变所属组
chgrp [最终用户组] [文件或目录]
改变文件或目录的所属组
搜索查找类
find
将从指定目录向下递归遍历其各个子目录,将满足条件的文件显示在终端
find [搜索范围] [选项]
查找文件或目录
-name<查询方式> 按照指定的文件名查找模式查找文件(可以使用正则,需要用"")
-user<用户名> 查找属于指定用户名所有文件
-size<文件大小> 按照指定的文件大小查找文件,单位为:b块(512字节)、c(字节)、w字(2字节)、k千字节、M兆字节、G吉字节
find ./ -size +2M
将大于2M的文件全部检索
locate 快速定位文件路径
locate指令利用事先建立的系统中所有文件名称及路径的locate数据库实现快速定位给定的文件
在运行locate前,需要将索引表更新
updatedb
更新locate索引表
locate 搜索文件
检索的文件路径
grep 过滤查找及‘|’管道
‘|’ 表示将前一个命令的处理结果传递给后面的命令处理
grep 选项 查找内容 源文件
-n 显示匹配行及行号
压缩解压类
gzip/gunzip
gzip 文件
压缩文件,只能将文件压缩为 *.gz 文件
gunzip 文件.gz
解压缩文件
-
只能压缩文件不能压缩目录
-
不保留源文件
-
同时压缩多个文件会产生多个压缩包
zip/unzip
zip [选项] xxx.zip 将要压缩的内容
压缩文件和目录
-r 压缩目录
unzip [选项] xxx.zip
解压缩文件
-d<目录> 指定解压后文件的存放目录
tar
tar [选项] xxx.tar.gz 将要打包的内容
打包目录,压缩后的文件格式为 .tar.gz
-c 产生 .tar 打包文件
-v 显示详细信息
-f 指定压缩后的文件名
-z 打包同时压缩
-x 解包 .tar 文件
-C 解压到指定目录
磁盘查看和分区类
du 查看文件和目录占用的磁盘空间
du 目录/文件
显示目录下每个子目录的磁盘使用情况
-h 使用 GBytes, MBytes, KBytes 等格式显示
-a 不仅查看子目录大小,还要包括文件
-c 显示所有的文件和子目录大小后,显示总和
-s 只显示总和
--max-depth=n 指定统计子目录的深度为第n层
df 查看磁盘空间使用情况
df 选项
列出文件系统的整体磁盘使用量,检查文件系统的磁盘空间占用情况
-h 使用 GBytes, MBytes, KBytes 等格式显示
lsblk 查看设备挂载情况
lsblk
查看设备挂载情况
-f 查看详细的设备挂载情况,显示文件系统信息
mount/umount 挂载/卸载
mount [-t vfstype] [-o option] 设备名 挂载点
挂载设备
umount 设备文件名或挂载点
卸载设备
-t vfstype 指定文件系统的类型,通常不必指定。mount会自动选择正确的类型
-o option 用来描述设备或档案的挂接方式
参数:
loop:用来把一个文件当成硬盘分区挂接上系统
ro:采用只读方式挂接设备
rw:采用读写方式挂接设备
iocharset:指定访问文件系统所用字符集
设置开机自动挂载
vi /etc/fstab
fdisk 分区
fdisk -l
查看磁盘分区详情
fdisk 硬盘设备名
对新增硬盘进行分区操作
将硬盘格式化:mkfs -t xfs 硬盘设备名
进程管理类
ps 查看当前系统进程状态
ps:process status
进程状态
ps
当前用户及控制台使用的进程
a 列出带有终端的所有用户的进程
x 列出当前用户的所有进程,包括没有终端的进程
u 面向用户友好的显示风格
-e 列出所有进程
-u 用户名 列出某个用户关联的所有进程
-f 显示完整格式的进程列表
ps aux | grep xxx
查看系统中所有进程
ps -ef | grep xxx
可以查看子父进程间的关系
ps aux 显示信息说明
-
USER:改进程是由哪个用户产生的
-
PID:进程的ID号
-
%CPU:进程占用CPU资源百分比,占用越高,进程越耗费资源
-
%MEM:进程占用物理内存百分比,占用越高,进程越耗费资源
-
VSZ:进程占用虚拟内存的大小,单位KB
-
RSS:进程占用实际物理内存的大小,单位KB
-
TTY:进程是哪个终端中运行的。在CentOS中,tty 1是图形化终端,tty2-tty6是本地字符界面终端,pts/0-255是虚拟终端
-
STAT:进程状态。R:运行状态、S:睡眠状态、T:暂停状态、Z:僵尸状态、s:包含子进程、+:前台显示
-
START:进程的启动时间
-
TIME:进程占用CPU的运算时间(不是系统时间)
-
COMMAND:产生进程的命令名
使用技巧:
-
aux:查看进程CPU占用率和内存占用率
-
ef:查看进程的父进程ID
kill 终止进程
kill [选项] 进程号
通过进程号杀死进程
killall 进程名称
通过进程名称杀死进程(相关进程全部会被kill),也支持通配符(在系统因负载过大而变慢时很有用)
-9 强制进程立即停止
pstree 查看进程树
pstree [选项]
-p 显示进程的PID
-u 显示进程的所属用户
top 实时监控系统进程状态
top [选项]
-d 秒数 制定top命令每隔几秒更新。默认是3秒在top命令的交互模式当中可以执行的命令
-i 使top不显示任何闲置或者僵尸进程
-p 通过指定监控进程ID来仅仅监控某个进程的状态
操作:
-
P:以CPU使用率排序,默认为P
-
M:以内存使用率排序
-
N:以PID排序
-
q:退出top
natstat 显示网络状态和端口占用信息
netstat -anp | grep 进程号
查看该进程网络信息
netstat -nlp | grep 端口号
查看网络端口号占用情况
-a 显示所有正在监听(listen)和未监听的套接字(socket)
-n 拒绝显示别名,能显示数字的全部转化为数字
-l 仅列出在监听的服务状态
-p 表示显示正在被调用的进程
crontab 系统定时任务
systemctl restart crond
重启 crond 服务
crontab [选项]
设置 crontab 定时任务
-e 编辑 crontab 定时任务
-l 查询 crontab 任务
-r 删除当前用户所有的 crontab 任务
编辑定时任务
命令: ***** 执行的任务
项目 | 含义 | 范围 |
---|---|---|
第一个 “*” | 一个小时中的第几分钟 | 0-59 |
第二个 “*” | 一天中的第几小时 | 0-23 |
第三个 “*” | 一个月中的第几天 | 1-31 |
第四个 “*” | 一年中的第几月 | 1-12 |
第五个 “*” | 一周中的星期几 | 0-7(0和7都代表星期日) |
特殊符号 | 含义 |
---|---|
* | 代表任何时间。eg:第一个“*”代表一小时中每分钟都执行一次 |
, | 代表不连续时间。eg:“0 8,12 * * * 命令”代表每天8点0分,12点0分都执行一次 |
- | 代表连续的时间范围。eg:“0 5 * * 1-6 命令”代表在周一到周六的凌晨5点0分执行 |
*/n | 代表每隔多久执行一次。eg:“*/10 * * * * 命令”代表每隔10分钟执行一次 |
eg:
命令 | 含义 |
---|---|
45 22 * * * 命令 | 每天22点45分执行 |
0 17 * * 1 命令 | 每周一17点0分执行 |
0 5 1,15 * * 命令 | 每月1号和15号5点0分执行 |
40 4 * * 1-5 命令 | 每周一到周五4点40分执行一次 |
*/10 4 * * * 命令 | 每天4点,每隔10分钟执行一次 |
0 0 1,15 * 1 命令 | 每月1号和15号,每周一0点0分执行 |
软件包管理
rpm
rpm 查询命令
rpm -qa
查询所安装的所有rpm软件包
rpm -qi 软件包
显示安装软件的详细信息
rpm -qa | grep rpm 软件包
过滤
eg: 查看 Firefox 软件安装 rpm -qa | grep rpm 软件包
rpm 卸载命令
rpm -e RPM软件包
卸载软件包
rpm -e --nodeps 软件包
不检查依赖,直接卸载
rpm 安装命令
rpm -ivh RPM包全名
安装软件
-i install,安装
-v --verbose,显示详细信息
-h --hash,进度条
--nodeps 安装前不检查依赖
yum 仓库配置
yum常用命令
yum [选项] [参数]
选项:
-y 对所有提问都回答"yes"
参数:
install 安装rpm软件包
update 更新rpm软件包
check-update 检查是否有可用的更新rpm软件包
remove 删除指定的rpm软件包
list 显示软件包信息
clean 清理 yum 过期缓存
deplist 显示 yum 软件包的所有依赖关系
修改 yum 源
-
安装 wget(wget用来从指定的URL下载文件)
yum install wget
-
在 /etc/yum.repos.d/ 目录下,备份默认的 repos 文件
cp Centos-Base.repo Centos-Base.repo.backup
-
下载网易163或aliyun的repos文件
wget http://mirrors.aliyun.com/repo/Centos-7.repo //阿里云 或 wget http://mirrors.163.com/.help/Centos-Base-163.repo //网易163
shell 操作
概述
查看本机全部解析器: cat /etc/shells
查看本机默认使用解析器命令: echo $SHELL
shell 脚本
shell 脚本以 #!/bin/bash
开头(指定解析器)
第一个 shell 脚本:helloworld.sh
# 创建文件 touch helloworld.sh # 写入 vim helloworld.sh #!/bin/zsh echo "helloworld"
执行脚本
-
方法1本质是bash解析器执行脚本,所以脚本本身不需要执行权限
-
方法2本质是需要自己执行,需要执行权限
# 1、采用bash或sh使用相对路径或绝对路径执行脚本 sh ./helloworld.sh 或 bash ./helloworld.sh # 2、采用脚本的相对路径和绝对路径执行脚本(必须具有可执行权限 +x) # 脚本增加 x 权限 chmod +x helloworld.sh # 执行 ./helloworld.sh # 3 source helloworld.sh 或 . helloworld.sh
注意事项:
-
前两种方法都是在当前shell中打开一个子shell来执行脚本内容,当脚本内容结束,则子shell关闭,回到父shell
-
第三种可以使脚本内容在当前shell里执行,无需打开子shell
-
开子shell和不开子shell的区别在于,环境变量的继承,若在子shell中设置当前变量,父shell是不可见的
变量
常用系统变量
$HOME、$PWD、$SHELL、$USER
# 查看系统变量的值 echo $HOME # 显示当前shell中所有变量 set # 将局部变量提升为全局变量 export 变量名 # 定义常量(不可重新赋值) readonly 常量名=值
自定义变量
语法:
-
定义变量:变量名=变量值,=号前后不能有空格
-
撤销变量:unset 变量名
-
声明静态变量:readonly 变量,不能unset
变量定义规则:
-
可由字母、数字和下划线组成,不能以数字开头,环境变量名建议大写
-
等号两侧不能有空格
-
在 bash 中,变量默认类型都是字符串类型,无法直接进行数值运算
-
变量的值如果有空格,需要使用双引号或单引号
父shell和子shell变量测试
# 在脚本中写入变量 var vim helloworld.sh #!/bin/zsh echo "helloworld" echo $var # 在父 shell 中设置var="hello" var="hello" # 执行脚本 source helloworld.sh helloworld hello # 查看变量赋值 echo $var hello # 在父 shell 中设置为全局变量 export var # 进入子shell bash # 打印变量(成功,成功读取到父 shell 中的赋值) echo $var hello # 修改变量 var="Hello" # 退出子shell exit # 在父 shell 中查看变量(变量未修改) echo $var hello
特殊变量
$n
n为数字,$0代表该脚本名称,$1-$9代表第一到第九个参数,十以上的参数需要用大括号${10}
$#
获取所有输入参数个数,常用于循环,判断参数的个数是否正确以及脚本的健壮性
$*
代表命令行中所有参数,$*将所有参数看成一个整体
$@
代表命令行中所有参数,$@将每个参数区分对待
$?
最后一次执行命令的返回状态。若该值为0,则上一个命令正确执行;若值非0(具体值不定),则上一个命令执行不正确
# 编写脚本 vim parameter.sh #!/bin/bash echo '=======$n========' echo "$0" echo "parameter1=$1" echo "parameter2=$2" echo "parameter3=$3" echo '=======$#========' echo parameter numbers: $# echo '=======$*========' echo $* echo '=======$@========' echo $@ echo '=================' # 运行脚本 . ./parameter.sh 111 222 333 =======$n======== ./parameter.sh parameter1=111 parameter2=222 parameter3=333 =======$#======== parameter numbers: 3 =======$*======== 111 222 333 =======$@======== 111 222 333 ================= # 判断上一次命令执行是否正确(0为正确) echo $? 0
运算符
$((运算式))
或 $[运算式]
s=$[(2+3)*4] echo $s 20 expr 5 + 2 7 expr 5 - 2 3 expr 5 \* 2 10 a=`expr 5 \* 2` echo $a 10 a=$(expr 5 \* 4) echo $a 20
vim add.sh #!/bin/bash sum=$(($1 + $2)) # 或 $[$1+$2] echo sum=$sum . ./add.sh 22 11 33
条件判断
-
test condition
判断是否正确 -
[ condition ]
condition前后有空格
条件非空即为true,[ 321321 ]返回true,[ ]返回false
a=hello # 测试方法一 test $a = hello echo $? 0 # 测试正确输出0 test $a = Hello echo $? 1 # 测试错误输出除0外的值 # 测试方法二 [ $a = hello ] echo $? 0 # 测试正确输出0 [ $a = Hello ] echo $? 1 # 测试错误输出除0外的值
常用判断条件
-
整数比较
-eq 等于(equal) -ne 不等于(not equal) -lt 小于(less than) -le 小于等于(less equal) -gt 大于(greater than) -ge 大于等于(greater equal) 与 && -a 或 || -o [ 8 -ne 8 ] echo $? 1
注意:如果是字符串之间的比较,“=”判断相等,“!=”判断不等
-
文件权限进行判断
-r 有读取的权限(read) -w 有写入的权限(write) -x 有执行的权限(execute) # 判断文件是否有可读的权限 [ -r helloworld.sh ] echo $? 0
-
按照文件类型进行判断
-e 文件存在(existence) -f 文件存在且是一个常规文件(file) -d 文件存在且是一个目录(directory) [ -e helloworld.sh ] echo $? 0
-
多条件判断(&& 表示前一条命令执行成功后,才执行后一条命令,|| 表示上一条命令执行失败后,才执行下一条命令)
# 若 [ 123123 ] 和 echo OK 执行为真,则不会继续 || 后的判断,所以只会输出OK [ 123123 ] && echo OK || echo NOTOK OK # 若 [ 123123 ] 执行为假,则跳过 && 后的判断,直接执行 || 后的判断,所以只会输出NOTOK [ ] && echo OK || echo NOTOK NOTOK [ $a -lt 20 ] && echo "$a < 20" || echo "$a >= 20" 15 < 20
流程控制
if 判断
# 第一种 if [ 条件判断式 ];then 程序 fi # 第二种 if [ 条件判断式 ] then 程序 fi # 第三种 if [ 条件判断式 ] then 程序 elif [ 条件判断式 ] then 程序 else 程序 fi
# 实例(防止传入的参数为空出现报错,所以设置最少有一个字符) # 编写脚本 vim test1.sh if [ $1 = parameter ] then echo "hello world" fi . ./test1.sh parameter hello world # 1、判断是否达到条件 a=15 if [ $a -gt 18 ] && [ $a -lt 35 ];then echo "OK";fi a=15 if [ $a -gt 18 ] && [ $a -lt 35 ];then echo "OK";fi OK # 2 -a替换&&(and) -o替换||(or) a=15 if [ $a -gt 18 -a $a -lt 35 ];then echo "OK";fi OK
case 语句
case $变量名 in "值1") 程序1 ;; "值2") 程序2 ;; ..省略其他分支.. *) 若变量值都不为以上的值,则执行此程序 ;; esac
注意:
-
case 行尾必须为单词
in
,每一个模式匹配必须以右括号)
结束 -
双分号
;;
表示命令序列结束,相当于 break -
最后
*_
表示默认,相当于 default
for 循环
# 语法一 for (( 初始值;循环控制条件;变量变化 )) do 程序 done # 语法二 for 变量 in 值1 值2 值3... do 程序 done
# 编写脚本 vim test.sh #!/bin/bash sum=0 for (( i=0; i<=$1; i++ )) do sum=$[ $sum + $i ] done echo $sum . ./test.sh 100 5050 # {值1..值2} 表示从值1遍历到值2 for i in {1..100}; do sum=$[$sum+$i]; done; echo $sum 5050
测试 $*
和 $@
的区别:$* 是将所有元素看作是一个整体,$@是看作是单独的元素
# 脚本 vim test.sh #!/bin/bash echo '=======$*========' for i in "$*" do echo "$i" done echo '=======$@========' for i in $@ do echo "$i" done echo '=================' # 运行脚本 . ./parameter.sh 11 22 33 =======$*======== 11 22 33 =======$@======== 11 22 33 =================
while 循环
while [ 条件判断式 ] do 程序 done
# 方法一 a=1 while [ $a -le $1 ] do sum=$[$sum +$a] a=$[$a + 1] done echo $sum # 方法二 a=1 while [ $a -le $1 ] do let sum+=a let a++ done echo $sum
read 读取控制台输入
read (选项) (参数)
选项:
-
-p:指定读取值时的提示符
-
-t:指定读取值时等待的时间(秒),如果-t不加表示一直等待
参数:
-
变量:指定读取变量的变量名
# 编写脚本 vim read_test.sh #!/bin/bash read -t 10 -p "请输入数字:" num echo "the number is $num" # 运行脚本 bash ./read_test.sh
函数
basename
basename [string/pathname] [suffix]
basename命令会删掉所有的前缀,包括最后一个('/')字符,然后将字符串显示出来
-
basename可以理解为取路径中的文件名称
suffix 为后缀,若 suffix 被指定了,basename 会将 pathname 或 string 中的 suffix 去掉
# 获取文件名 basename /Users/a11/Desktop/code/shell/helloworld.sh helloworld.sh # 将文件名的后缀删除 basename /Users/a11/Desktop/code/shell/helloworld.sh .sh helloworld
dirname
dirname 文件绝对路径
从给定的包含绝对路径的文件名中去除文件名(非目录的部分),返回剩下的路径(目录部分)
-
dirname 可以理解为取文件路径的绝对路径名称
dirname /Users/a11/Desktop/code/shell/helloworld.sh /Users/a11/Desktop/code/shell
应用实例
vim test.sh #!/bin/bash echo script name: $(basename $0 .sh) echo script path: $(cd $(dirname $0); pwd) . ./test.sh script name: test script path: /Users/a11/Desktop/code/shell
自定义函数
# []表示可以省略 [ function ] funname[()] { Action; [return int;] }
-
在调用函数之前,需先声明函数,shell脚本时逐行运行,不会像其他语言一样先编译
-
函数返回值,只能通过 $? 系统变量获得,可以加 return 返回;如果不加,将以最后一条命令运行结果作为返回值。return后跟数值 n(1-255)
#!/bin/bash function add(){ s=$[$1+$2] echo $s } read -p "first number" a read -p "second number" b sum=$(add $a $b) echo "sum="$sum echo "sum^2="$[$sum * $sum]
正则表达式
^
匹配一行的开头
$
匹配一行的结束
.
匹配任意一个字符
*
表示某个字符出现任意次
cat /etc/passwd | grep ^a cat /etc/passwd | grep a$ cat /etc/passwd | grep r..t cat /etc/passwd | grep ro*t
[]
字符区间,表示匹配某个范围内的一个字符
[6,8] 匹配 6 或 8 [0-9] 匹配 0-9 的数字 [0-9]* 匹配任意长度的数字字符串 [a-z] 匹配一个 a-z 的字符 [a-z]* 匹配任意长度的字符串 [a-c,e-f] 匹配 a-c或e-f 的任意字符
\
表示转义字符,需匹配特殊字符时使用
cat /etc/passwd | grep a \$
文本处理工具
cut
cut [选项参数] filename
从文件的每一行剪切字节、字符和字段并输出
-
-f 列号,提取第几列
-
-d 分隔符,按照指定分隔符分割列,默认是制表符“\t”
-
-c 按字符进行切割后加n,表示取第几列,eg:-c 1
# 截取文件第 1 列 cut -d " " -f 1 cut.txt # 截取文件第 2,3 列 cut -d " " -f 2,3 cut.txt # 截取系统PATH变量值,第2个“:”开始后的所有路径 echo $PATH | cut -d ":" -f 3- # 截取ip地址 ifconfig en0 | grep netmask | cut -d " " -f 2
awk
awk [选项参数] '/pattern1/{action1} /pattern2/{action2} ...' filename
-
awk [选项参数] 'BEGIN{action1} /pattern2/{action2} END{action3}' filename
在开始和结束时执行操作
pattern:表示 awk 在数据中查找的内容(匹配模式)
action:在找到匹配内容时所执行的一系列命令
-F 指定输入文件分隔符
-v 赋值一个用户定义变量
# 搜索 passwd 文件以 root 关键字开头的所有行,并输出该行的第 7 列 cat /etc/passwd | grep ^root | cut -d ":" -f 7 或 cat /etc/passwd | awk -F ":" '/^root/{print $7}' # 搜索 passwd 文件以 root 关键字开头的所有行,并输出该行的第1列和第7列,并以“,”分割 cat /etc/passwd | awk -F : '/^root/{print $1","$7}' # 只显示 /etc/passwd 的第1列和第7列,以逗号分割,且在所有行前面添加列名 user,shell 在最后一行添加 "aaaaa,/bin/bash" cat /etc/passwd | awk -F : 'BEGIN{print "user,shell"} {print $1,$7} END{print "aaaaa,/bin/bash"}' # 将 passwd 文件中的用户id 数值增加 1 并输出 cat /etc/passwd | awk -F : '{print $3+1}' 或 cat /etc/passwd | awk -v i=1 -F : '{print $3+i}'
awk 的内置变量
-
FILENAME 文件名
-
NR 已读的记录数(行号)
-
NF 浏览记录的域的个数(切割后列的个数)
# 在每行前增加文件名,行号,列数 awk -F : '{print "filename:" FILENAME ",linenum:" NR ",col:" NF}' /etc/passwd # 输出空行的行号 ifconfig | awk '/^$/{print NR}' # 切割IP ifconfig | awk '/netmask/{print $2}'
综合应用案例
归档文件
需求:每天对指定目录中的文件进行归档备份,输入一个目录名称(末尾不带/),将目录下的所有文件按天归档保存,并将归档日期附加在归档文件名上,放在指定目录下
归档命令:tar
#!/bin/bash # 首先判断输入参数个数是否为1 if [ $# != 1 ] then echo "参数个数错误" exit fi # 从参数中获取目录名称 # 判断是否是一个目录 if [ -d $1 ] then echo else echo "目录不存在" exit fi DIR_NAME=$(basename $1) DIR_PATH=$(cd $(dirname $1); pwd) # 获取当前日期 DATE=$(date '+%y%m%d') # 定义生成归档文件的名称 FILE=archive_${DIR_NAME}_${DATE}.tar.gz DEST=$DIR_PATH/$FILE # 开始归档目录文件 echo "start archive" echo tar -czf $DEST $DIR_PATH/$DIR_NAME if [ $? = 0 ] then echo "OK" echo $DEST else echo "NOTOK" fi
发送消息
需求:向某个用户快速发送消息,输入用户名作为第一个参数,后面加上要发送的消息。脚本需要检测用户是否登陆在系统中、是否打开消息功能,以及当前发送消息是否为空
#!/bin/bash # 查用户是否登陆 login_user=$(who | grep -i -m 1 $1 | awk '{print $1}') if [ -z $login_user ] then echo "$1 不在线" echo "exit" exit fi # 查用户是否开启通信 is_allowed=$(who -T | grep -i -m 1 $1 | awk '{print $2}') if [ $is_allowed != "+" ] then echo "$1 无法通信" echo "exit" exit fi # 查看是否有消息发送 if [ -z $2 ] then echo "没有消息发送" echo "exit" exit fi # 从参数中获取要发送的消息 whole_msg=$(echo $* | cut -d " " -f 2-) # 获取用户登陆的终端 user_terminal=$(who | grep -i -m 1 $1 | awk '{print $2}') # 写入要发送的消息 echo $whole_msg | write $login_user $user_terminal if [ $? = 0 ] then echo "OK" else echo "NOTOK" fi