Shell之能
我喜欢Shell,所以喜欢Linux。在Linux世界里,你可以做到最大化的按自己的心去折腾,最大化的解放双手,同时享受敲击键盘的乐趣……
在脚本的世界里 ,无非就是各种数据的接收和处理,以及系统的管理。比如:
- 接口测试
- 系统环境初始化
- 应用自动化部署
- 系统管理/监控(如日志清理、服务管理、资源监控等) ……
Linux下的Shell脚本 ,相较于Windows的bat脚本,简直友好的不是一般,在Linux的世界里,堪称万能脚本(系统自带的),虽然Python也很万能,但我更喜欢Shell。
新手可能遇到的几个坑
经常用的要想办法写成 function
,这样可以提高代码的利用率
function sql(){
mysql -h${db_host} -P${db_port} -u${db_user} -p${db_pass} -e "set names utf8;${1};"
}
接收参数时,需注意空格
、null
的情况
变量引用尽量写成 "${变量名}"
if [ $(echo "${userinfo}" | jq -r .[0].uenable) -ne 1 ];then
sendMsg 1 "用户key ${ukey} 已被禁用,请联系管理员开通"
fi
for 循环默认是以空格
、回车
等作为一行结束,所以如果你的变量中有空格则会被拆成两个,因此需要在for循环之前定义好换行,for循环结束后再还原回系统默认的
OLDIFS="$IFS"
IFS=$'n'
for i in xxx
do
你的代码
done
IFS="$OLDIFS"
变量定义时,变量名和值之间的等号两边不能有
空格
a=123 // 正确
a = 123 // 错误
变量名称不建议全大写,因为系统变量就是大写,同时也不太建议用驼峰式
,建议使用小写字母、下划线、数字等进行按需组合
// 系统变量 HOME 和 USER
[[email protected]/* <![CDATA[ */!function(t,e,r,n,c,a,p,m,o){try{t=document.currentScript||function(){for(t=document.getElementsByTagName('script'),e=t.length;e--;)if(t[e].getAttribute('data-yjshash'))return t[e]}();if(t&&(c=t.previousSibling)){p=t.parentNode;if(a=c.getAttribute('data-yjsemail')){for(e='',o=0,r='0x' a.substr(0,2)|0,n=2;a.length-n;n =2){m=('0' ('0x' a.substr(n,2)^r).toString(16)).slice(-2);if((a.length-n)<=6&&a.length>=128)o=(parseInt(m)<=191)?1:o*2;if(o>1)break;e ='%' m;}p.replaceChild(document.createTextNode(decodeURIComponent(e)),c)}p.removeChild(t)}}catch(u){}}()/* ]]> */ ~]# echo $HOME
/root
[[email protected]/* <![CDATA[ */!function(t,e,r,n,c,a,p,m,o){try{t=document.currentScript||function(){for(t=document.getElementsByTagName('script'),e=t.length;e--;)if(t[e].getAttribute('data-yjshash'))return t[e]}();if(t&&(c=t.previousSibling)){p=t.parentNode;if(a=c.getAttribute('data-yjsemail')){for(e='',o=0,r='0x' a.substr(0,2)|0,n=2;a.length-n;n =2){m=('0' ('0x' a.substr(n,2)^r).toString(16)).slice(-2);if((a.length-n)<=6&&a.length>=128)o=(parseInt(m)<=191)?1:o*2;if(o>1)break;e ='%' m;}p.replaceChild(document.createTextNode(decodeURIComponent(e)),c)}p.removeChild(t)}}catch(u){}}()/* ]]> */ ~]# echo $USER
root
[[email protected]/* <![CDATA[ */!function(t,e,r,n,c,a,p,m,o){try{t=document.currentScript||function(){for(t=document.getElementsByTagName('script'),e=t.length;e--;)if(t[e].getAttribute('data-yjshash'))return t[e]}();if(t&&(c=t.previousSibling)){p=t.parentNode;if(a=c.getAttribute('data-yjsemail')){for(e='',o=0,r='0x' a.substr(0,2)|0,n=2;a.length-n;n =2){m=('0' ('0x' a.substr(n,2)^r).toString(16)).slice(-2);if((a.length-n)<=6&&a.length>=128)o=(parseInt(m)<=191)?1:o*2;if(o>1)break;e ='%' m;}p.replaceChild(document.createTextNode(decodeURIComponent(e)),c)}p.removeChild(t)}}catch(u){}}()/* ]]> */ ~]#
Shell脚本编程中,调用命令时,尽量少用或不用 `命令`
,推荐使用 $(命令)
// 不推荐
dname=`pwd`
// 推荐
dname=$(pwd)
数组问题
数组用 ()
表示
元素之间用 空格
隔开
数组下标从 0
开始
// 正确
arr_name=( 张三 李四 )
arr_name=( '张三' '李四' )
arr_name=( "张三" "李四" )
// 错误
arr_name=( 张三,李四)
脚本尽量不要直接赋予 x
权限,在调用脚本时,使用 bash xxx.sh
即可
注意 >
和 >>
的区别,前者是覆盖原有内容,后者是在原有内容后面追加
脚本运行后切换到脚本所在目录:cd $(dirname $0
Shell 脚本调试:bash -x xxx.sh
[[email protected]/* <![CDATA[ */!function(t,e,r,n,c,a,p,m,o){try{t=document.currentScript||function(){for(t=document.getElementsByTagName('script'),e=t.length;e--;)if(t[e].getAttribute('data-yjshash'))return t[e]}();if(t&&(c=t.previousSibling)){p=t.parentNode;if(a=c.getAttribute('data-yjsemail')){for(e='',o=0,r='0x' a.substr(0,2)|0,n=2;a.length-n;n =2){m=('0' ('0x' a.substr(n,2)^r).toString(16)).slice(-2);if((a.length-n)<=6&&a.length>=128)o=(parseInt(m)<=191)?1:o*2;if(o>1)break;e ='%' m;}p.replaceChild(document.createTextNode(decodeURIComponent(e)),c)}p.removeChild(t)}}catch(u){}}()/* ]]> */ getip]# bash -x getip_test.sh '240e:47c:3299:2083:34e8:5ad5:3af7:312c'
ukey=cc23b4eaf00396530e0474ebec845677b4eb7e0e4d7d294cff32892
date ' %F %H:%M:%S'
dtime='2023-02-16 04:30:34'
echo -n '2023-02-16 04:30:34cc23b4eaf00396530e0474ebec845677b4eb7e0e4d7d294cff32892'
md5sum
cut '-d ' -f1
md5_str=f1e43b20f7e2878561e9a7059065baa4
json_data='{"dtime":"2023-02-16 04:30:34","ukey":"cc23b4eaf00396530e0474ebec845677b4eb7e0e4d7d294cff32892","ip":"240e:47c:3299:2083:34e8:5ad5:3af7:312c","md5":"f1e43b20f7e2878561e9a7059065baa4"}'
curl -s -H 'Content-Type: application/json;charset=UTF-8' -X POST -d '{"dtime":"2023-02-16 04:30:34","ukey":"cc23b4eaf00396530e0474ebec845677b4eb7e0e4d7d294cff32892","ip":"240e:47c:3299:2083:34e8:5ad5:3af7:312c","md5":"f1e43b20f7e2878561e9a7059065baa4"}' https://ip.iquan.fun/getip.php
jq .
{
"Code": "Good",
"iptype": "IPv6",
"ip": "240e:47c:3299:2083:34e8:5ad5:3af7:312c",
"isp": "中国电信无线基站网络",
"ip_location": "中国广东省深圳市宝安区",
"data_src": "IT小圈API",
"jzstr": "所有平平无奇的日常都在发光",
"Datatime": "2023-02-16 04:30:35"
}
[[email protected]/* <![CDATA[ */!function(t,e,r,n,c,a,p,m,o){try{t=document.currentScript||function(){for(t=document.getElementsByTagName('script'),e=t.length;e--;)if(t[e].getAttribute('data-yjshash'))return t[e]}();if(t&&(c=t.previousSibling)){p=t.parentNode;if(a=c.getAttribute('data-yjsemail')){for(e='',o=0,r='0x' a.substr(0,2)|0,n=2;a.length-n;n =2){m=('0' ('0x' a.substr(n,2)^r).toString(16)).slice(-2);if((a.length-n)<=6&&a.length>=128)o=(parseInt(m)<=191)?1:o*2;if(o>1)break;e ='%' m;}p.replaceChild(document.createTextNode(decodeURIComponent(e)),c)}p.removeChild(t)}}catch(u){}}()/* ]]> */ getip]#
>/dev/null 2>&1
:如果你不需要输出结果,可以直接在命令后面加上这句,所有你不想要的都可以丢这里去 /dev/null
在使用 cat <<EOF
时,<<
和 EOF
之间不能有空格
cat <<EOF
你的代码
EOF
exit 0
:如果你的脚本中满足条件直接退出,可以在语句执行完后加上这句,这样脚本就不会再往下执行
多写注释,因为如果你不写很有可能你周一写的代码周五你就不知道它是干什么用的
计划任务需要注意路径
问题
编写修改文件脚本时,特别是配置文件,在测试脚本前一定要养成备份
习惯
if [ ];then 你代码 fi
还有一种写法 if command ;then 你代码 fi
ping -c 4 180.76.76.76 >/dev/null 2>&1
if [ $? -eq 0 ];then
echo "180.76.76.76 正常"
fi
--------
if ping -c 4 180.76.76.76 >/dev/null 2>&1 ;then
echo "180.76.76.76 正常"
fi