因为大部分的工作都是重复的,使用脚本会极大地提升自身工作效率。实际工作中有很长时间在使用shell做一些操作,平时也会写一些脚本简化自己的操作,但是基本都是命令的罗列,也就是顺序式编程,很低级。因此决定系统地学习一下shell编程更加提升自我效率。
运行shell脚本的两种方式
#! 是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行,即使用哪一种 Shell。
作为可执行程序
chmod +x ./test.sh #使脚本具有执行权限 ./test.sh #执行脚本
./的意思是在当前目录寻找test.sh文件,如果不加的话就回去PATH中找,通常都是找不到的。
作为解释器参数
/bin/sh test.sh /bin/php test.php
这种方式运行的脚本,不需要在第一行指定解释器信息(#!/bin/bash),写了也没用。
Shell 变量
定义变量 =
变量定义要满足如下规则:
- 命名只能使用英文字母,数字和下划线,首个字符不能以数字开头。
- 中间不能有空格,可以使用下划线(_)。
- 不能使用标点符号。
- 不能使用bash里的关键字(可用help命令查看保留关键字)。
使用变量 ${}
在变量名前加上$符号即可。特殊情况下需要在变量名外加上{}
for skill in Ada Coffe Action Java; do echo "I am good at ${skill}Script" done
这样做是为了识别变量边界。推荐做法~
只读变量 readonly
#!/bin/bash myUrl="http://www.google.com" readonly myUrl myUrl="http://www.github.com"
运行脚本得到如下结果:
/bin/sh: NAME: This variable is read only.
删除变量 unset
变量被删除后不能再次使用,将读不到任何相关值,不能删除只读变量。
变量类型
局部变量:
局部变量在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量。
环境变量 (/etc/profile、.bash_profile、/etc/bashrc、/etc/profile.d):
通常是放在以上文件中的变量,也可以使用export自己定义,但是只有写入文件的变量可以在当前shell断开后接着使用。
shell变量:
shell变量是由shell程序设置的特殊变量。shell变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了shell的正常运行。
Shell 字符串
单引号 ‘’
- 单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的
- 单引号字串中不能出现单独一个的单引号(对单引号使用转义符后也不行),但可成对出现,作为字符串拼接使用
双引号””
- 双引号里可以有变量
- 双引号里可以出现转义字符
字符串相关函数
获取字符串长度: ${#string}
提取子字符串: ${string:1:4} 从哪个字符开始截,截几位
string="runoob is a great site" echo ${string:1:4} # 输出 unoo
查找子字符串:
string="runoob is a great site" echo `expr index "$string" io` # 输出 4
Shell 数组
bash仅支持一维数组。
定义数组
array_name=(value0 value1 value2 value3) #或者 array_name=( value0 value1 value2 value3 ) #单独定义分量 array_name[0]=value0 array_name[1]=value1 array_name[n]=valuen ## 可以不使用连续的下标,而且下标的范围没有限制。
读取数组
# 一般格式 ${数组名[下标]} valuen=${array_name[n]} # 使用 @ 符号可以获取数组中的所有元素 echo ${array_name[@]} # 获取数组的长度 length=${#array_name[@]} #或者 length=${#array_name[*]} #单个元素长度 ${#array_name[n]}
注释
:<<EOF 注释内容... 注释内容... 注释内容... EOF # EOF可以用其他内容代替 :<<! 注释内容... 注释内容... 注释内容... !
实践Demo
向其他机器拷贝文件
#!/bin/bash echo "ready to cp $@ to all nodes >>>>>>>>>" if [ $# -lt 1 ];then echo "need files!" exit -1 fi for file in $@;do if [ ! -f $file ]; then echo "$file is not a file!" exit -1 fi done for i in notestorage026 notestorage027 notestorage028 notestorage029 notestorage030;do echo "start handle files for $i" for file in $@;do echo "start scp $file to $i" scp $file $i:/disk1/cloudstorage/ echo "scp $file to $i done" done done
启动其他机器的脚本
#!/bin/bash for i in notestorage026 notestorage027 notestorage028 notestorage029 notestorage030;do echo "start init $i" ssh -T $i <<'ENDSSH' cd /disk1/cloudstorage sh deploy-storeserver.sh #cd /disk1/cloudstorage/ServerCommons #sh my_deploy.sh ENDSSH echo "deploy $i done" done
参考
本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!