Shell脚本入门需要注意的几个问题

2023-06-15 15:14:56 浏览数 (1)

Shell之能

我喜欢Shell,所以喜欢Linux。在Linux世界里,你可以做到最大化的按自己的心去折腾,最大化的解放双手,同时享受敲击键盘的乐趣……

在脚本的世界里 ,无非就是各种数据的接收和处理,以及系统的管理。比如:

  • 接口测试
  • 系统环境初始化
  • 应用自动化部署
  • 系统管理/监控(如日志清理、服务管理、资源监控等) ……

Linux下的Shell脚本 ,相较于Windows的bat脚本,简直友好的不是一般,在Linux的世界里,堪称万能脚本(系统自带的),虽然Python也很万能,但我更喜欢Shell。


新手可能遇到的几个坑

经常用的要想办法写成 function,这样可以提高代码的利用率

代码语言:javascript复制
function sql(){
mysql -h${db_host} -P${db_port} -u${db_user} -p${db_pass} -e "set names utf8;${1};"
}

接收参数时,需注意空格null的情况

变量引用尽量写成 "${变量名}"

代码语言:javascript复制
if [ $(echo "${userinfo}" | jq -r .[0].uenable) -ne 1 ];then
sendMsg 1 "用户key ${ukey} 已被禁用,请联系管理员开通"
fi

for 循环默认是以空格回车 等作为一行结束,所以如果你的变量中有空格则会被拆成两个,因此需要在for循环之前定义好换行,for循环结束后再还原回系统默认的

代码语言:javascript复制
OLDIFS="$IFS"
IFS=$'n'
for i in xxx
do
你的代码
done
IFS="$OLDIFS"

变量定义时,变量名和值之间的等号两边不能有空格

代码语言:javascript复制
a=123  // 正确
a = 123  // 错误

变量名称不建议全大写,因为系统变量就是大写,同时也不太建议用驼峰式,建议使用小写字母、下划线、数字等进行按需组合

代码语言:javascript复制
// 系统变量 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脚本编程中,调用命令时,尽量少用或不用 `命令` ,推荐使用 $(命令)

代码语言:javascript复制
// 不推荐
dname=`pwd`

// 推荐
dname=$(pwd)

数组问题

数组用 () 表示

元素之间用 空格 隔开

数组下标从 0 开始

代码语言:javascript复制
// 正确
arr_name=( 张三 李四 )
arr_name=( '张三' '李四' )
arr_name=( "张三" "李四" )

// 错误
arr_name=( 张三,李四)

脚本尽量不要直接赋予 x 权限,在调用脚本时,使用 bash xxx.sh 即可

注意 >>> 的区别,前者是覆盖原有内容,后者是在原有内容后面追加

脚本运行后切换到脚本所在目录:cd $(dirname $0

Shell 脚本调试:bash -x xxx.sh

代码语言:javascript复制
[[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 之间不能有空格

代码语言:javascript复制
cat <<EOF
你的代码
EOF

exit 0 :如果你的脚本中满足条件直接退出,可以在语句执行完后加上这句,这样脚本就不会再往下执行

多写注释,因为如果你不写很有可能你周一写的代码周五你就不知道它是干什么用的

计划任务需要注意路径问题

编写修改文件脚本时,特别是配置文件,在测试脚本前一定要养成备份习惯

if [ ];then 你代码 fi 还有一种写法 if command ;then 你代码 fi

代码语言:javascript复制
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

0 人点赞