linux 命令行与shell脚本编程大全
第一章
Linux LiveCD就是从cd读取的系统,由于没法将数据写入到cd,所以一旦重启,之前操作过后的一切数据都会丢失。
第二章
第三章
1.man手册使用快捷键
使用空格键翻页
2.man -k 某类型 ==== 查找某类型下的所有命令
3.ls
-R 递归选项
-a 显示隐藏文件
-F :方便区分何为目录何为文件
-l :长列表格式输出
linux会在根驱动器上创建一些特别的目录,我们称之为挂载点
ls -l my_scr[ai]pt 匹配a或i
ls -l f[a-i]ll 匹配a到i范围的或
ls -l [!a]all 匹配非a的通配字符串
ls my?test 通配一个字符
处理文件
1.创建空文件(很实用) :再也不用vi再保存了。
touch file.name 文件不存在则创建文件,文件存在则更新文件的修改时间(并不修改文件内容)
2.复制文件
-i : cp -i file1 file -i 开启强制提醒是否覆盖!
-R: cp -R Scripts/ Mod_Scripts
链接文件
如需要在系统上维护同一文件的两份或多份副本,除了保存多份单独的副本的物理文件外,还可以采用保存一份物理文件副本和多个虚拟文件副本的方法,这种虚拟文件的副本就称为链接。
1.软链接 (i结点不同,表明是不同的文件)
一个实在存在的文件,它指向存放在虚拟目录结构中某个地方的另一个文件。这两个通过符号链接在一起的文件彼此的内容并不相同。
软链接只是指向文件的一个文件,所以它的大小远小于文件。
2.硬链接 (i结点相同,表明就是同一个文件)
.硬链接会创建独立的虚拟文件,其中包含了原始文件的信息及位置。但他们从根本上来讲是同一个文件。引用硬链接文件等同于引用源文件。
同时创建多个目录和子目录
mkdir -p /askcm/sajcn/akscn
root@ubuntu:/home/zyb/CODE/LEETCODE/myleetcode/JZ_OFFER# mkdir -p ./askcm/sajcn/akscn
root@ubuntu:/home/zyb/CODE/LEETCODE/myleetcode/JZ_OFFER# ls
03 05 32_1 32_3 42 askcm operator_reload.cpp
root@ubuntu:/home/zyb/CODE/LEETCODE/myleetcode/JZ_OFFER# cd askcm/sajcn/akscn/
查看文件内容
1.file “filename”
确定文件类型,编码信息等
2.cat
-n 给输出的内容加上行号
-b 只给有文本的内容加上行号 (突然知道怎么统计代码行号了!!!)
3.more
more 分页显示
4.less
5.tail 显示文件的最后几行内容
-n number :具体要显示最后的几行。
6.head …
第四章
管理进程
1.ps
-e 指定显示所有运行在系统上的进程
-f 扩展输出信息
-l 长格式输出
-T 显示跟当前终端关联的所有进程
-a 显示跟任意终端关联的所有进程
-r 仅显示运行的进程
2.top
实时显示进程的信息
结束进程
1.kill
一般是 kill pid
加-s更强制一些,避免有的进程不服管理。kill -s pid
2.kill all (支持进程名,支持通配符)
killall http* 通常是因为系统中某一系列进程占用资源过多
监测磁盘空间
1.mount
2.umount (linux系统,先卸载再弹出)
3.df (所有已挂在磁盘的使用情况)
4.du 显示当前目录下的所有文件、目录和子目录的磁盘使用情况(以磁盘块为单位显示每个文件和目录占用了多大存储空间)
处理数据文件
1.排序文件
1.1 sort (默认字符排序)
-n 把数字识别成数字而不是字符,并按序排序
-M 按月排序
2.搜索数据
2.1 grep 【options】pattern 【file】
-v 反向搜索
-n 显示搜索结果的行
-c 有多少行含有匹配的模式
-e 指定多个匹配模式 grep -e t -e f file1
3.压缩数据
1.gzip
4.归档数据
tar tar function 【options】 object1 object2 …
function:
-A 将一个已有tar归档文件追加到另一个已有tar归档文件
-c 创建一个新的tar归档文件
-d 检查归档文件和文件系统的不同之处
-r 追加文件到已有tar归档文件末尾
-t 列出已有tar归档文件的内容
-u 将比tar归档文件中已有的同名文件新的文件追加到该tar归档文件中
-x 从已有归档文件中提取文件
options:
-C 切换到指定目录
-f 输出结果到文件或指定file
-j 将输出重定向给bzip2命令来压缩内容
-p 保留所有文件权限
-v 在处理文件时显示文件
-z 将输出重定向给gzip命令来压缩内容
第五章
1.进程列表
(pwd;ls;cd /etc;pwd;ls;cd -;echo $BASH_SUBSHELL) (生成一个子shell来执行)
{。。。。。。。。。。。} 不生成子shell
2.协程
协程可以同时做两件事,它在后台生成一个子shell,并在这个子shell中执行命令
3.理解shell内建命令
3.1外部命令
当外部命令执行时,会创建一个子进程(比如运行我们自己构建的程序)
3.2内部命令
内建命令和外部命令的区别在于前者不需要使用子进程来执行。它们已经和shell编译成一体,作为shell工具的组成部分存在。不需要借助外部的程序文件来运行。
4.命令别名
alias li=“ls -li"
第六章
1.显示环境变量:
printenv
echo $HOME
2.环境遍量:
1.全局:大写字母,所有派生的shell都可以使用。
2.局部:小写字母,只能自己使用。
一旦启动了bash shell,就能创建在这个shell进程内可见的局部变量
2.创建局部环境变量:
通过’='给环境变量赋值,如果要给变量赋值一个含有空格的字符串值,必须使用双引号来界定字符串首尾。
3.创建全局环境变量:
先创建一个局部环境变量,再将它导入全局环境变量。
zyb@zyb-ubto:~$ my_varibale=“I am Global Now”
zyb@zyb-ubto:~$ echo
m
y
v
a
r
i
b
a
l
e
z
y
b
@
z
y
b
−
u
b
t
o
:
my_varibale zyb@zyb-ubto:~
myvaribalezyb@zyb−ubto: I am Global Now
zyb@zyb-ubto:~$ export my_varibale
zyb@zyb-ubto:~$ bash
zyb@zyb-ubto:~$ echo
m
y
v
a
r
i
b
a
l
e
z
y
b
@
z
y
b
−
u
b
t
o
:
my_varibale zyb@zyb-ubto:~
myvaribalezyb@zyb−ubto: I am Global Now
创建的子shell改变了该值,但是并不会映射到父shell,只在该子shell中有效。
4.删除环境变量 (同样遵循全局和局部的关系)
unset
!!!(要操作环境变量,不使用
,
要
用
到
变
量
,
使
用
,要用到变量,使用
,要用到变量,使用)
5.设置PATH环境变量 ( 同样具有全局和局部的特性 )
如何理解PATH环境变量:
以前只是跟着网上教程瞎设置,大体也了解,就是在打开一个程序后,系统搜索PATH中的路径,去追踪最终程序处于何位置!书上原文,当你在shell命令行界面中输入一个外部命令时,shell必须搜索系统来找到对应的程序。PATH环境变量定义了用于进行命令和程序查找的目录。
1.添加环境变量:(当退出系统时,对环境变量的修改将会复原)
PATH=$PATH:newpath
2.如何添加永久的环境变量?
编辑启动文件,并添加自己的环境变量,这些环境变量会在每次启动bash_shell会话时生效。
5.交互式shell进程
如果shell是作为交互式shell启动的,他就不会访问/etc/profile文件,只会检查HOME目录中的.bashrc文件
第七章
1.系统账户:系统上运行的各种服务进程,当他们运行时,和用户操作某一个对象一样,需要存在一个用户,且这个用户需要有操纵这个对象的权限,于是就为这些服务进程创建一个非真正的用户来操作他们,于是他们就叫系统用户。所有运行在后台的服务都需要一个系统用户登陆到linux系统上。
(用户 : 密码 : uid : gid : home : shell )
2.用户文件 /etc/passwd
密码文件 /etc/shadow
3.useradd -m newuser
userdel (默认情况下,只删除用户不删除其文件)
4.修改用户
1.usermod
选项:
-c, --comment 注释 GECOS 字段的新值
-d, --home HOME_DIR 用户的新主目录
-e, --expiredate EXPIRE_DATE 设定帐户过期的日期为 EXPIRE_DATE
-f, --inactive INACTIVE 过期 INACTIVE 天数后,设定密码为失效状态
-g, --gid GROUP 强制使用 GROUP 为新主组
-G, --groups GROUPS 新的附加组列表 GROUPS
-a, --append GROUP 将用户追加至上边 -G 中提到的附加组中,
并不从其它组中删除此用户
-h, --help 显示此帮助信息并退出
-l, --login LOGIN 新的登录名称
-L, --lock 锁定用户帐号
-m, --move-home 将家目录内容移至新位置 (仅于 -d 一起使用)
-o, --non-unique 允许使用重复的(非唯一的) UID
-p, --password PASSWORD 将加密过的密码 (PASSWORD) 设为新密码
-s, --shell SHELL 用户帐号的新登录 shell
-u, --uid UID 用户帐号的新 UID
-U, --unlock 解锁用户帐号
-Z, --selinux-user new SELinux user mapping for the user account
2.passwd、chpasswd
chpasswd < users.txt (键值对文本):批量修改用户的密码
\3. chsh:修改shell chsh -s /bin/tsch 用户
chfn: chfn 用户
chage:管理账户的有效期
chage
用法:chage [选项] [登录]
选项:
-d, --lastday 最近日期 将最近一次密码设置时间设为“最近日期”
-E, --expiredate 过期日期 将帐户过期时间设为“过期日期”
-h, --help 显示此帮助信息并退出
-I, --inactive INACITVE 过期 INACTIVE 天数后,设定密码为失效状态
-l, --list 显示帐户年龄信息
-m, --mindays 最小天数 将两次改变密码之间相距的最小天数设为“最小天数”
-M, --maxdays 最大天数 将两次改变密码之间相距的最大天数设为“最大天数”
-W, --warndays 警告天数 将过期警告天数设为“警告天数”
5.组 在添加用户到不同的组之前,要创建这个组
1.创建新组 groupadd
2.修改组 groupmod ( 组名+GID )
选项:
-g, --gid GID 将组 ID 改为 GID
-h, --help 显示此帮助信息并推出
-n, --new-name NEW_GROUP 改名为 NEW_GROUP
-o, --non-unique 允许使用重复的 GID
-p, --password PASSWORD 将密码更改为(加密过的) PASSWORD
//groupmod -n newgroupname oldgroupname
//文件权限解读
1.解读 ls -l
示例: -rw-r–r-- 1 zhangyb zhangyb 8445 4月 17 2012 examples.desktop
bit1:
- 文件
d 目录
l 链接
c 字符型设备
b 块设备
n 网络设备
bit 2~10:对象属主、属组、其他用户的:读、写、可执行权限
2.权限设置
umask命令用来设置和创建文件和目录的默认权限
umask 显示用户账户的默认权限:
umask (如缩写,umask即掩去权限)
0022 (第一位粘着位,八进制)
umask xxx 即可改变默认去权限值
3.权限改变 (chmod options mode file )
chmod命令用来改变文件和目录的安全性设置
八进制模式:
chmod 0xxx file
字符模式:
chmod【ugoa】【±=】【rwx…】
4.改变所属关系 (chown:改变文件属主 、 chgrp改变文件的默认属组)
1.chown options owner[.group] file
(属主:owner,属组.group)
总结:以前创建samba的共享文件夹时,使用的是某一个创建的用户来创建的,然后添加了另一个用户作为samba的用户,导致该用户登陆失败。这就是因为创建的共享文件目录的用户属组,它并不包含我添加的samba用户账户而导致的。
第八章
操作文件系统
1.创建分区(一开始,你必须**在文件系统上创建分区来存储文件系统**, 分区可以是整个硬盘。也可以是部分硬盘,以容纳虚拟目录的 一部分。)fdisk :交互式程序
:fdisk /dev/sdb
参数:
n: 在该存储设备上创建新的分区
分区:
主分区 (可被文件系统直接格式化)
扩展分区 (只能容纳其他逻辑主分区),扩展分区出现的原因是因为每个存储设备上只能有四个分区,可以通过创建多个扩展分区,然后在扩展分区内创建主分区进行扩展。
l: 列出系统支持的文件系统
w: 将更改保存到存储设备上 (存储设备的分区信息被写入到分区表中)
创建文件系统
mkfs.exe4 /dev/sdb1在将数据存储到分区之前,你必须使用某种文件系统对其进行格式化,这样linux系统才能使用它。每种文件系统都使用自己的命令行程序来格式化分区。
挂载文件系统到虚拟目录下的某个挂载点
(到这一步终于明白,原来系统上并无任何直接存储东西的较大内存空间,都是通过创建分区,将分区使用某种文件系统初始化,然后将该已经被初始化成某种文件系统的分区挂载在操作系统的某个虚拟目录下,以后,我们在该目录的一切操作(创建文件、目录...),其实就是对该分区的操作)mount -t exe4 /dev/sdb1 /mnt/myDir
(文件系统可以通过设备名、在虚拟目录中的挂载点、以及分配给文件系统的唯一UUID值来使用)
文件系统的检查与修复
fsck options filesystem
逻辑存储设备
出现原因:比如你当前创建的一个分区你要扩展,但是该分区所在的物理硬盘大小不够了,要么移动到另一个硬盘,要么创建逻辑分区。逻辑卷管理系统,将卷组视作一个物理硬盘,但事实上卷组可能是由分布在多个物理硬盘上的多个物理分区组成的。
linux系统将每一个逻辑卷称为一个物理分区。
每个逻辑卷可以被格式化成ext4文件系统,然后挂载到虚拟目录中的某个特定位置。
镜像: 镜像是一个实时更新的逻辑卷的完整副本。
第九章
各种PMS:包管理系统,一个数据库,用来记录各种相关内容
linux系统上已安装了什么软件包
每个包上安装了什么文件
每个已安装软件包的版本
yum
卸载软件
yum remove package_name 只删除软件包的数据和配置文件
yum erase package_name 删除软件和他所有的文件
处理损坏的包依赖关系
损坏的包依赖关系:某个包的软禁啊依赖关系可能会被另一个包的安装覆盖掉。
处理: yum clean all
yum update
还不行的话 , yum deplist package_name 就能显示所有包的依赖关系以及什么软件可以提供这些依赖库的关系。
最后的办法:若是以上还不行的话,可以使用 yum update --skip-broken 允许你忽略依赖关系损坏的那个包,继续去更新其他的软件包。
查看你从哪些仓库中获取软件。
yum repolist
若仓库中没有需要的软件,你可以编辑一下配置文件,/etc/yum.repos.d
从源码创建安装
- ./configure 确保正确的库依赖关系、合适的编译环境
- make 编译源码、链接器会为这个包创建最终的可执行文件。
- make install 经2之后程序编译好了,但是你只能在编译好程序的目录下执行该程序,为了能在任何目录下使用该程序,你可以执行make install 命令。(这个要有makefile文件)
第十章
vim编辑器
hjkl 左下上右
shift
- 4 当前行尾巴
- 6 当前行首
- 3 当前单词头
ctr
- f 下翻一屏
+b 上翻一屏
G 移动到缓冲区的最后一行
nums G 移动到第几行
gg 移动到缓冲区第一行
普通模式下编辑数据
x 将当前光标的数据删除
dd 删除行
d$ 删除当前光标所在直至当前行尾
J 删除当前行的行尾换行符
u 撤销前一编辑命令
a 在当前光标后追加数据
A 在当前光标尾追加数据
r char 用char替换当前光标所在位置的单个字符
R text 用text替换当前光标所在位置的数据,直至按下ESC键
5r char 用char替换当前光标所在位置的5个字符
等等…
复制和粘贴
p 粘贴,可以将它和任何删除命令使用,(因为vim删除数据时,实际上会将数据保存在单独的一个寄存器中,可以使用p命令取回)
y 复制文本
yd 复制当前行
y$ 从当前光标复制到行尾
查找
命令行模式下:
/word 回车之后输入n,便可跳到下一个单词
替换
s/old/new/ 只替换第一个
s/old/new/g 替换当前行中所有的old
n,ms/old/new/g 替换n~m行中所有的old
%s/old/new/g 替换整个文件中的所有old
%s/old/new/g 替换整个文件中的所有old,但在每次出现时提示
第十一章
shell脚本的关键在于输入多个命令并处理每个命令的结果,甚至需要将一个命令的结果传给另一个命令。
命令之间串起来用(who;date…),只要最大命令行字符数<=255即可
创建shell脚本,必须在文件的第一行指定要使用的shell
#!/bin/bash
shell不会解释以#开头的行,除了以#!开头的第一行
1.添加自己的文本消息来告诉脚本用户正在做什么!
2.单双引号:谁在外就显示另一方。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FYQr1ImA-1616509371795)(C:\Users\zhangyunbo\AppData\Local\YNote\data\m13821823961@163.com\ab3d67f0c4294b57a310294ea92dbe8d\clipboard.png)]
3.将输出信息和命令显示在一行,echo -n "info "(你需要在字符串的两侧使用引号,保证要显示的字符串尾部有一个空格)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lmuXj8Br-1616509371798)(C:\Users\zhangyunbo\AppData\Local\YNote\data\m13821823961@163.com\3717cfb3cb50443094ce639efd766733\clipboard.png)]
4.使用变量(环境变量、自定义变量和存储临时数据)
用户变量可以是任何由字母、数字或下划线组成的文本字符串,长度不超过20个,区分大小写,
变量=value之间不允许出现空格
shell脚本会自动决定变量值的数据类型
变量每次被引用时,都会输出当前赋给它的值
设置:VARNAME=VALUE
使用: V A R N A M E 从 而 , 引 号 中 使 用 VARNAME 从而,引号中使用 VARNAME从而,引号中使用字符,必须为$的形式
5.命令替换
将shell命令的输出赋给变量
datevar=date
datevar=$(date)
testvar=$(data +%y%m%d) 将时间输出成
命令替换是派生一个子shell来执行对应的命令,所以这些命令无法使用脚本中创建的变量。
7.重定向输入和输出
>> 以追加的形式重定向到一个已存在的文件。
wc wc < file.txt 输出文本中的:行、词、字节数
<< 内联输入重定向: cmd << characterstring(开始结束标记)
(任何字符串都可作为(开始结束标记))
例:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lg5BaOnm-1616509371799)(C:\Users\zhangyunbo\AppData\Local\YNote\data\m13821823961@163.com\88bec6accc4640e0b2207840242ee5ce\clipboard.png)]
8.管道
管道连接:将命令输出重定向到另一个命令(可持续地将命令的输出通过管道传给其他命令来细化操作)
9.执行数学运算
9.1 expr “数学表达式”
[root@localhost eight_chapter]# expr 300 * 100
30000
9.2 $[ operation ] (只支持整数运算)
10.执行退出码
在脚本结尾设置 exit num
exit 5
第十二章
对脚本中的命令增加一些逻辑流程控制
结构化命令:根据条件使得脚本跳过某些命令。
1.if-then
if cmd (若执行cmd后,退出状态为true(0),就执行then后的命令组
then cmds
fi
2.if-then-else-fi 同
3.if-then-elif-then-fi (优化.if-then-else-(if-then-fiI-fi))
4.test :超越单条命令退出码 仅(数值比较、字符串比较、文件比较)
if test conditios
then cmds
fi
if [ cmds ]
then cmds
fi
第十三章
重复执行一系列命令
for var in a b c d e f g h i j k (for循环假定每个值都是用空格分隔的,要输出空格使用双引号)
do
echo the next char is $var
done
{ 例子 :将一系列命令存放到一个变量中
[root@localhost 11章]# cat for1.sh
#!/bin/bash
list=“a b c d e f g h i j k”
list=$list" l"
for char in $list
do
echo the char is $char
done
}
//没有按行输出,依旧是按空格切割
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RqqRmeWZ-1616509371801)(C:\Users\zhangyunbo\AppData\Local\YNote\data\m13821823961@163.com\16f0cd6dda1a40f58c834b9503cea1fc\clipboard.png)]
1.更改字段分符(IFS:空格、制表符、换行符)
IFS=$’ \n’
13.2 C语言风格的for命令
for (( variable assignment ; condition ; iteration process ))
//for (( a = 1; a < 10; a ++ ))
1.变量赋值可以有空格
2.条件中的变量不以$开头
3.迭代过程中的算式未用expr命令格式
for循环中,可以使用多个变量,但是只能有一个条件
Linux的shell中的for循环使用
架构 完美起航 2020-10-10 19:49 92
shell中的for循环使用
常见的for循环用法主要有以下几种:
语法结构:
for item in (list)
do
command
done
例:
#!/bin/bash
for i in “土豆” “菠菜” “鱿鱼”
do
echo “我喜欢吃$i 。”
done
输出结果:
“我喜欢吃“土豆” 。”
“我喜欢吃“菠菜” 。”
“我喜欢吃“鱿鱼” 。”
示例 计算1到500的和
方式1:
#!/bin/bash
sum=0
for item in {1..500}
do
let "sum+=item"
done
echo "总数为:${sum}"
方式2:
#!/bin/bash
sum=0
for item in $(seq 1 500)
do
let "sum+=item"
done
echo "总数为:${sum}"
输出结果:120250
3、类C语言的for循环
语法结构:
for ((exp1;exp2;exp3;))
do
command
done
例:
#!/bin/bash
for ((num=1;num<=100;num++))
do
echo -n "$num "
done
计算1到100的和以及1到100的奇数和
#!/bin/bash
sum1=0
sum2=0
for((i=1,j=1;i<=100;i++,j+=2))
do
let "sum1+=i"
if [ $j -lt 100 ];then
let "sum2+=j"
fi
done
echo "sum1=$sum1"
echo "sum2=$sum2"
输出:
sum1=5050
sum2=2500
13.3 while命令
while test cmd
do
other cmds
done
while 命令允许你在while语句行定义多个测试命令,且所有定义的测试命令都会被执行一遍,但是起决定作用的只有最后一个测试命令。(!每个测试命令都出现在单独的一行)
until 退出状态 !=0
13.5 嵌套循环、控制循环(break,continue)
break 跳出内部循环
break n 跳出外部循环(n为几层循环)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pbPyDRJL-1616509371802)(C:\Users\zhangyunbo\AppData\Local\YNote\data\m13821823961@163.com\e99d03cbe92f4e97bfc9f01b468ef541\clipboard.png)]
continue 跳出本次循环
continue n n定义了要继续执行的层级
13.8 处理循环的输出
在shell脚本中,可以对循环的输出使用管道或进行重定向,这可以通过在done命令之后添加一个处理命令来实现
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-M18ZNQZp-1616509371803)(C:\Users\zhangyunbo\AppData\Local\YNote\data\m13821823961@163.com\0a4d41ed6078492abf6a10bf5ebd6611\clipboard.png)]
第十四章
从用户处获取数据
命令行参数
命令行选项
直接从键盘读取输入
1.读取参数
位置参数:$0 程序名,$1, … ,$9 (最大值)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u89VrLG2-1616509371805)(C:\Users\zhangyunbo\AppData\Local\YNote\data\m13821823961@163.com\598e8a6b4c0c410495d084b99d6f41d4\clipboard.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JeG0gLOI-1616509371806)(C:\Users\zhangyunbo\AppData\Local\YNote\data\m13821823961@163.com\1f79c34ad0f345768acd8f29fc44e9e9\clipboard.png)]
输入带空格的字符串参数时如果有空格要输入,则 ’ this is a string ’
2.超过9个的参数
${10} ${11}
3.使用脚本名
basename
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ggnf0Q1A-1616509371806)(C:\Users\zhangyunbo\AppData\Local\YNote\data\m13821823961@163.com\0f53e9494ce64ee4b2f051818f5c7f7f\clipboard.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DpCHvn5m-1616509371807)(C:\Users\zhangyunbo\AppData\Local\YNote\data\m13821823961@163.com\14a7f760bb024c61b45c55edb5684896\clipboard.png)]
14.2 特殊参数变量
14.2.1:参数统计
$# 得到输入的命令行个数
14.2.2:得到所有的命令行参数
这两个变量*、@都能够在单个变量中存储所有的命令行参数。
$* //将所有参数当作一个字符串
$@ //将参数当作参数数组
14.3 移动变量
shift //默认将变量值左移到变量的值。
14.4 处理选项 (选项:在单破折线后面的单个字母,它能改变命令的行为)
14.4.1 查找选项
1.处理简单选项
#!/bin/bash while [ -n “$1” ] do case “$1” in -a) echo “Found the -a option” ;; -b) echo “Found the -b option” ;; -c) echo “Found the -c option” ;; *) echo “$1 is not an option” ;; esac #注意case语句的用法 shift done
2.分离参数选项
#将参数与选项一同作为输入,但是要用–来表示选项的结束以及参数的开始 #!/bin/bash while [ -n “$1” ] do case “$1” in -a) echo “Found the -a option” ;; -b) echo “Found the -b option” ;; -c) echo “Found the -c option” ;; --) shift break ;; *) echo “$1 is not an option”;; esac shift done # echo $1 count=1 for param in KaTeX parse error: Expected 'EOF', got '#' at position 23: …cho "Parameter #̲count: p a r a m " c o u n t = param" count= param"count=[ $count + 1 ] done
3.使用 getopt 命令
#getopt 命令可以接受一系列任意形式的命令行选项和参数,并将它们自动转换成适当的格式 /* [root@localhost 11_chapter]# getopt ac:de -a -c -de tssdgdv -g getopt:无效选项 – g -a -c -de – tssdgdv / //忽略错误提示 / [root@localhost 11_chapter]# getopt -q ac:de -a -c -de tssdgdv -g -a -c ‘-de’ – ‘tssdgdv’ */ #详细解释 getopt optstring parameters optstring:表示选项有哪些,比如abs:f ,代表parameters 中的参数 -a -b -s s的参数 -f
14.4.2
#用getopt格式化后的版本作为来替换已有的命令行选项和参数, #然后使用 set – 来将getopt格式化后的命令行参数去替换原来的命令行参数 set – ( g e t o p t − q a b : c d " (getopt -q ab:cd " (getopt−qab:cd"@")
例子:
#!/bin/bash echo “the initital parameter:$@” set – ( g e t o p t − q a b : c d " (getopt -q ab:cd " (getopt−qab:cd"@") while [ -n “$1” ] do echo echo $1 echo case “$1” in -a) echo “Found the -a option”;; -b) param="$2" echo “Found the -b option,with parameter value $param” shift;; -c) echo “Found the -C option”;; --) shift break;;//跳出while循环了,所以就不执行case语句了,也不必担心参数多移动一位 *) echo “ 1 i s n o t a n o p t i o n " ; ; e s a c s h i f t d o n e e c h o e c h o " f i n i s h p a r a m e t e r : 1 is not an option";; esac shift done echo echo "finish parameter: 1isnotanoption";;esacshiftdoneechoecho"finishparameter:@”
//输出:
#输出结果 [root@localhost 11_chapter]# ./getopt_set.sh -a -b asdkcn -c -d p1 p2 p3 p4 the initital parameter:-a -b asdkcn -c -d p1 p2 p3 p4 -a Found the -a option -b Found the -b option,with parameter value ‘asdkcn’ -c Found the -C option -d -d is not an option – finish parameter:‘p1’ ‘p2’ ‘p3’ ‘p4’
4.使用更高级的getopts ( getopt是替换,getopts是和已有的shell参数变量默契配合 )
getopts optstring variable optstring 有效命令选项,取消错误提示使用:,需要参数使用:。 variable 将命令行参数保存在命令行中定义的variable中。 getopts 命令会用到两个环境变量: 如果选项需要跟一个参数值,OPTARG 环境变量就会保存这个值 OPTIND 环境变量保存了参数列表中getopts正在处理的参数位置,这样你就能在处理完选项之后继续处理其他命令行参数了 getopts会移除开头的单破折线,所以case中不使用-
示例 OPTARG与OPTIND的关系
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GtE828xA-1616509371808)(C:\Users\zhangyunbo\AppData\Local\YNote\data\m13821823961@163.com\fdd3216b892849f883ae5565c19b442c\clipboard.png)]
#还能这么用: getopts -abtest1 //会自动分离成选项-a,-b,参数test1 #找不到有效的选项会输出?
14.6 交互式获取用户输入:
.1)基本的读取
#read variable 从标准输入或另一个文件描述符中接受输入,并存储到变量variable中 1. read name 2. read -p “input your name:” name //直接在read命令行指定提示信息 3. read v1 v2 v3 //会将输入的变量按照空格从左往右保存,并且保存不完的全部保存在最后一个变量中 4. read //不指定变量,则会将接受到的任何数据都保存到特殊环境变量REPLY中
.2) 超时+超量
#超时:为了避免read阻塞脚本执行,需要设置一个定时器,-t(等待单位:s) #示例 echo -n “Enter your name:” read name echo “your name 's :$name” if read -t 5 -p “Enter your age:” age then echo “your arge is $age” else echo echo -n “you input nothing” fi while read -t 3 -p “input your address:” address do echo “your address is KaTeX parse error: Expected 'EOF', got '#' at position 23: …" break; done #̲超量:当读取的字符串长度到达我…cont” in Y | y) echo echo “fine,continue on…”;; N | n) echo echo “ok!goodbye” exit;; esac echo "this is the end of the script"cont
14.6.4 从文件中读取
#read //行缓冲 #!/bin/bash count=1 cat $1 | while read line do echo “Line c o u n t : count: count:line” count=$[ $count + 1] done echo “finish read file!”
第十五章
1.只重定向部分内容
ls -Rl file 2> errfile //将执行这条命令的标准错处重定向到文件errfile中 //关键:文件描述符值必须紧挨重定向符前
2.重定向错误和数据
#如果想重定向错误和正常输出,必须用两个重定向符号。 需要在符号前面放上待重定向数据所对应的文件描述符,然后指向用于保存数据的输出文件。 ls -al $1 $2 nofile1 nofile2 2> err_file 1> out_file #将标准输出和标准出错输出到同一个文件中 ls -al $1 $2 nofile1 nofile2 &> out_file
3.在脚本中重定向输出
#临时重定向 echo “this is an error message” >&2 //在重定向到文件描述符时,你必须在文件描述符数字之前加一个& #永久重定向 在有大量需要重定向的数据时,使用echo逐句重定向很繁琐,可以用exec命令告诉shell脚本执行期间重定向某个特定文件描述符 #!/bin/bash exec 1>testout echo “this is an test 1” echo “this is an test 2” echo “this is an test 3”
4.在脚本中重定向输入
#将STDIN从键盘重定向到其他位置 exec 0< testfile //告诉shell它应该从文件testfile中获得输入,而不是STDIN 这个重定向只要在脚本需要输入时就会作
5.重建自己的重定向
#由于每个进程可以有多至9个的fd,所以我们还可以将3~8分配给文件,然后再进行重定向 1. 创建输出文件描述符 exec 3>othrefdfile //也可以是直接追加到已存在文件 exec 3>>othrefdfile echo “this is an test 2” >&3 2. 创建输入文件描述符
6.创建读写文件描述符 # 类似C语言 exec <> file 7.在脚本退出之前关闭文件描述符 exec 3>&- 8.列出打开的文件描述符 lsof 列出整个linux系统打开的所有文件描述符。
8.创建临时文件和临时目录 cat /dev/null > file //快速清空文件 mktemp -t test.XXXXXX //在/tmp 目录下(-t选项指定)创建临时文件test.xxxxxx ,xxxxxx是为了文件不重复 mktemp -d testdir.XXXXXX //在创建目录(-d指定)test.xxxxxx ,xxxxxx是为了文件不重复 9.记录消息 tee file //将输出重定向至标准输出和文件file中(覆盖写,追加则加 -a 选项)
第十六章
\1. 处理信号
可以通过对脚本进行编程,使其在收到特定信号时执行某些命令,从而控制shell脚本的操作
1.1 捕获信号 trap commands signals 1.2 捕获脚本退出 trap commands EXIT 1.3 移除信号 trap – SIGINT
示例:
#!/bin/bash trap “echo ’ sorry! I havae tarped Ctr-C’” SIGINT trap “echo ‘Good bye!’” EXIT echo This is a test script count=1 while [ KaTeX parse error: Expected 'EOF', got '#' at position 30: …do echo "Loop #̲count" sleep 1 count=$[ $count + 1] done echo “end” #remove signal SIGINT trap – SIGINT count=1 while [ KaTeX parse error: Expected 'EOF', got '#' at position 31: …do echo "Loop #̲count" sleep 1 count=$[ $count + 1] done
\2. 以后台模式运行脚本
./a.sh &
\3. 禁止挂起
在终端会话中启动shell脚本,然后让脚本一直以后台模式运行到结束,
即使你退出了终端会话,这可以使用nohub命令来实现。
nohub ./a.sh &
\4. 作业控制
启动、停止、终止、恢复作业的这些功能统称为作业控制。
重启作业:bg
\5. 修改脚本优先级
nice值得修改 nice -n 10 ./a.sh //设置命令启动时的调度优先级 renice -n 10 -p pid //改变系统上已运行命令(pid指示)的优先级
\6. 脚本执行自动化 :在预选时间运行脚本
\1. at [-f filename] time
第十七章
//脚本中的函数更多考虑的是因为担心多次重复相同内容
1.基本的脚本函数(函数:脚本代码块)
#注意name与 ‘{’ 花括号之间的一个空格 1. function name { commands } 2. name() { commands } 同一个函数重复定义,后者会覆盖前者,遵循先定义后使用的规则
\2. 返回值
bash shell 会把函数当做一个小脚本,运行结束时会返回一个退出状态码。在函数结束时,可以用标准变量$?来确定函数的退出状态码。这个状态退出码不是表示这整个函数的所有命令的执行状态,而是这个函数的最后一条语句执行的状态码。
\1. return 2. result=$(db1) //保存函数输出
//示例
#!/bin/bash db1() { read -p "Enter a value: " value echo “doubling the value” return $[ $value * 2 ] } db1 echo “The new value is $?” #注意: 1. 必须在函数一结束就取状态码(避免丢失) 2. 状态码范围(0-255)
\3. 在函数中使用变量
#!/bin/bash addem() { if [ $# -eq 0 ] || [ $# -gt 2 ] then echo -1 elif [ $# -eq 1 ] then echo $[ $1 + $1 ] else echo $[ $1 + KaTeX parse error: Expected 'EOF', got '}' at position 8: 2 ] fi }̲ echo -n "Addin…(addem 10 15) echo v a l u e e c h o − n " L e t ′ s t r y a d d i n g j u s t o n e n u m b e r : " v a l u e = value echo -n "Let's try adding just one number: " value= valueecho−n"Let′stryaddingjustonenumber:"value=(addem 10) echo v a l u e e c h o − n " T r y a d d i n g n o n u m b e r : " v a l u e = value echo -n "Try adding no number: " value= valueecho−n"Tryaddingnonumber:"value=(addem) echo v a l u e e c h o − n " F i n a l l y , t r y a d d i n g t h r e e n u m b e r s : " v a l u e = value echo -n "Finally,try adding three numbers: " value= valueecho−n"Finally,tryaddingthreenumbers:"value=(addem 10 15 20) echo $value
由于函数使用特殊参数环境变量作为自己的参数值,因此它无法直接获取脚本在命令行中的参数值。 //错误示例 func () { echo $[ $1 + $2 ] } 要使用也得作为参数传递过去 func($1 $2)
\4. 变量的作用域
\1. 全局变量
脚本函数外的地方的变量
\2. 局部变量
函数内的地方的变量
func() { local temp //local声明temp为函数func内部自己声明的变量,这样就避免了外部同名变量与函数内部的值互相影响 }
\5. 数组作函数参数
必须将数组所有成员作为参数,在函数内部将所有值又组合成数组
#!/bin/bash function testbit { local newarray newarray=(‘echo “$@”’) echo "The new array value is: ${newarray[]}" } myarray=(1,2,3,4,5) echo "The original array is KaTeX parse error: Expected '}', got 'EOF' at end of input: …[*]}" testbit {myarray[]}
\6. 从函数返回数组
#!/bin/bash function arraydblr { local originalarray local newarray local elements local i originalarray=( ( e c h o " (echo " (echo"@")) newarray=( ( e c h o " (echo " (echo"@")) elements=$[ $# -1 ] //运行失败 for ((i = 0 ; i <= KaTeX parse error: Expected '}', got 'EOF' at end of input: …)) { newarray[i]=$[ KaTeX parse error: Expected '}', got 'EOF' at end of input: {originalarray[i]} * 2 ] } echo ${newarray[]} } myarrary=(1,2,3,4,5) echo -n "The original array is: m y a r r a r y [ ∗ ] " a r g 1 = {myarrary[*]}" arg1= myarrary[∗]"arg1=(echo ${myarrary[]}) echo echo -n “1: ${arg1[]}" echo echo -n "2: a r g 1 " e c h o r e s u l t = ( arg1 " echo result=( arg1"echoresult=((arraydblr a r g 1 ) ) e c h o − n " T h e n e w a r r a r y i s : arg1)) echo -n "The new arrary is: arg1))echo−n"Thenewarraryis:{result[]}”
\7. 创建库 //函数是为了同一脚本多次复用,库是为了多个脚本复用同一代码
使用source关键字 别名为 . #!/bin/bash #引用库 . ./myfuncs //注意是 . + 库的路径 value1=10 value2=5 rt1=$(addem $value1 v a l u e 2 ) r t 2 = value2) rt2= value2)rt2=(multem $value1 v a l u e 2 ) e c h o " T h e a d d e m r e s u l t i s : value2) echo "The addem result is : value2)echo"Theaddemresultis:rt1" echo “The multem result is :$rt2”
\8. 在命令行上定义函数和使用
[root@localhost sh_dir]# add() { echo $[ $1 + $2 ]; } [root@localhost sh_dir]# add 1 2 3 [root@localhost sh_dir]# add 1 5 6
\9. 在.bashrc文件中定义函数 永久定义函数
,5) echo "The original array is KaTeX parse error: Expected '}', got 'EOF' at end of input: …[*]}" testbit {myarray[*]}
\6. 从函数返回数组
#!/bin/bash function arraydblr { local originalarray local newarray local elements local i originalarray=( ( e c h o " (echo " (echo"@")) newarray=( ( e c h o " (echo " (echo"@")) elements=$[ $# -1 ] //运行失败 for ((i = 0 ; i <= KaTeX parse error: Expected '}', got 'EOF' at end of input: …)) { newarray[i]=$[ KaTeX parse error: Expected '}', got 'EOF' at end of input: {originalarray[i]} * 2 ] } echo ${newarray[]} } myarrary=(1,2,3,4,5) echo -n "The original array is: m y a r r a r y [ ∗ ] " a r g 1 = {myarrary[*]}" arg1= myarrary[∗]"arg1=(echo ${myarrary[]}) echo echo -n “1: ${arg1[]}" echo echo -n "2: a r g 1 " e c h o r e s u l t = ( arg1 " echo result=( arg1"echoresult=((arraydblr a r g 1 ) ) e c h o − n " T h e n e w a r r a r y i s : arg1)) echo -n "The new arrary is: arg1))echo−n"Thenewarraryis:{result[]}”
\7. 创建库 //函数是为了同一脚本多次复用,库是为了多个脚本复用同一代码
使用source关键字 别名为 . #!/bin/bash #引用库 . ./myfuncs //注意是 . + 库的路径 value1=10 value2=5 rt1=$(addem $value1 v a l u e 2 ) r t 2 = value2) rt2= value2)rt2=(multem $value1 v a l u e 2 ) e c h o " T h e a d d e m r e s u l t i s : value2) echo "The addem result is : value2)echo"Theaddemresultis:rt1" echo “The multem result is :$rt2”
\8. 在命令行上定义函数和使用
[root@localhost sh_dir]# add() { echo $[ $1 + $2 ]; } [root@localhost sh_dir]# add 1 2 3 [root@localhost sh_dir]# add 1 5 6
\9. 在.bashrc文件中定义函数 永久定义函数