当前位置: 首页 > news >正文

设计网站公司力荐亿企邦阿里云wordpress 讲解

设计网站公司力荐亿企邦,阿里云wordpress 讲解,关于网站开发的自我评价,gae+wordpress目录 1 基础1.1 程序组成1.2 程序编程风格1.3 编程语言1.4 编程逻辑处理方式 2 shell 脚本语言的基本结构2.1 shell脚本的用途2.2 shell脚本基本结构2.3 创建shell脚本过程2.4 脚本注释规范2.5 第一个脚本2.6 脚本调试2.7 变量2.7.1 变量2.7.2 变量类型2.7.3 编程语言分类2.7.4… 目录 1 基础1.1 程序组成1.2 程序编程风格1.3 编程语言1.4 编程逻辑处理方式 2 shell 脚本语言的基本结构2.1 shell脚本的用途2.2 shell脚本基本结构2.3 创建shell脚本过程2.4 脚本注释规范2.5 第一个脚本2.6 脚本调试2.7 变量2.7.1 变量2.7.2 变量类型2.7.3 编程语言分类2.7.4 shell中变量命名法则2.7.5 变量定义和引用2.7.6 环境变量2.7.7 只读变量2.7.8 位置变量2.7.9 退出状态码变量2.7.10 展开命令行2.7.11 脚本安全和 set 命令 2.8 格式化输出 printf2.9 算术运算2.10 逻辑运算2.11 条件测试命令2.11.1 变量测试2.11.2 数值测试2.11.3 字符串测试2.11.4 文件测试 2.12 关于()和{}2.13 组合测试条件2.13.1 方法 1 []2.13.2 方法 2 [[]] 2.13 使用read命今来接受输入 3 bash的配置文件3.1 按生效范围划分两类3.2 shell登录两种方式分类3.2.1 交互式登录3.2.2 非交互式登录 3.3 按功能划分分类3.3.1 profile类3.3.2 Bashrc类 3.4 编辑配置文件生效3.5 Bash 退出任务 4 流程控制4.1 条件选择4.1.1 选择执行 if 语句4.1.2 条件判断 case 语句 4.2 循环4.2.1 循环执行介绍4.2.2 for循环**格式1:****格式2** 例加入参数实现三角形4.2.3 while循环4.2.4 until循环4.2.4 循环控制语句 continue4.2.5 循环控制语句 break4.2.6 循环控制 shift 命令4.2.7 while read 特殊用法4.2.8 select 循环与菜单 5 函数介绍5.1 管理函数5.1.1 定义函数5.1.2 查看函数5.1.3 删除函数 5.2 函数调用**5.2.1 交互式环境调用函数**5.2.2 在脚本中定义及使用函数5.2.3 使用函数文件 5.3 函数返回值5.4 环境函数5.5 函数参数5.6 函数变量5.7 函数递归 6 其它脚本相关工具6.1 信号捕捉 trap6.2 创建临时文件 mktemp6.3 安装复制文件 install6.4 交互式转化批处理工具 expect 7数组7.1 数组介绍7.2 声明数组7.3 数组赋值7.4 显示所有数组7.5 引用数组7.6 删除数组7.7 数组数据处理7.8 关联数组7.9 范例 8 字符串处理8.1 字符串切片8.2 查找替换、8.3 查找并删除8.4 字符大小写转换 9 高级变量9.1 高级变量赋值9.2 高级变量用法-有类型变量9.3 变量间接引用9.3.1 eval命令9.3.2 间接变量引用9.3.3变量引用reference 1 基础 1.1 程序组成 程序:算法数据结构数据:是程序的核心算法:处理数据的方式数据结构: 数据在计算机中的类型和组织方式 1.2 程序编程风格 面向过程语言 做一件事情排出个步骤第一步干什么第二步干什么如果出现情况A做什么处理如果出现了情况B做什么处理问题规模小可以步骤化按部就班处理以指令为中心数据服务于指令Cshell 面向对象语言 一种认识世界、分析世界的方法论。将万事万物抽象为各种对象类是抽象的概念是万事万物的抽象是一类事物的共同特征的集合对象是类的具象是一个实体问题规模大复杂系统以数据为中心指令服务于数据javaC#pythongolang等 1.3 编程语言 计算机运行二进制指令 编程语言人与计算机之间交互的语言。分为两种:低级语言和高级语言 低级编程语言: 机器二进制的0和1的序列称为机器指令。与自然语言差异太大难懂、难写 汇编用一些助记符号替代机器指令称为汇编语言 ​ 如:ADDAB 将寄存器A的数与寄存器B的数相加得到的数放到寄存器A中 ​ 汇编语言写好的程序需要汇编程序转换成机器指令 ​ 汇编语言稍微好理解即机器指令对应的助记符助记符更接近自然语言 高级编程语言: 编译高级语言–编译器–机器代码文件-执行如: CC解释高级语言–执行–解释器–机器代码如: shellpythonphpJavaScriptperl 编译和解释型语言 1.4 编程逻辑处理方式 三种处理逻辑 顺序执行选择执行循环执行 2 shell 脚本语言的基本结构 2.1 shell脚本的用途 自动化常用命令执行系统管理和故障排排除创建简单的应用程序处理文本或文件 2.2 shell脚本基本结构 shell脚本编程:是基于过程式、解释执行的语言 编程语言的基本结构 ​ 各种系统命令的组合​ 数据存储:变量、数组​ 表达式:ab​ 控制语句: if shell脚本:包含一些命令或声明并符合一定格式的文本文件 格式要求:首行shebang机制 #!/bin/bash #!/usr/bin/python #!/usr/bin/perl2.3 创建shell脚本过程 第一步使用文本编辑器来创建文本文件 第一行必须包括shell声明序列: #!示例:#!/bin/bash添加注释,注释以#开头 第二步加执行权限 给予执行权限在命令行上指定脚本的绝对或相对路径 第三步运行脚本 直接运行解释器将脚本作为解释器程序的参数运行 autocmd BufNewFile *.sh exec :cal SetTitle() func SetTitle()if expand(%:e) shcall setline(1,#!/bin/bash)call setline(2,#)call setline(3,#*****************************************************)call setline(4,#Author: minNexus)call setline(5,#QQ: 1299575088)call setline(6,#Date: .strftime(%Y-%m-%d))call setline(7,#FileName: .expand(%))call setline(8,#URL: https://blog.csdn.net/qq_24472227?typeblog) call setline(9,#Description: The test script)call setline(10,#Copyright (C): .strftime(%Y), All rights reserved)call Setline(11,#****************************************************)call setline(12,)endif endfunc autocmd BufNewFile * normal G2.4 脚本注释规范 第一行一般为调用使用的语言 程序名避免更改文件名为无法找到正确的文件 版本号 更改后的时间 作者相关信息 该程序的作用及注意事项 最后是各版本的更新简要说明 2.5 第一个脚本 [rootCentOS8 ~]#vim hello.sh 输入echo hello world [rootCentOS8 ~]#./hello.sh 执行hello.sh hello world2.6 脚本调试 语法错误导致后续命令不再执行 命令错误后续命令仍然执行 逻辑错误 检测脚本中的语法错误bash后加-n提示出错行不一定准确不执行 bash -n /path/to/some_script一定程度上检查逻辑出错 与 命令出错调试并执行加-x逐行执行并显示 bash -x /path/to/some_script注意 bash ScriptName 开启一个子进程在里面执行脚本source ScriptName 在当前进程执行脚本不开启子进程如果在其中修改了变量则修改了当前shell的变量不推荐使用除非配置文件 2.7 变量 2.7.1 变量 变量表示命名的内存空间将数据放在内存空间中通过变量名引用获取数据 2.7.2 变量类型 类型 内置变量如: PS1PATHUIDHOSTNAMEPPID$ ?BASHPIDHISTSIZE使用$查看用户自定义变量 不同的变量存放的数据不同决定了以下 数据存储方式参与的运算表示的数据范围 变量数据类型: 字符数值整型、浮点型 bash不支持浮点型 2.7.3 编程语言分类 静态和动态语言 静态编译语言:使用变量前先声明变量类型之后类型不能改变在编译时检查如:javac动态编译语言:不用事先声明可随时改变类型如: bashPython 强类型和弱类型语言 强类型语言: 不同类型数据操作必须经过强制转换才同一类型才能运算如java c#python ​ 如:以下python代码 print(magedu 10) 提示出错不会自动转换类型 print(magedustr(10)) 结果为magedu10需要显示转换类型弱类型语言:语言的运行时会隐式类型转换。无须指定类型默认均为字符型参与运算会自动进行隐式类型转换;变量无须事先定义可直接调用 如: bash phpjavascript 2.7.4 shell中变量命名法则 不能使程序中的保留字:如: if,for 只能使用数字、字母及下划线且不能以数字开头注意:不支持短横线“.和主机名相反 见名知义用英文单词命名并体现出实际作用不要用简写如: ATM 统一命名规则驼峰命名法studentname大驼峰StudentName 小驼峰studentName 变量名大写STUDENTNAME局部变量小写函数名小写 2.7.5 变量定义和引用 变量的生效范围等标准划分变量类型 普通变量生效范围为当前shel进程对当前shell之外的其它shell进程包括当前shell的子shell进程均无效环境变量生效范围为当前shell进程及其子进程本地变量生效范围为当前shell进程中某代码片断通常指函数 变量赋值: namevaluevalue可以是以下多种形式 直接字串: name‘root’变量引用: name“$USER”命令引用: nameCOMMAND 或者 name$(COMMAND) 注意变量赋值临时生效终端退出将自动删除不过为了安全起见最好使用完手动删除。脚本中的变量也随脚本结束自动删除 变量引用: $name ${name}弱引用和强引用 $name 双引号弱引用其中的变量引用会被替换为变量值 $name 单引号强引用其中的变量引用不会被替换为变量值而保持原字符串显示已定义的所有变量 set删除变量 unset name例 1 [rootCentOS8 ~]#ls f1.txt f2.txt f3.txt issue.bak passwd scripts test.img [rootCentOS8 ~]#FILE* 将当前文件夹所有文件名保存至变量FILE中 [rootCentOS8 ~]#echo $FILE f1.txt f2.txt f3.txt issue.bak passwd scripts test.img2 [rootCentOS8 ~]#FILEi am $HOSTNAME 将hostname的变量名存入变量FILE中 [rootCentOS8 ~]#echo $FILE i am CentOS8.Joyce.person13 [rootCentOS8 ~]#seq 10 1 2 3 4 5 6 7 8 9 10 [rootCentOS8 ~]#NUMseq 10 [rootCentOS8 ~]#echo $NUM 1 2 3 4 5 6 7 8 9 10 [rootCentOS8 ~]#echo $NUM 加双引号保留多行格式 1 2 3 4 5 6 7 8 9 102.7.6 环境变量 环境变量可以使子进程(包括子子进程)继承父进程的变量但是无法让父进程使用子进程的变量 一旦子进程修改从父进程继承的变量新的值将传递给子子进程 一般只在系统配置文件中使用在脚本中较少使用 声明环境变量 并赋值 export nameVALUE declare -x nameVALUE或分2步 nameVALUE export name变量引用 $name ${name}例 [rootCentOS8 ~]#NAMEjoyce [rootCentOS8 ~]#AGE21 [rootCentOS8 ~]#echo $NAME$AGE joyce21 [rootCentOS8 ~]#echo $NAME_$AGE 21 [rootCentOS8 ~]#echo ${NAME}_$AGE joyce_21显示所有环境变量 env printenv export declare -x删除变量: unset namebash内建的环境变量 PATH SHELL USER UID HOME PWD SHLVL 当前所在shell的深度使用bash进入下一shell开子进程后深度1最低是1 LANG 当前设置语言与编码格式 MAIL 邮箱位置 HOSTNAME HISTSIZE _ 下划线表示前一命令的最后一个参数前面记得加$脚本显示系统信息 RED\E[1;31m GREEN\E[1;32m END\E[0m echo -e \E[1;32m--------------------------------Host systeminfo------------------------------------$END echo -e HOSTNAME: $REDhostname$END echo -e IPADDR: $RED ifconfig ens160|grep -Eo ([0-9]{1,3}\.){3}[0-9][1,3] |head -n1$END echo -e OSVERSION: $REDcat /etc/redhat-release$END echo -e KERNEL: $REDuname -r$END echo -e CPU: $REDlscpu|grep Model name|tr -s |cut -d : -f2$END echo -e MEMORY: $REDfree -h|grep Mem|tr -s : |cut -d : -f2$END echo -e DISK: $REDlsblk |grep ^sd |tr -s |cut -d -f4$END echo -e \E[1;32m-----------------------------------------------------------------------------------$END2.7.7 只读变量 只读变量只能声明定义但后续不能修改和删除即常量退出终端自动删除 声明只读变量: 加-r readonly name declare -r name查看只读变量: readonly [-p] declare -r2.7.8 位置变量 位置变量在bash shell中内置的变量,在脚本代码中调用通过命令行传递给脚本的参数 $1$2... 对应第1个、第2个等参数shift [n]换位置 $0 命令本身包括路径想只显示名字可以写basename $0 $* 传递给脚本的所有参数全部参数合为一个字符串 $ 传递给脚本的所有参数每个参数为独立字符串 $# 传递给脚本的参数的个数注意: $ $ 只在被双引号包起来的时候才会有差异* 清空所有位置变量 set --例 [rootCentOS8 ~]#cat arg.sh 查看arg.sh文件 #!/bin/bash # #***************************************************************************** #Author: minNexus #QQ: 1299575088 #Date: 2023-07-25 #FileName: arg.sh #URL: https://blog.csdn.net/qq_24472227?typeblog #Description: The test script #Copyright (C): 2023 All rights reserved #****************************************************************************echo lst arg is $l echo 2st arg is $2 echo 3st arg is $3 echo 10st arg is ${l0} echo 1lst arg is ${11}echo The number of arg is $# echo All args are $* echo All args are $ echo The scriptname is basename $0[rootCentOS8 ~]#bash arg.sh {a..z} 运行脚本加上a..z参数 lst arg is 2st arg is b 3st arg is c 10st arg is 1lst arg is k The number of arg is 26 All args are a b c d e f g h i j k l m n o p q r s t u v w x y z All args are a b c d e f g h i j k l m n o p q r s t u v w x y z The scriptname is arg.sh2.7.9 退出状态码变量 进程执行后将使用变量 ? 保存状态码的相关数字不同的值反应成功或失败$?取值范例 0-255 $?的值为0 代表成功$?的值是1到255 代表失败 例 [rootCentOS8 ~]#curl www.google.com /dev/null [rootCentOS8 ~]#echo $? 7用户可以在脚本中使用以下命令自定义退出状态码 exit [n]注意: 脚本中一旦遇到exit命令脚本会立即终止终止退出状态取决于exit命令后面的数字如果未给脚本指定退出状态码整个脚本的退出状态码取决于脚本中执行的最后一条命令的状态码 2.7.10 展开命令行 展开命令执行顺序: 把命令行分成单个命令词 展开别名 展开大括号的声明{} 展开波浪符声明 ~ 命令替换$()和 再次把命令行分成命令词 展开文件通配* ? [abc]等等 准备I/0重导向 、 运行命令防止扩展 反斜线(\)会使随后的字符按原意解释加引号来防止扩展 单引号()-防止所有扩展 双引号 ()也可防止扩展但是以下情况例外: $(美元符号)变量扩展反引号命令替换 \ 反斜线禁止单个字符扩展 ! 叹号历史命令替换2.7.11 脚本安全和 set 命令 **set命令**可以用来定制shell环境 $- 变量 h hashal打开洗项后Shell会将命令所在的路径hash下来避免每次都要查询。通过set h将h洗项关闭 i interactive-comments包含这个选项说明当前的 shel 是一个交式的 shel。所谓的交式shell在脚本中i选项是关闭的 m monitor打开监控模式就可以通过Job control来控制进程的停止、继续后台或者前台执行等 B braceexpand大括号{}扩展set B关闭{}的功能 H historyH选项打开可以展开历史列表中的命令可以通过!感叹号来完成例如“!返回上最近的一个历史命令“!n”返回第 n个历史命令set 命今实现脚本安全 推荐打开-eu -u 在扩展一个没有设置的变量时显示错误信息等同set -o nounset避免出现删除整个目录 -e 如果一个命令返回一个非0退出状态值(失败)就退出等同set -o errexit -o option 显示打开或者关闭选项显示选项 set-o打开选项 set -o选项关闭选项 set o选项 -x 当执行命令时打印命令及其参数类似bash -x2.8 格式化输出 printf 格式 printf 指定的格式 文本1 文本2...常用格式替换符 %s 字符串 %f 浮点格式 %b 相对应的参数中包含转义字符时可以使用此替换符进行替换对应的转义字符会被转义 %c ASCII字符即显示对应参数的第一个字符 %d,%i 十进制整数 %o 八进制值 %u 不带正负号的十进制值 %x 十六进制值 (a-f) %X 十六进制值 (A-F) %% 说明:%s中的数字代表此替换符中的输出字符宽度不足补空格默认是右对齐%-10s表示10个字符宽- 表示左对齐 常用转义字符 \a 警告字符通常为ASCII的BEL字符 \b 后退 \f 换页 \n 换行 \r 回车 \t 水平制表符 \v 垂直制表符 \ 表示\本身例 [rootCentOS8 ~]#printf (%.3f)\n 1 2 3 (1.000) (2.000) (3.000)[rootCentOS8 ~]#printf %s\n%s 1 2 3 4;echo 1 23 42.9 算术运算 shell 支持算术运算但只支持整数不支持小数 bash中的算术运算 - * / % 取模即取余数%5的结果在0-4 ** 乘方乘法符号有些场景中需要转义 实现算术运算: let var算术表达式 var$[算术表达式] var$((算术表达式)) var$(expr argl arg2 arg3 ...) 注意expr里*可能被当作通配符乘法要用\* declare -i var 数值 echo算术表达式|bc例 [rootCentOS8 ~]#echo -e \E[1;$[RANDOM%731]mhello\e[0m 打印随机颜色的hello颜色编号31-37 hello[rootCentOS8 ~]#expr 99 \* 3 297[rootCentOS8 ~]#echo scale3;3/7|bc .428内建的随机数生成器变量 $RANDOM 取值范围 0-32767 增强型赋值 i10 相当于 ii10 - i-j 相当于 ii-j * / %i,i 相当于 ii1 -- i--,--i 相当于 ii-12.10 逻辑运算 true false1 0与: 与0为0与1保留1与111与000与100与00 或:| 同0为01或111或010或110或00 非:!!1 0 ! true!0 1 ! false 异或:^ 异或的两个值相同为假0不同为真非0。1^101^010^110^00两个数字异或将结果与任意一个数字异或结果是另一数字12^848^41212^48例 [rootCentOS8 ~]#ii10;j20;echo i$[i^(i^j)] j$[j^(i^j)] 使用异或交换i和j的值 i20 j10 [rootCentOS8 ~]#i10;j20;i$[i^j];j$[i^j];i$[i^j];echo i$i,j$j i20,j10短路运算 短路与 CMD1 短路与 CMD2 第一个CMD1结果为0(假)总的结果必定为0因此不需要执行CMD2第一个CMD1结果为1(真)第二个CMD2必须要参与运算才能得到最终的结果 短路或 CMD1 短路或CMD2 第一个CMD1结果为1(真)总的结果必定为1因此不需要执行CMD2第一个CMD1结果为0(假)第二个CMD2必须要参与运算才能得到最终的结果 2.11 条件测试命令 条件测试判断某需求是否满足需要由测试机制来实现专用的测试表达式需要由测试命令辅助完成测试过程实现评估布尔声明以便用在条件性环境下进行执行 若真则状态码变量 $? 返回0若假则状态码变量 $? 返回1 条件测试命令 test EXPRESSION 等价于 [ EXPRESSION ] 推荐使用[ ] [[ EXPRESSION ]]注意EXPRESSION前后必须有空白字符 2.11.1 变量测试 -v VAR 变量VAR是否设置即是否存在 -R VAR 变量VAR是否设置并引用示例判断NAME变量是否定义 [rootCentOS8 ~]#[ -v name ] 或 test -v NAME [rootCentOS8 ~]#echo $? 12.11.2 数值测试 -eq 是否等于 -ne 是否不等于 -gt 是否大于 -ge 是否大于等于 -lt 是否小于 -le 是否小于等于例 [rootCentOS8 ~]#x33 [rootCentOS8 ~]#y44 [rootCentOS8 ~]#[ $x -gt $y ] 必须假$ [rootCentOS8 ~]#echo $? 1 [rootCentOS8 ~]#[ $x -lt $y ] [rootCentOS8 ~]#echo $? 02.11.3 字符串测试 -z STRING 字符串是否为空未定义或空为真不空为假 -n STRING 字符串是否不空不空为真空为假 是否等于 ! 是否不等于​ ascii码是否大于ascii码 是否小于左侧字符串是否和右侧的PATTERN相同 注意:此表达式用于[[ ]]中PATTERN为通配符 ~ 左侧字符串是否能够被右侧的正则表达式的PATTERN所匹配注意: 此表达式用于[[ ]]中;扩展的正则表达式 即只在正则表达式才用双中括号[[]]其他都用[]且在[[ ]] 右侧的*单列则表示通配符只作为字符需要加或\转义字符串最好两边加否则可能出现问题 [rootCentOS8 ~]#namehello babe [rootCentOS8 ~]#[ $name ] -bash: [: hello: unary operator expected [rootCentOS8 ~]#[ $name ] [rootCentOS8 ~]#echo $? 0例 [rootCentOS8 ~]#title1ceo [rootCentOS8 ~]#title1cto [rootCentOS8 ~]#[ $title1 $title2 ] 字符串之间必须加空格 不加空格则成赋值 [rootCentOS8 ~]#echo $? 12通配符 [rootCentOS8 ~]#FILEtest.log [rootCentOS8 ~]#[[ $FILE *.log ]] [rootCentOS8 ~]#echo $? 03正则表达式 [rootCentOS8 ~]#FILEtest.log [rootCentOS8 ~]#[[ $FILE ~ \.log$ ]] [rootCentOS8 ~]#echo $? 0[rootCentOS8 ~]#IP1.2.3.444 判断ip地址是否合法在255.255.255.255之间 [rootCentOS8 ~]#[[ $IP ~ ^(([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$ ]] [rootCentOS8 ~]#echo $? 1 [rootCentOS8 ~]#IP1.2.3.4 [rootCentOS8 ~]#echo $? 02.11.4 文件测试 存在性测试 -a FILE 同 -e -e FILE 文件存在性测试存在为真否则为假 -b FILE 是否存在且为块设备文件 -C FILE 是否存在且为字符设备文件 -d FILE 是否存在且为目录文件 -f FILE 是否存在且为普通文件判断软链接则判断软链接指定的文件 -h FILE 或 -L FILE: 存在且为符号链接文件 -p FILE 是否存在且为命名管道文件 -S FILE 是否存在且为套接字文件例 [rootCentOS8 ~]#[[ -c /dev/zero ]] 判断是否为字符文件 [rootCentOS8 ~]#echo $? 0文件权限测试. -r FILE 是否存在且可读 -W FILE 是否存在且可写 -X FILE 是否存在且可执行 -u FILE 是否存在且拥有suid权限 -g FILE 是否存在且拥有sgid权限 -k FILE 是否存在且拥有sticky权限例 [rootCentOS8 ~]# [[ -x CHOOK_RABBIT.sh ]] 判断是否有执行权限 [rootCentOS8 ~]#echo $? 0 [rootCentOS8 ~]#chmod 0 CHOOK_RABBIT.sh 去除所有权限 [rootCentOS8 ~]# [[ -x CHOOK_RABBIT.sh ]] 判断是否有执行权限 [rootCentOS8 ~]#echo $? 1[rootCentOS8 ~]# [[ -r CHOOK_RABBIT.sh ]] 判断是否有可读权限因为我们是root所有仍然可以读 [rootCentOS8 ~]#echo $? 0 [rootCentOS8 ~]# [[ -w CHOOK_RABBIT.sh ]] 判断是否有写入权限因为我们是root所有仍然可以写 [rootCentOS8 ~]#echo $? 0文件属性测试 -S FILE 是否存在且非空 -t fd fd 文件描述符是否在某终端已经打开 -N FILE 文件自从上一次被读取之后是否被修改过 -O FILE 当前有效用户是否为文件属主 -G FILE 当前有效用户是否为文件属组 FILE1 -ef FILE2 FILE1是否是FILE2的硬链接 FILE1 -nt FILE2 FILE1是否新于FILE2(mtime) FILE1 -ot FILE2 FILE1是否旧于FILE22.12 关于()和{} (CMD1;CMD2;...) 都可以批量执行多个命令 { CMD1;CMD2;...; }最后加;{ }内前后加空格()会开启子shell继承父进程的变量。list中变量赋值及内部命令执行后不影响后续的环境。帮助参看:man bash 搜索(list) {;}不会启子shell在当前shell中运行会影响当前shell环境帮助参看:man bash 搜索{list;} 例 [rootCentOS8 ~]#namebabe;(echo $name;namehello;echo $name);echo $name 使用() babe hello babe [rootCentOS8 ~]#namebabe;{ echo $name;namehello;echo $name; };echo $name 使用{} babe hello hello2.13 组合测试条件 2.13.1 方法 1 [] EXPRESSION1 -a EXPRESSION2 并且EXPRESSION1和EXPRESSION2都是真结果才为真 EXPRESSION1 -o EXPRESSION2 或者EXPRESSION1和EXPRESSION2只要有一个真结果就为真 [ ! EXPRESSION ] 或 ![ exp ] 取反说明: -a和-0 需要使用测试命令进行[[]]不支持 2.13.2 方法 2 [[]] COMMAND1 COMMAND2 #并且短路与代表条件性的AND THEN如果COMMAND1 成功将执行COMMAND2否则将不执行COMMAND2 COMMAND1 || COMMAND2 #或者短路或代表条件性的OR ELSE如果COMMAND1 成功将不执行COMMAND2否则将执行COMMAND2 !COMMAND 非取反例 [rootCentOS8 ~]#NAMEjoycee;id $NAME /dev/null echo $NAME is exist || echo $NAME is not exist joycee is not exist[rootCentOS8 ~]#NANAMEjoycee;id $NAME /dev/null echo $NAME is exist || (useradd $NAME;echo $NAME is created) joycee is created注意 如果和 || 混用则 要放前|| 放后 2.13 使用read命今来接受输入 使用read来把输入值分配给一个或多个shell变量read从标准输入中读取值给每个单词分配一个变量所有剩余单词都被分配给最后一个变量 格式 read [options] [name ...]常见选项: -p 指定要显示的提示 -s 静默输入一般用于密码 -n N 指定输入的字符长度N -d 字符输入结束符 -t N TIMEOUT为N秒[rootCentOS8 ~]#read joyce [rootCentOS8 ~]#echo $REPLY joyce[rootCentOS8 ~]#read NAME TITLE joyce babe [rootCentOS8 ~]#echo $NAME $TITLE joyce babe[rootCentOS8 ~]#read -p are u ok? ANSWER are u ok?not bad [rootCentOS8 ~]#echo $ANSWER not bad[rootCentOS8 ~]#echo 1 2 test.txt 重定向 [rootCentOS8 ~]#read a b test.txt;echo $a; echo $b 1 2注意 [rootCentOS8 ~]#echo 1 2 | read a b | echo $a $b 1 2 [rootCentOS8 ~]#echo 1 2 | (read a b; echo $a $b) 1 2 [rootCentOS8 ~]#echo 1 2 | read a b; echo $a $b 管道里如果不加括号或|则中间和后面是两个独立的shell因此二者的ab不等 1 23 bash的配置文件 bash shell的配置文件很多可以分成下面类别 3.1 按生效范围划分两类 全局配置 /etc/profile /etc/profile.d/*.sh /etc/bashrc个人配置: ~/.bash_profile ~/.bashrc3.2 shell登录两种方式分类 3.2.1 交互式登录 直接通过终端输入账号密码登录使用su - UserName切换用户 配置文件执行顺序: /etc/profile -- /etc/profile.d/*,sh -- ~/.bash_profile -- ~/.bashrc -- /etc/bashrc3.2.2 非交互式登录 su UserName图形界面下打开的终端 执行脚本 任何其它的bash实例 执行顺序: /etc/profile.d/*.sh -- /etc/bashrc --~/.bashrc3.3 按功能划分分类 profile类和bashrc类 3.3.1 profile类 profile类为交互式登录的shell提供配置 全局: /etc/profile,/etc/profile.d/*.sh 个人:~/.bash_profile作用 用于定义环境变量运行命令或脚本 3.3.2 Bashrc类 bashrc类:为非交互式和交互式登录的shell提供配置 全局: /etc/bashrc 个人:~/.bashrc作用 定义命令别名和函数定义本地变量 3.4 编辑配置文件生效 修改profile和bashrc文件后有生效两种方法 重新启动shell进程source 或 . 配置文件 3.5 Bash 退出任务 保存在~/.bash_logout文件中 (用户),在退出登录shell时运行 功能 ​ 创建自动备份​ 清除临时文件 4 流程控制 4.1 条件选择 条件判断 if case||4.1.1 选择执行 if 语句 格式: if CMDs; then CMDs;[ elif CMDs; then CMDs; ]... [ else CMDs; ] fi单分支: if 判断条件;then条件为真的分支代码 fi双分支: if 判断条件; then条件为真的分支代码 e1se条件为假的分支代码 fi多分支: if 判断条件1; then条件1为真的分支代码 elif 判断条件2; then条件2为真的分支代码 ... e1se以上条件都为假的分支代码 fi说明: 多个条件时逐个条件进行判断第一次遇为“真”条件时执行其分支而后结束整个if语句if 语句可嵌套 4.1.2 条件判断 case 语句 格式: case WORD in [PATTERN [| PATTERN]...) CMDs ;;]...esac此处PATTERN指通配符的模式 case 变量引用 in PAT1)分支1;; PAT2)分支2;; ... *)默认分支;; esaccase支持glob风格的通配符: * 任意长度任意字符 ? 任意单个字符 [] 指定范围内的任意单个字符 | 或如 a或bG R E E N 清理日志 GREEN清理日志 GREEN清理日志END ;; 4.2 循环 4.2.1 循环执行介绍 将某代码段重复运行多次通常有进入循环的条件和退出循环的条件 重复运行次数 循环次数事先已知循环次数事先未知 常见的循环的命令forwhileuntil 4.2.2 for循环 格式1: for NAME [in WORDS ...] ; do COMMANDS; done(WORD之间使用空白符(空格、Tab键、回车)分割)或 for 变量名 in 列表;do循环体 done或 for 变量名 in 列表 do循环体 done执行机制依次将列表中的元素赋值给“变量名” 每次赋值后即执行一次循环体直到列表中的元素耗尽循环结束 for循环列表生成方式 直接给出列表整数列表 {start..end} $(seq [start [step]] end)返回列表的命令: $(COMMAND)使用glob如*.sh变量引用如$$#$*等位置参数 ( ∗ 将变量视为单个 *将变量视为单个 ∗将变量视为单个将变量视为整体) 死循环 for((;;)) ; do CMDs;done例 [rootCentOS8 ~]#for i in {001..8..2};do echo $i; done 001 003 005 007 [rootCentOS8 ~]#for i in seq 5;do echo $i; done 1 2 3 4 5 [rootCentOS8 ~]#for i in $(seq 5);do echo $i; done 1 2 3 4 5例计算123…100的和 [rootCentOS8 ~]#seq -s 100|bc 5050或 [rootCentOS8 ~]#sum0;for i in {1..100};do let sumi;done;echo $sum 5050例 [rootCentOS8 scripts]#cat sum.sh #!/bin/bashsum0 for i in $ ;dolet sumi doneecho $sum[rootCentOS8 scripts]#chmod x sum.sh [rootCentOS8 scripts]#./sum.sh 1 3 4 5 6 19例九九乘法表的实现 [rootCentOS8 scripts]#cat ./9x9.sh #!/bin/bashfor j in {1..9};dofor i in seq $j;doecho -e ${i}x$j$((i*j))\t\cdoneecho done [rootCentOS8 scripts]#./9x9.sh 1x11 1x22 2x24 1x33 2x36 3x39 1x44 2x48 3x412 4x416 1x55 2x510 3x515 4x520 5x525 1x66 2x612 3x618 4x624 5x630 6x636 1x77 2x714 3x721 4x728 5x735 6x742 7x749 1x88 2x816 3x824 4x832 5x840 6x848 7x856 8x864 1x99 2x918 3x927 4x936 5x945 6x954 7x963 8x972 9x981面试题要求将目录YYYY-MM-DD/中所有文件移动到YYYY-MM/DD/下 #1 yyyy-mm-dd10.sh 准备数据 #创建YYYY-MM-DD当前日期一年前365天到目前共365个目录里面有10个文件$RANDOM.Tog[rootcentos8 ~]#cat for_dir20.sh #!/bin/bash for i in {1..365};doDIRdate -d -$i day %Fmkdir /data/test/$DIRcd /data/test/$DIRfor n in {1..10};dotouch $RANDOM.logdone done#2 移动到YYYY-MM/DD/下 [rootcentos8 ~]#cat for_mv20.sh #!/bin/bash # DIR/data/test cd $DIR for DIR in *;doYYYY_MMecho $DIR |cut -d- -f1,2 #将年月和日期拆分成2部分这里是年月DDecho $DIR | cut -d- -f3 #这里是日期[ -d $YYYY_MM/$DD ] || mkdir -p $YYYY_MM/$DD /dev/nullmv $DIR/* $YYYY_MM/$DD done面试题扫描一个网段10.0.0.0/24判断此网段中主机在线状态将在线的主机的IP打印出来 NET10.0.0 for ID in {1..254};do{ping -c1 -W1 $NET.$ID /dev/null echo $NET.$ID is up || echo $NET.$ID is down} #实现并行 done wait #默认并行不会自动退出加上wait使其自动执行下一个命令格式2 双小括号方法即((…))格式也可以用于算术运算双小括号方法也可以使bash Shell实现C语言风格的变量操作 |10;((l)) for ((控制变量初始化;条件判断表达式;控制变量的修正表达式)) do循环体 done说明: 控制变量初始化:仅在运行到循环代码段时执行一次控制变量的修正表达式:每轮循环结束会先进行控制变量修正运算而后再做条件判断 例实现1累加到100 for ((sum0;i100;i));dolet sumi done echo $sum例九九乘法表的实现_2 for ((i1;i10;i));dofor((j1;ji;j));doecho -e ${j}x$i$((j*i))\t\cdoneecho done例实现国际象棋的棋盘较垃圾 for ((i1;i8;i));doif((i%2));thenfor((x0;x4;x));dofor ((j0;j8;j));doif ((j%2));thenecho -e \E[47m \E[0m\c ;elseecho -e \E[40m \E[0m\c ;fidoneechodoneelsefor((x0;x4;x));dofor ((j0;j8;j));doif ((j%2));thenecho -e \E[40m \E[0m\c ;elseecho -e \E[47m \E[0m\c ;fidoneechodonefi done例实现三角形 for((i1;i10;i));do#for((z0;z10-i;z));dofor((z10;z-i0;z--));doecho -e \c;donefor((j1;j2*i-1;j));doecho -e *\cdoneecho done例加入参数实现三角形 read -p 请输入三角形的行数: line for((i1;i$line;i));do#for((z0;z10-i;z));dofor((z$line;z-i0;z--));doecho -e \c;donefor((j1;j2*i-1;j));doecho -e *\cdoneecho done4.2.3 while循环 格式: while COMMANDs; do COMMANDS; donewhile CONDITION; do循环体 done说明: CONDITION:循环控制条件进入循环之前先做一次判断每一次循环之后会再次做判断;条件为“true则执行一次循环直到条件测试状态为“false终止循环因此:CONDTION一般应该有循环控制变量而此变量的值会在循环体不断地被修正 进入条件: CONDITION为true退出条件: CONDITION为false 死循环 #方法1 while true; do循环体 done#方法2 while :; do循环体 done范例使用while实现磁盘报警 WARNING10 #阈值 while : ;doUSEdf | sed -rn /^\/dev\/sd/s#.* ([0-9])%.*#\1#p |sort -nr | head -n1if [ $USE -gt $WARNING ] ; thenecho DISK will be full from hostname -I | mail -s Disk Warning 1299575088qq.comfisleep 10 #10秒循环一次 done例死循环 [rootCentOS8 scripts]#while :;do echo ok ;sleep 1 ;done ok ok ok ok ok4.2.4 until循环 格式: until COMMANDS; do COMMANDS; doneuntil CONDITION; do循环体 done说明: 进入条件CONDITION为false退出条件CONDITION为true 死循环 until false; do循环体 done4.2.4 循环控制语句 continue continue[N]提前结束第N层的本轮循环而直接进入下一轮判断最内层为第1层 格式 while CONDITION1; doCMD1...if CONDITION2; thencontinueCMDn... done例 #1 for((i0;i10;i));dofor((j0;j10;j));do[ $j -eq 5 ] continue 1 #1可以不写代表终止该层循环的本次循环echo $jdoneecho ----------------- done [rootCentOS8 scripts]#bash continue_for_1.sh 0 1 2 3 4 6 7 8 9 ----------------- 0 1 2 3 4 6 7 8 9 ----------------- 0 1 2 3 4 6 7 8 9 ----------------- 0 1 2 3 4 6 7 8 9 ----------------- 0 1 2 3 4 6 7 8 9 ----------------- 0 1 2 3 4 6 7 8 9 ----------------- 0 1 2 3 4 6 7 8 9 ----------------- 0 1 2 3 4 6 7 8 9 ----------------- 0 1 2 3 4 6 7 8 9 ----------------- 0 1 2 3 4 6 7 8 9 ----------------- #2 for((i0;i10;i));dofor((j0;j10;j));do[ $j -eq 5 ] continue 2 #2代表终止外层循环的本次循环使外层循环进入下次循环echo $jdoneecho ----------------- done [rootCentOS8 scripts]#bash continue_for_1.sh 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 0 1 2 3 44.2.5 循环控制语句 break break [N]提前结束第N层整个循环最内层为第1层 格式 while CONDITION1; doCMD1...if CONDITION2; thenbreakfiCMDn例 #1 for((i0;i10;i));dofor((j0;j10;j));do[ $j -eq 5 ] break 1 #1可以不写表示结束内层循环使外层循环进入下一轮echo $jdoneecho ----------------- done [rootCentOS8 scripts]#bash continue_for_1.sh 0 1 2 3 4 ----------------- 0 1 2 3 4 ----------------- 0 1 2 3 4 ----------------- 0 1 2 3 4 ----------------- 0 1 2 3 4 ----------------- 0 1 2 3 4 ----------------- 0 1 2 3 4 ----------------- 0 1 2 3 4 ----------------- 0 1 2 3 4 ----------------- 0 1 2 3 4 -----------------#2 for((i0;i10;i));dofor((j0;j10;j));do[ $j -eq 5 ] break 2 #2表示结束外层循环即结束所有循环echo $jdoneecho ----------------- done [rootCentOS8 scripts]#bash continue_for_1.sh 0 1 2 3 4例菜品选择 sum0 COLOR1echo -e \033[1;31m COLOR2echo -e \033[1;32m END\033[0mwhile :;doecho -e \033[33;1m\ccat -EOF 1)米 2)面 3)粉 4)汤 5)谷 6)肉EOFecho -e \033[0mread -p 请选择菜品 MENU case $MENU in 1|4)$COLOR1菜价$10$ENDlet sum10;; 3|5)$COLOR1菜价$20$ENDlet sum20;; 2)$COLOR1菜价$888$ENDlet sum888;; 6)$COLOR2你点的菜品总价是$sum$ENDbreak;; *)echo 输入错误;;esac$COLOR2你点的菜品总价是$sum$END done4.2.6 循环控制 shift 命令 shift[n]用于将参量列表list 左移指定次数缺省为左移一次。 参量列表list 一旦被移动最左端的那个参数就从列表中删除。while 循环遍历位置参量列表时常用到 shift 例shift批量创建用户 PASS110420 while [ $1 ];douseradd $1 echo $1 is created || echo $1 is existsecho $PASS | passwd --stdin $1shift #shift 1 一次只跳过1个2则跳过2个 done [rootCentOS8 scripts]#bash shift_user.sh Tom Alice Tom is created Changing password for user Tom. passwd: all authentication tokens updated successfully. Alice is created Changing password for user Alice. passwd: all authentication tokens updated successfully. 例判断某个ip访问的次数 [rootCentOS8 data]#sed -En /^ESTAB/s#.*[: ]([^:]):[0-9] $#\1#p ss.log | sort |uniq -c1 10.0.0.1200 10.0.0.84.2.7 while read 特殊用法 while循环的特殊用法遍历文件或文本的每一行即逐行处理 支持stdin 格式 while read line; do循环体 done /PATH/FROM/SOMEFILE说明依次读取/PATH/FROM/SOMEFILE文件中的每一行且将行赋值给变量line 例 [rootcentos8 ~]#echo joyce | read X ; echo $X # 管道|开启子进程[rootcentos8 ~]#echo joyce | while read X ; do echo $X;done joyce[rootcentos8 ~]#echo joyce | { read X ; echo $X; } joyce[rootcentos8 ~]#echo joyce | ( read X ; echo $X ) joyce[rootcentos8 ~]#echo joyce wang zhang | ( read X Y Z; echo $X $Y $Z ) joyce wang zhang[rootcentos8 ~]#echo joyce wang zhang | while read X Y Z; do echo $X $Y $Z;done joyce wang zhang例使用while read实现磁盘报警 WARNING10 MAIL1299575088qq.com df |sed -nr /^\/dev\/sd/s#^([^ ]) .* ([0-9])%.*#\1 \2#p |while read DEVICE USE;doif [ $USE -gt $WARNING ] ;thenecho $DEVICE will be full,use:$USE | mail -s DISK WARNING $MAILfi done例查看/sbin/nologin的shell类型的用户名和UID while read line ;doif [[ $line ~ /sbin/nologin$ ]] ; thenecho $line | cut -d: -f1,3fi done /etc/passwd例存放大量单词文件 [rootCentOS8 scripts]#wc -l /usr/share/dict/linux.words 479828 /usr/share/dict/linux.words4.2.8 select 循环与菜单 格式: select NAME [in WORDS ... ;] do COMMANDS; doneselect variable in list ;do循环体命令 done说明 select 循环主要用于创建菜单按数字顺序排列的菜单项显示在标准错误上并显示 PS3 提示符等待用户输入用户输入菜单列表中的某个数字执行相应的命令用户输入被保存在内置变量REPLY中select 是个无限循环因此要记住用 break 命令退出循环或用exit 命令终止脚本。也可以按 ctrlc 退出循select经常和 case 联合使用与for 循环类似可以省略 in list此时使用位置参量 5 函数介绍 5.1 管理函数 函数由两部分组成函数名和函数体 帮助参看help function 5.1.1 定义函数 function name { COMMANDS ; } or name () { COMMANDS ; }#语法一: func_name () {...函数体... }#语法二: function func_name {...函数体... }#语法三: function func_name () {...函数体... }例创建disable_firewall_selinux函数以关闭firewalld和selinux [rootcentos8_3 ~]#systemctl status firewalld ● firewalld.service - firewalld - dynamic firewall daemonLoaded: loaded (/usr/lib/systemd/system/firewalld.service; enabled; vendor preset: enabled)Active: active (running) since Sat 2023-08-12 22:57:44 CST; 6min ago [rootcentos8_3 ~]#getenforce Enforcing# 函数主体 [rootcentos8_3 ~]#disable_firewall_selinux () {systemctl stop firewalldsystemctl disable firewalldsed -i s/SELINUXenforcing/SELINUXdisabled/ /etc/selinux/configsetenforce 0}[rootcentos8_3 ~]#disable_firewall_selinux Removed /etc/systemd/system/multi-user.target.wants/firewalld.service. Removed /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service. [rootcentos8_3 ~]#systemctl status firewalld ● firewalld.service - firewalld - dynamic firewall daemonLoaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled; vendor preset: enabled)Active: inactive (dead) [rootcentos8_3 ~]#getenforce Permissive注意函数操作后确实修改了文件因此重启后仍然保存。但是函数本身一次性使用重启后消失因此想要保存函数需要写入到文件 例分装函数与调用于2个文件可直接调用函数 #funtions文件保存函数主体 [rootcentos8_3 scripts]#cat functions #函数1disable_firewall_selinux() disable_firewall_selinux () {systemctl stop firewalldsystemctl disable firewalldsed -i s/SELINUXenforcing/SELINUXdisabled/ /etc/selinux/configsetenforce 0 }#函数2yum_repo() yum_repo() {cd /etc/yum.repos.d/mkdir backupmv *.repo backupcat base.repo EOF[BaseOS] namealiyun BaseOS baseurl https://mirrors.aliyun.com/centos/8/BaseOS/x86_64/os/https://repo.huaweicloud.com/centos/8-stream/BaseOS/x86_64/os/ gpgcheck1 enabled1 gpgkeyfile:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial[AppStream] namealiyun AppStream baseurl https://mirrors.aliyun.com/centos/8/AppStream/x86_64/os/https://repo.huaweicloud.com/centos/8-stream/AppStream/x86_64/os/ gpgcheck1 enabled1 gpgkeyfile:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial[epel] nameExtra Packages for Enterprise Linux \$releasever - \$basearch # It is much more secure to use the metalink, but if you wish to use a local mirror # place its address here. #baseurlhttps://download.example/pub/epel/\$releasever/Everything/\$basearch metalinkhttps://mirrors.fedoraproject.org/metalink?repoepel-\$releaseverarch\$basearchinfra\$infracontent\$contentdir enabled1 gpgcheck1 countme1 gpgkeyfile:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-8[epel-debuginfo] nameExtra Packages for Enterprise Linux \$releasever - \$basearch - Debug # It is much more secure to use the metalink, but if you wish to use a local mirror # place its address here. #baseurlhttps://download.example/pub/epel/\$releasever/Everything/\$basearch/debug metalinkhttps://mirrors.fedoraproject.org/metalink?repoepel-debug-\$releaseverarch\$basearchinfra\$infracontent\$contentdir enabled0 gpgkeyfile:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-8 gpgcheck1[epel-source] nameExtra Packages for Enterprise Linux \$releasever - \$basearch - Source # It is much more secure to use the metalink, but if you wish to use a local mirror # place its address here. #baseurlhttps://download.example/pub/epel/\$releasever/Everything/SRPMS metalinkhttps://mirrors.fedoraproject.org/metalink?repoepel-source-\$releaseverarch\$basearchinfra\$infracontent\$contentdir enabled0 gpgkeyfile:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-8 gpgcheck1 EOF }#函数3install_package() install_package() { packages vim tree autofs net-tools apache httpdfor i in $packages;dorpm -q $i /dev/null || yum -q -y install $i done }#disable_firewall_selinux.sh文件调用disable_firewall_selinux函数 [rootcentos8_3 scripts]#cat disable_firewall_selinux.sh #!/bin/bash . functions #引用functions文件disable_firewall_selinux#yum_repo.sh文件调用yum_repo函数 [rootcentos8_3 scripts]#cat yum_repo.sh #!/bin/bash . functionsyum_repo#install_package.sh文件调用install_package函数 [rootcentos8_3 scripts]#cat install_package.sh #!/bin/bash . functionsinstall_package 5.1.2 查看函数 #查看当前已定义的函数名 declare -F#查看当前已定义的函数定义 declare -f5.1.3 删除函数 格式: unset func_name5.2 函数调用 函数的调用方式 可在交互式环境下定义函数可将函数放在脚本文件中作为它的一部分可放在只包含函数的单独文件中 调用函数只有被调用才会执行通过给定函数名调用函数函数名出现的地方会被自动替换为函数代码 函数的生命周期被调用时创建返回时终止。 不过调用函数时如果函数内外有同名变量调用函数后会修改函数内外的变量类似于全局变量如果要使函数只修改函数内部的变量而不影响函数外的同名变量可以在函数内声明时加上local使其成为本地变量如local NAME1 5.2.1 交互式环境调用函数 交互式环境下定义和使用函数 5.2.2 在脚本中定义及使用函数 函数在使用前必须定义因此应将函数定义放在脚本开始部分直至shell首次发现它后才能使用调用函数仅使用其函数名即可 5.2.3 使用函数文件 例调用系统函数 [rootCentOS8 ~]#. /etc/init.d/functions [rootCentOS8 ~]#action you an me you an me [ OK ] [rootCentOS8 ~]#action you an medsadsad false you an medsadsad [FAILED]5.3 函数返回值 默认情况下我们使用exit 100会返回100但用在函数里会使整个脚本退出而不执行下面的代码。 因此使用return #返回值可只退出当前函数而不退出脚本不过只在函数中使用 函数的执行结果返回值 使用echo等命令进行输出函数体中调用命令的输出结果 函数的退出状态码 默认取决于函数中执行的最后一条命令的退出状态码 自定义退出状态码其格式为 return 从函数中返回用最后状态命令决定返回值 return 0 无错误返回 return 1-255 有错误返回 5.4 环境函数 类拟于环境变量也可以定义环境函数使子进程也可使用父进程定义的函数 定义环境函数 export -f function_name declare -xf function_name查看环境函数 export -f declare -xf5.5 函数参数 函数可以接受参数: 传递参数给函数在函数名后面以空白分隔给定参数列表即可如: testfunc arg1 arg2…在函数体中当中可使用$1 2 . . . 调用这些参数还可以使用 2...调用这些参数还可以使用 2...调用这些参数还可以使用 ∗ * ∗#等特殊变量 5.6 函数变量 变量作用域: 普通变量只在当前shell进程有效为执行脚本会启动专用子shell进程因此本地变量的作用范围是当前shell脚本程序文件包括脚本中的函数环境变量当前shell和子shell有效本地变量函数的生命周期;函数结束时变量被自动销毁 注意: 如果函数中定义了普通变量且名称和局部变量相同则使用本地变量由于普通变量和局部变量会冲突建议在函数中只使用本地变量 在函数中定义本地变量的方法 local NAMEVALUE5.7 函数递归 函数递归函数直接或间接调用自身注意递归层数可能会陷入死循环 基例确定值链条规律 递归示例阶乘 阶乘是基斯顿·卡曼于1808 年发明的运算符号是数学术语一个正整数的阶乘(factorial)是所有小于及等于该数的正整数的积并且有0的阶乘为1自然数n的阶乘写作n! n!1x2x3x…xn 阶乘亦可以递归方式定义: 0!1n!(n-1)!xn n!n(n-1)(n-2)…1 n(n-1)!n(n-1)(n-2)! 例递归实现阶乘 [rootCentOS8 functions]#cat fact.sh fact() {if [ $1 -eq 1 ];thenecho 1elseecho $[fact $[$1-1]*$1]fi } fact $1[rootCentOS8 functions]#bash fact.sh 5 120 fork炸弹是一种恶意程序它的内部是一个不断在 fork 进程的无限循环实质是一个简单的递归程序。由于程序是递归的如果没有任何限制这会导致这个简单的程序迅速耗尽系统里面的所有资源 参考:https://en.wikipedia.org/wiki/Fork_bomb 函数实现 :(){ :|: };: #无基例 bomb () {} bomb | bomb }; bomb脚本实现 cat Bomb.sh #!/bin/bash ./$0|./$0OOM内存溢出 6 其它脚本相关工具 6.1 信号捕捉 trap trap ‘触发指令’ 信号 ​ 进程收到系统发出的指定信号后将执行自定义指令而不会执行原操作 trap 信号 ​ 忽略信号的操作 trap ‘-’ 信号 ​ 恢复原信号的操作 trap -p ​ 列出自定义信号操作 trap finish EXIT ​ 当脚本退出时执行finish函数 例 [rootCentOS8 functions]#cat signal_trap1.sh trap echo Press ctrlc int quit #将int 和quit信号改为echo Press ctrlc trap -p for((i1;i10;i)) dosleep 1echo $i donetrap int #将int信号改为空即忽略 trap -p for((i11;i21;i )) dosleep 1echo $i donetrap - int #恢复int信号接下来遇到int信号将执行ctrlc trap -p for(( i21;i31;i)) dosleep 1echo $i done[rootCentOS8 functions]#bash signal_trap1.sh trap -- echo Press ctrlc SIGINT trap -- echo Press ctrlc SIGQUIT 1 ^CPress ctrlc 2 ^CPress ctrlc 3 ^CPress ctrlc 4 ^CPress ctrlc 5 ^CPress ctrlc 6 ^CPress ctrlc 7 ^CPress ctrlc 8 ^CPress ctrlc 9 ^CPress ctrlc 10 trap -- SIGINT trap -- echo Press ctrlc SIGQUIT ^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^[[A11 ^[[A12 ^[[A^[[A^[[A^C13 ^C^C^C^C^C^C^C^C^C^C^C14 15 16 17 18 19 20 trap -- echo Press ctrlc SIGQUIT 21 22 23 24 25 26 ^C6.2 创建临时文件 mktemp mktemp命令用于创建并显示临时文件可避免冲突 格式 mktemp [OPTION]... [TEMPLATE]说明TEMPLATEfilenameXXXX至少要出现三个 常见选项: -d 创建临时目录 -p DIR或--tmpdirDIR 指明临时文件所存放目录位置例 #默认放在tmp目录下 [rootCentOS8 functions]#mktemp /tmp/tmp.B9CHlgxwCL [rootCentOS8 functions]#mktemp /tmp/tmp.ur2MYKCZhU[rootCentOS8 ~]#mktemp -d tmpdirXXXX #在当前目录下生成临时目录 tmpdirqWDe [rootCentOS8 ~]#ll tmpdirqWDe -d drwx------ 2 root root 6 Aug 13 14:51 tmpdirqWDe例实现rm的进阶写法 [rootCentOS8 scripts]#cat rm2.sh DIRmktemp -d /tmp/trash-$(date %F_%H-%M-%S)XXXXX mv $* $DIR echo $* is move to $DIR[rootCentOS8 scripts]#bash rm2.sh 123 321 123 321 is move to /tmp/trash-2023-08-13_14-59-58BDIIO [rootCentOS8 scripts]#ls /tmp/trash-2023-08-13_14-59-58BDIIO/ 123 321 [rootCentOS8 scripts]#alias rm/data/scripts/rm2.sh [rootCentOS8 scripts]#touch 1 [rootCentOS8 scripts]#chmod x rm2.sh [rootCentOS8 scripts]#rm 1 1 is move to /tmp/trash-2023-08-13_15-05-24kBeQl6.3 安装复制文件 install 功能相当于cp、chmod、chown、chgrp等相关工具的集合 install命令格式 install [OPTION]... [-T] SOURCE DEST 单文件 install [OPTION]... SOURCE... DIRECTORY install [OPTION]... -t DIRECTORY SOURCE... insta11 [OPTION]... -d DIRECTORY...创建空目录选项: -m MODE默认755 #改权限 -o OWNER #改所有者 -g GROUP #改所属组 -d DIRNAME例 [rootCentOS8 ~]#ll cal.txt -rw-r--r-- 1 root root 0 Jul 28 19:29 cal.txt [rootCentOS8 ~]#install -m 666 -o joyce -g bin cal.txt /data/test.txt [rootCentOS8 ~]#ll /data/test.txt -rw-rw-rw- 1 joyce bin 0 Aug 13 15:12 /data/test.txt#创建空文件夹 [rootCentOS8 ~]#install -m 700 -o joyce -g daemon -d /data/testdir/ [rootCentOS8 ~]#ll -d /data/testdir/ drwx------ 2 joyce daemon 6 Aug 13 15:13 /data/testdir/6.4 交互式转化批处理工具 expect expect 是由 Don Libes 基于 TcI ( Tool Command Language )语言开发的主要应用于自动化交互式操作的场景借助 expect处理交互的命令可以将交互过程如ssh登录tp登录等写在一个脚本上使之自动化完成尤其适用于需要对多台服务器执行相同操作的环境中可以大大提高系统管理人员的工作效率 expect 语法: expect [选项] [ -c cmds ] [ [ -[fIb] ] cmdfile ] [ args ]常见选项: -c 从命令行执行expect脚本默认expect是交互地执行的 -d 可以输出输出调试信息示例: expect -c expect \n {send pressed enter\n} expect -d ssh.expexpect中相关命令 spawn 启动新的进程 expect 从进程接收字符串 send 用于向进程发送字符串 interact 允许用户交互 exp_continue 匹配多个字符串在执行动作后加此命令expect最常用的语法 tcl语言模式-动作 ) 单一分支模式语法只生效一次遇到hi输出后即结束 [rootcentos8 test]#expect expect1.1 expect hi {send You said hi\n} hahahixixi You said hi例非交互式发送文件至第二个主机自动输入yes和密码 #!/usr/bin/expect #注意不是bash spawn scp /etc/fstab 10.0.0.7:/data expect {yes/no { send yes\n,exp_continue }password { send 110420\n } } expect eof例非交互式自动登录至第二个ip主机自动输入yes和密码 [rootcentos8 scripts]#cat expect2 #!/usr/bin/expect spawn ssh 10.0.0.209 expect {yes/no { send yes\n;exp_continue }password { send 110420\n } } interact [rootCentOS8 scripts]#chmod x expect1.sh [rootCentOS8 scripts]#./expect1.sh spawn ssh 10.0.0.209 root10.0.0.209s password: hello Joyce! Nna Activate the web console with: systemctl enable --now cockpit.socketLast login: Sun Aug 13 15:48:51 2023 from 10.0.0.201 [rootcentos8_2 ~]#hostname centos8_2例带有参数的自动登录其他ip主机的脚本自动输入yes和密码 [rootCentOS8 scripts]#cat ./expect2.sh #!/usr/bin/expect set ip 10.0.0.209 set user root set password 110420 set timeout 10 spawn ssh $user$ip expect {yes/no { send yes\n;exp_continue }password { send $password\n } } interact #代表可以进行交互[rootCentOS8 scripts]#chmod x expect2.sh [rootCentOS8 scripts]#./expect2.sh spawn ssh root10.0.0.209 root10.0.0.209s password: hello Joyce! Nna Activate the web console with: systemctl enable --now cockpit.socketLast login: Sun Aug 13 15:49:06 2023 from 10.0.0.201例使用位置参数实现自动登录其他ip的主机 [rootCentOS8 scripts]#cat ./expect3.sh #!/usr/bin/expect set ip [lindex $argv 0] set user [lindex $argv 1] set password [lindex $argv 2] spawn ssh $user$ip expect {yes/no { send yes\n;exp_continue }password { send $password\n } } interact [rootCentOS8 scripts]#chmod x expect3.sh [rootcentos8 scripts]#./expect3 10.0.0.209 root 110420 spawn ssh roota10.0.0.7 roota10.0.0.209s password: Last login: wed Apr 29 15:34:14 2020 from 10.0.0.8例远程登陆主机并创建账号设置密码完了退出 #!usr/bin/expect set ip [lindex $argv 0] set user [lindex $argv 1] set password [lindex $argv 2] set timeout 10 spawn ssh $user$ip expect {yes/no { send yes\n;exp_continue }password{ send$password\n } } # ]#即登陆后输入内容前面的标识符 expect ]# { send useradd haha\n } expect ]# { send echo 110420 |passwd --stdin haha\n } send exit\n expect eof例在bash脚本里调用expect以远程登录主机并创建账号设置密码 [rootCentOS8 scripts]#cat ./expect5.sh #!/bin/bash ip$1 user$2 password$3 expect EOF set timeout 10 spawn ssh $user$ip expect {yes/no { send yes\n;exp_continue }password{ send$password\n } } # ]#即登陆后输入内容前面的标识符 expect ]# { send useradd haha\n } expect ]# { send echo 110420 |passwd --stdin haha\n } send exit\n expect eof EOF[rootCentOS8 scripts]#bash expect5.sh 10.0.0.209 root 110420例批量登录不同主机并创建用户设置密码 #!/bin/bash NET10.0.0 userroot password110420 for ID in 209 210;do #循环遍历不同IP的主机 ip$NET.$ID expect EOF set timeout 20 spawn ssh $user$ip expect {yes/no { send yes\n;exp_continue }password { send $password\n } } expect # { send useradd test\n } expect # { send exit\n } expect eof EOF done例批量登录不同主机并修改selinux为disabled #!/bin/bash NET10.0.0 userroot password110420 for ID in 209 210;do #循环遍历不同IP的主机 ip$NET.$ID expect EOF set timeout 20 spawn ssh $user$ip expect {yes/no { send yes\n;exp_continue }password { send $password\n } } expect # { send sed -i s/^SELINUXenforcing/SELINUXdisabled/ /etc/selinux/confiig\n } expect # { send setenforce 0\n } expect # { send exit\n } expect eof EOF done7数组 7.1 数组介绍 变量存储单个元素的内存空间 数组存储多个元素的连续的内存空间相当于多个变量的集合 数组名和索引 索引的编号从0开始属于数值索引索引可支持使用自定义的格式而不仅是数值格式即为关联索引bash4.0版本之后开始支持bash的数组支持稀疏格式(索引不连续) 7.2 声明数组 #普通数组可以不事先声明直接使用 declare -a ARRAY_NAME#关联数组必须先声明再使用 declare -A ARRAY_NAME注意两者不可相互转换 7.3 数组赋值 数组元素的赋值 一次只赋值一个元素 ARRAY_NAME[INDEX]VALUE例 [rootCentOS8 ~]#title[0]ceo [rootCentOS8 ~]#echo ${title} ceo一次赋值全部元素 ARRAY_NAME(VAL1 VAL2 VAL3...例 title(ceocoocto) num({0..10}) alpha({a..g}) file( *.sh )只赋值特定元素 ARRAY_NAME([0]VAL1 [3]VAL2 ...)交互式数组值对赋值 read -a ARRAY[rootCentOS8 ~]#read -a number 1 3 5 7 9 [rootCentOS8 ~]#echo ${number[*]} 1 3 5 7 9 [rootCentOS8 ~]#echo ${number[2]} 5 [rootCentOS8 ~]#echo ${number} 17.4 显示所有数组 显示所有数组 declare -a7.5 引用数组 引用数组元素 ${ARRAY_NAME[INDEX]} #如果省略[INDEX]表示引用下标为0的元素引用数组所有元素 ${ARRAY_NAME[*]} ${ARRAY_NAME[]}例 [rootCentOS8 ~]#NUM({1..5}) [rootCentOS8 ~]#echo ${NUM[3]} 4 [rootCentOS8 ~]#echo ${NUM[2]} 3 [rootCentOS8 ~]#echo ${NUM[*]} 1 2 3 4 5 [rootCentOS8 ~]#echo ${NUM[]} 1 2 3 4 5例 [rootCentOS8 ~]#read -a number 1 3 5 7 9 [rootCentOS8 ~]#echo ${number[*]} 1 3 5 7 9 [rootCentOS8 ~]#echo ${number[2]} 5 [rootCentOS8 ~]#echo ${number} 17.6 删除数组 删除数组中的某元素会导致稀疏格式 unset ARRAY[INDEX]例 [rootcentos8 ~]#echo $title[*]} ceo coo cto [rootcentos8 ~]#unset title[1] [rootcentos8 ~]#echo $ftitle[*]] ceo cto删除整个数组 unset ARRAY例: [rootcentos8 ~]#unset title [rootcentos8 ~]#echo ${title[*]} 7.7 数组数据处理 数组切片 ${ARRAY[]:offset:number} offset #要跳过的元素个数 number #要取出的元素个数{ARRAY[]:offset} #取偏移量之后的所有元素例 [rootcentos8 ~]#num({0..10}) [rootcentos8 ~]#echo ${num[*]:2:3} 2 3 4 [rootcentos8 ~]#echo ${num[*]:6} 6 7 8 9 10向数组中追加元素 ARRAY[${#ARRAY[*]}]value ARRAY[${#ARRAY[]}]value例 [rootCentOS8 ~]#num({0..10}) [rootCentOS8 ~]#echo ${num[2]} 2 [rootCentOS8 ~]#echo ${num[*]} 0 1 2 3 4 5 6 7 8 9 10 [rootCentOS8 ~]#num[11]11 [rootCentOS8 ~]#echo ${num[*]} 0 1 2 3 4 5 6 7 8 9 10 11 [rootCentOS8 ~]#echo ${#num[*]} 12 [rootCentOS8 ~]#num[${#num[*]}]12 [rootCentOS8 ~]#echo ${#num[*]} 13 [rootCentOS8 ~]#echo ${num[*]} 0 1 2 3 4 5 6 7 8 9 10 11 127.8 关联数组 declare -A ARRAY_NAME ARRAY_NAME([idx_namel]val1 [idx_name2]val2...注意:关联数组必须先声明再调用 例 [rootCentOS8 ~]#declare -A name [rootCentOS8 ~]#name[first]Tom [rootCentOS8 ~]#name[second]Jack [rootCentOS8 ~]#name[third]Case [rootCentOS8 ~]#echo ${name[first]} Tom [rootCentOS8 ~]#echo ${name[*]} Case Jack Tom [rootCentOS8 ~]#echo ${name[third]} Case7.9 范例 例生成包含10个随机数的数组并显示其中的最大值MAX和最小值MIN [rootCentOS8 test]#cat random1.sh #!/bin/bash declare -i min max declare -a nums for ((i0;i10;i));donums[$i]$RANDOM[ $i -eq 0 ] min${nums[0]} max${nums[0]} continue[ ${nums[$i]} -gt $max ] max${nums[$i]}[ ${nums[$i]} -lt $min ] min${nums[$i]} done echo All numbers are ${nums[*]} echo Max is $max echo min is $min[rootCentOS8 test]#bash random1.sh All numbers are 23203 6083 14719 18022 31925 25880 9039 10908 30266 23092 Max is 31925 min is 60838 字符串处理 8.1 字符串切片 基于偏移量取字符串 #返回字符串变量var的长度 ${#var}#返回字符串变量var中从第offset个字符后(不包括第offset个字符)的字符开始到最后的部分offset的取值在0到${#var}-1 之间(bash4.2后允许为负值) ${var:offset]#返回字符串变量var中从第offset个字符后(不包括第offset个字符)的字符开始长度为number的部分 ${var:offset:number}#取字符串的最右侧几个字符取字符串的最右侧几个字符注意: 冒号后必须有一空白字符 ${var: -length}#从最左侧跳过offset字符一直向右取到距离最右侧lengh个字符之前的内容即:掐头去尾 ${var:offset:-length}#先从最右侧向左取到length个字符开始再向右取到距离最右侧offset个字符之间的内容注意: -length前空格 ${var: -length:-offset}例 [rootCentOS8 test]#str123abc哇哦 [rootCentOS8 test]#echo ${#str} 8 [rootCentOS8 test]#echo ${str:5} c哇哦 [rootCentOS8 test]#echo ${str:5:2} c哇 [rootCentOS8 test]#echo ${str: -2} 哇哦 [rootCentOS8 test]#echo ${str:3:-2} abc [rootCentOS8 test]#echo ${str: -3:-1} #取倒数3个和倒数1个之间的2个 c哇基于模式取子串 从左往右 #其中word可以是指定的任意字符,自左而右查找var变量所存储的字符串中第一次出现的word删除字符串开头至第一次出现word字符串 (含) 之间的所有字符 ${var#*word}:#同上贪婪模式不同的是删除的是字符串开头至最后一次由word指定的字符之间的所有内容 ${var##*word}:例 [rootcentos8 ~]#filevar/log/messages [rootcentos8 ~]#echo ${file#*/} log/messages [rootcentos8 ~]#echo ${file##*/} messages从右往左 #其中word可以是指定的任意字符,功能自右而左查找var变量所存储的字符串中第一次出现的worc删除字符串最后一个字符向左至第一次出现word字符串 (含) 之间的所有字符 ${var%word*}#同上只不过删除字符串最右侧的字符向左至最后一次出现word字符之间的所有字符 ${var%%word*}例 [rootcentos8 ~]#file/var/log/messages [rootcentos8 ~]#echo ${file%/*} var/log [rootcentos8 ~]#echo ${file%%/*} var8.2 查找替换、 #查找var所表示的字符串中第一次被pattern所匹配到的字符串以substr替换之 ${var/pattern/substr}#查找var所表示的字符串中所有能被pattern所匹配到的字符串以substr替换之 ${var//pattern/substr}#查找var所表示的字符串中行首被pattern所匹配到的字符串以substr替换之 ${var/#pattern/substr}#查找var所表示的字符串中行尾被pattern所匹配到的字符串以substr替换之 ${var/%pattern/substr}8.3 查找并删除 #删除var表示的字符串中第一次被pattern匹配到的字符串 ${var/pattern}#删除var表示的字符串中所有被pattern匹配到的字符串 ${var//pattern}#删除var表示的字符串中所有以pattern为行首匹配到的字符串 ${var/#pattern}#删除var所表示的字符串中所有以pattern为行尾所匹配到的字符串 ${var/%pattern}8.4 字符大小写转换 #把var中的所有小写字母转换为大写 ${var^^}#把var中的所有大写字母转换为小写 ${var,,}例 [rootCentOS8 test]#echo $str 123abc哇哦 [rootCentOS8 test]#echo ${str^^} 123ABC哇哦9 高级变量 9.1 高级变量赋值 变量配置方法str 没有配置str 为空字符串str 已配置非为空字符串var${str-expr}varexprvarvar$strvar${str:-expr}varexprvarexprvar$strvar${strexpr}varvarexprvarexprvar${str:expr}varvarvarexprvar${strexpr}strexprvarexprstr 不变varstr 不变var$strvar${str:expr}strexprvarexprstrexprvarexprstr 不变var$strvar${str?expr}expr输出至stderrvarvarsstrvar${str:?expr}expr输出至stderrexpr输出至stderrvarsstr 例 [rootcentos8 ~]#titleceo [rootcentos8 ~]#name${title-oops} [rootcentos8 ~]#echo $name ceo[rootcentos8 ~]#title [rootcentos8 ~]#name${title-oops} [rootcentos8 ~]#echo $name[rootcentos8 ~]#unset title [rootacentos8 ~]#name$ftitle-oops} [rootcentos8 ~]#echo $name oops9.2 高级变量用法-有类型变量 Shell变量一般是无类型的但是bash Shell提供了declare和typeset两个命令用于指定变量的类型两个命令是等价的 declare [选项] 变量名选项 -r 声明或显示只读变量 -i 将变量定义为整型数 -a 将变量定义为数组 -A 将变量定义为关联数组 -f 显示已定义的所有函数名及其内容 -F 仅显示已定义的所有函数名 -x 声明或显示环境变量和函数相当于export -l 声明变量为小写字母 declare -l varUPPER -u 声明变量为大写字母 declare -u varlower9.3 变量间接引用 9.3.1 eval命令 eval命令将会首先扫描命令行进行所有的置换然后再执行该命令。该命令适用于那些一次扫描无法实现其功能的变量该命令对变量进行两次扫描因此后面必须跟命令 例1 [rootCentOS8 test]#CMDhostname [rootCentOS8 test]#$CMD CentOS8.Joyce.person1 [rootCentOS8 test]#echo $CMD hostname [rootCentOS8 test]#eval $CMD CentOS8.Joyce.person1例2 [rootCentOS8 test]#n10 [rootCentOS8 test]#for i in {1..$n};do echo $i;done {1..10} [rootCentOS8 test]#for i in eval echo {1..$n};do echo $i;done 1 2 3 4 5 6 7 8 9 109.3.2 间接变量引用 如果第一个变量的值是第二个变量的名字从第一个变量引用第二个变量的值就称为间接变量引用 variable1的值是variable2而variable2又是变量名variable2的值为value间接变量引用是指通过variable1获 得变量值value的行为 variablelvariable2 variable2valuebash Shell提供了两种格式实现间接变量引用 eval tempvar \$Svariable1 tempvar${!variable1}例 [rootCentOS8 test]#ceoname [rootCentOS8 test]#nameMe [rootCentOS8 test]#echo $ceo name [rootCentOS8 test]#echo $$ceo 7487ceo [rootCentOS8 test]#echo \$$ceo $name [rootCentOS8 test]#eval echo \$$ceo Me #或 [rootCentOS8 test]#echo ${!ceo} Me9.3.3变量引用reference [rootcentos8 ~]#cat test.sh #!/bin/bash ceoME titleceo declare -n ref$title [ -R ref ] echo reference echo $ref ceoJoyce echo $ref[rootcentos8 ~]#bash test.sh reference ME Joyce
http://www.pierceye.com/news/899546/

