Linux Shell脚本
一、Shell语法
1. 运行方式
A. 作为可执行文件:脚本保存到文件中(如:web-admin.sh),并切换到当前文件目录,赋予脚本执行权限chmod +x ./web-admin.sh,执行脚本./web-admin.sh;
附:linux下.表示当前目录,..表示父目录,./表示当前目录的全路径,如果运行某个可执行文件可用cd /usr/local/nginx/sbin && ./nginx或者绝对路径/usr/local/nginx/sbin/nginx;
B. 作为解释器参数:/bin/sh web-admin.sh,这种在脚本里第一行指定解释器信息会忽略。
2. 变量
A. 变量定义不能使用$符号,使用变量是在变量名前加$符号,最好带上花括号,有助于解释器识别变量的边界;
B. 变量名和等号之间不能有空格;
C. 完整的表达式要被反引号 ` ` 包含;
D. 双引号里可以有变量,还可以出现转义字符,但是单引号里变量是无效的,因为任何字符都会原样输出;
E. 引号中嵌套引号,可以使用\来转义。
3. 参数传递
A. 执行Shell脚本时,可向脚本传递参数,脚本内获取参数的格式为:$n,n代表数字,从1开始,1表示第一个参数,注意$0表示执行的文件绝对路径名。
4. 命令
A. echo:用于向窗口输出字符串文本;
B. printf:格式化输出文本;
C. test:检查条件是否成立。
D. eval:l执行变量中的命令,注意ssh 远程执行时使用双引号替代单引号,将命令发送之前替换对本地值;
5. 输入/输出重定向
A. n >> file:将文件描述符为n的文件以追加的方式重定向到file;
B. n >& m:将输出文件m和n合并。
6. if else流程控制
A. if中括号前后一定要加空格,当判断中的变量有可能为空时需要加双括号[[]];
B. -eq,-ne等比较符只能用于数字比较,字符串比较用==,!=等处理;
-gt(大于)、-eq(等于)、-lt(小于)、-ge(大于等于)、-le(小于等于)、-ne(不等于)
C. -d:判断目录是否存在;
-f:判断常规文件是否存在;
-z:判读字符串是否是空串。
# 如果文件夹不存在,创建文件夹 if [ ! -d "/myfolder" ]; then mkdir /myfolder fi
7. for循环语句
for var in item1 item2 ... itemN
do
command1
command2
...
commandN
done
8. 数组Array
A. 获取数组元素个数:${#array[@]} 或 ${#array[*]};
B. 获取数组所有元素:${array[@]} 或 ${array[*]};
C. 获取数组下标:${!array[@]} ;
D. 从数组n位置开始取m个元素:${array[@]:n:m} ;
E. 数组合并:new_array=(${array1[@]} ${array2[@]})
F. 对数组进行去重排序:array=($(echo ${array[@]} | sed 's/ /\n/g' | sort )) | uniq;
G. 数组转字符串:str=$(IFS=,; echo "${array[*]}");
H. 多行内容变数组:| xargs,将换行和空白变成空格的单行;
9. 键值对Map
A. shell数组只支持一维数组,并且没有map这种结构,实际是用关联数组来模拟的;
B. 声明格式:declare -A map,支持索引下标为字符串;
10. 函数
A. 函数定义格式:可以直接funname()定义不带参数
1 2 3 4 5 6 7 8 9 | [ function ] funname [()] { action; [return int;] } |
B. 函数调用:直接funname即可,所有函数需要先声明再调用,即将函数定义放在脚本开始位置
11. 特殊符号
A. $n 脚本的第n个参数值,n=1..9;
B. $? 执行上一个指令的返回值 (显示最后命令的退出状态,0表示没有错误,其他任何值表明有错误);
C. IFS 分隔符:如IFS='=',表示以等号分割;
12. 其他常见写法
A. shell远程执行命令:前提是配置ssh免密登陆,如:ssh root@ip "sh linux.sh; ip a",双引号必须有,否则第二个命令在本地执行,命令之间用分号来隔开;
B. 判读字符串是否以END字符开头:if [[ $str == END* ]],注意:通配符不能使用引号括起来,比较语句使用双中括号括起来;
C. 读取配置文件前15行内容:head -15 ./resource.txt | while read ip service,注意在管道符中操作全局变量会不生效,因为管道符是非内建指令,会创建子shell来运行命令,运行完就会销毁变量,故不推荐使用;
二、LInux输出重定向到文件和标准输出
1. Bash或Linux shell标准I/O流,程序输出进入标准输出流,错误消息进入标准错误流,默认情况下,输入流和错误流都打印在屏幕上;
A. 0-STDIN,标准输入流;
B. 1-STDOUT,标准输出流;
C. 2-STDERR,标准错误流;
2. 重定向标准输出流
A. 将命令输出(stdout)重定向到文件:command > file 或 command 1 > file;
B. 重定向标准错误流(stderr):command 2 > file;
C. 禁止在屏幕上显示错误信息:command 2 > /dev/null;
D. 将stderr重定向stdout并将错误信息发送到标准输出相同的文件:command > file 2&1;
E. 标识符限定输入:EOF表示自定义终止符。
注意:使用>时会将文件内容会覆盖,使用>>时文件内容追加。
三、常见错误
1. 错误一:shell脚本执行结果报$'\r': 未找到命令;
原因:脚本是使用VS Code编辑器编写的,查找是换行符的问题,注意是LF,而不是CRLF。
2. 错误二:/bin/bash^M: bad interpreter: No such file or directory
原因:脚本是使用Notepad++编辑器编写的,查找还是换行符的问题,注意是Unix,不是Windows。
四、使用举例
1. 检测网络是否ping通
1 2 3 4 5 6 7 8 9 | # 在内网下,DNS不能配置公网,否则Docker服务因为DNS解析巨慢 ping -c1 www.baidu.com if [ $? - ne 0 ]; then echo "当前环境判断为隔离内网环境" sed -ri '/(114.114.114.114|8.8.)/d' /etc/resolv .conf echo -e "#nameserver 114.114.114.114\n#nameserver 8.8.8.8" >> /etc/resolv .conf else echo "当前环境判断为可访问公网环境" fi |
2. Jenkins SpringBoot jar包启动脚本:sh web-admin.sh
#!/bin/bash PROJECT_PACKAGE=web-admin-0.0.1-SNAPSHOT.jar PATH_NAME=test/web-admin/web-admin # 删除文件 rm -rf /project/web/jar/$PROJECT_PACKAGE # 拷贝文件 cp /var/lib/jenkins/workspace/$PATH_NAME/target/$PROJECT_PACKAGE /project/web/jar/ # 切换路径 cd /project/web/jar/ pid=`ps -ef | grep $PROJECT_PACKAGE | grep -v grep | awk '{print $2}'` if [ -n "$pid" ] then # 杀死存在进程 kill -9 $pid fi # 避免项目启动之后被Jenkins杀掉 BUILD_ID=dontKillMe # 执行 nohup java -jar $PROJECT_PACKAGE --spring.profiles.active=test >> /project/web/log/web-admin.log 2>&1 & # echo 命令用于向窗口输出文本 echo "web-admin项目启动成功!"
3. MySQL全量备份脚本:定时任务生效就行
#!/bin/bash # mysqldump的路径 DUMP=/usr/bin/mysqldump # 数据库登录名 DB_USER=root # 数据库登录密码 DB_PASSWORD=password # 备份文件目录 BAK_DIR=/admin # 当前时间 DATE=`date +%Y%m%d%H%M` # 目录不存在就创建 if [ ! -d "$BAK_DIR" ]; then mkdir -p $BAK_DIR fi $DUMP -u$DB_USER -p$DB_PASSWORD --lock-all-tables --databases admin | gzip >$BAK_DIR/${DATE}.sql.gz # 只保留一周的备份数据 find $BAK_DIR -type d -mtime +7 -name "*.sql.gz" -exec rm -rf {} \; echo "数据库全量备份成功!"
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗
2020-01-02 SpringBoot 整合Shiro 集成Ehcache缓存