相关文章:

  • 创建网站开发公司公司做个网站
  • 做网站的工具+论坛html怎么自己做网站
  • 土木在线seo网站快速整站优化技术
  • 创造力网站设计建设有限公司网站
  • 如何做网站好看做h5小程序的网站
  • 济宁网站建设价格做网站公司深
  • ae成品免费下载网站申请一个app多少钱
  • 我想自己在网站上发文章 怎样做免费观看高清正能量直播下载
  • 做网站万网长春建站模板展示
  • 广州专业建网站公司福州网站制作
  • 西安烽盈网站建设郑州营销网站托管
  • 诸几建设银行网站怎么维护好网站
  • 深圳市国外网站建设简单html5网页设计
  • 网站制作公司西南城乡建设部网站首页
  • 网站名和域名能一样吗企业网站建设硬件
  • 德州做网站公司怎么开网店淘宝
  • 苏州做网站优化的电商定制开发
  • 广西庆海建设发展有限公司网站昆山有做网站的公司吗
  • 前端课程网站wordpress 微博登陆
  • asp怎么做网站适配开发公司安置房项目工程推进大会
  • 学做网站可以赚钱吗怎么批量修改wordpress文章内容
  • 写作网站vir上海博大园林建设发展有限公司网站
  • wordpress video gallery网站代码优化怎么做
  • 厦门网站设计品牌企业互联网门户网站建设
  • 做名片模板网站中文响应式网站
  • 用tornado做网站石家庄 外贸网站建设公司
  • 档案网站建设网页wordpress keyshot
  • 鞍山制作网站哪家好建设银行员工网站
  • 手机怎么提升网站流量品牌型网站成功案例图片
  • 网站视频主持人制作网站开发 质量管理