【linux】编写linux脚本
1、linux shell种类
- Bourne Shell(/usr/bin/sh或/bin/sh)
- Bourne Again Shell(/bin/bash)
- C Shell(/usr/bin/csh)
- K Shell(/usr/bin/ksh)
- Shell for Root(/sbin/sh)
其中/bin/bash是免费的所以用的最多,一般情况不区分 Bourne Shell 和 Bourne Again Shell
2、shell脚本
首先脚本如果是用的shell写的,后缀就是.sh,如果是php写的,就是.php,
然后执行之前要赋予执行的权限,最后用/bin/sh 文件名就好了(最好还是用/bin/bash 使用过程发现数组声明用/bin/sh会报错)
touch test.sh
chmod +x ./test.sh //注意这里要写明路径,不然就会去默认的path路径里找文件了
/bin/sh test.sh
或者 ./test.sh
3、编写shell脚本
3.1、shell变量
局部变量和全局变量
printenv 或者 echo $变量名 :查看全局变量的命令
set :查看局部变量的命令
变量名=变量值:声明局部变量
export 变量名:将局部变量变为全局变量,注意:这里没有$
unset $环境变量名 :删除环境变量名
声明的环境变量可以在子进程中使用,但是子进程声明的全局环境变量是不能影响到父进程的。
变量声明和赋值
name="wcy" //名字可以加_,但是不能用bash的关键字
echo $name #单引号就是原样输出,即输出$name,如果是要输出命令结果,可以用 $(命令) 或者 ``
name="123"
echo "my name is ${name}" #加不加{}其实都可以,方便识别的
for file in $(ls -l); do #shell命令加 $()
echo $file
done
readonly name
echo name
unset name //删除变量
#字符串
str='my name is wcy' #单引号只能原样输出
str="my name is \"${name}\" !\n" #双引号可以输出变量,转义字符逻辑和Java一样
echo ${#str} #输出字符串长度
echo ${str:1:4} #输出字符串1-4位 和java逻辑一样
#数组
num=(1 2 3 4) #数组比较特别,用(),隔开是用的空格
valuen=${num[1]}
valuen=${num[@]} #获取数组所有元素
valuen=${num[*]} #获取数组所有元素
len=${#num[1]} #获取第一个元素长度
len=${#num[@]} #获取数组长度
# #注释单行
:<<!
批量注释,这个!可以换成其他符号
!
#参数扩展
${parameter:-word}
paramter存在,就是原值,否则就是word
${parameter:+word}
paramater存在,就会执行paramter word命令,否则就执行pamater命令
3.2、传递参数和运算符
脚本内传参
./temp.sh 1 2 : 这就相当于传递了两个参数
$0: 默认为执行的文件名,包括路径
$?: 这个是退出状态码,0代表正常结束
$#: 参数个数
$*: 所以参数以"$1 $2 … $n"的形式输出
$@:所有的参数以"$1" "$2" … "$n"形式输出
运算符
除了正常的+、-、*、/、%、=、、!=、==
注意:
1、数学表达式的计算需要使用 `expr 1 + 1` (注意这里是反引号,并且需要有空格) 命令或者 $[1 + 1] 这样的格式
2、*需要转义 变成\*才能用
还有
-eq:判断等于
-ne:判断不等于
-gt:大于
-ge:大于等于
-lt:小于
-le:小于等于
逻辑运算符:&& ||
与或非:-a、-o、!
字符串运算符
= :检测两个字符串是否相等,相等返回 true。[ $a = $b ] 返回 false。
!=:检测两个字符串是否不相等,不相等返回 true。[ $a != $b ] 返回 true。
-z: 检测字符串长度是否为0,为0返回 true。[ -z $a ] 返回 false。
-n:检测字符串长度是否不为 0,不为 0 返回 true。[ -n "$a" ] 返回 true。
$:检测字符串是否为空,不为空返回 true。[ $a ] 返回 true。
文件测试运算符
-b file
检测文件是否是块设备文件,如果是,则返回 true。 [ -b $file ] 返回 false。
-c file
检测文件是否是字符设备文件,如果是,则返回 true。 [ -c $file ] 返回 false。
-d file
检测文件是否是目录,如果是,则返回 true。 [ -d $file ] 返回 false。
-f file
检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。 [ -f $file ] 返回 true。
-g file
检测文件是否设置了 SGID 位,如果是,则返回 true。 [ -g $file ] 返回 false。
-k file
检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。 [ -k $file ] 返回 false。
-p file
检测文件是否是有名管道,如果是,则返回 true。 [ -p $file ] 返回 false。
-u file
检测文件是否设置了 SUID 位,如果是,则返回 true。 [ -u $file ] 返回 false。
-r file
检测文件是否可读,如果是,则返回 true。 [ -r $file ] 返回 true。
-w file
检测文件是否可写,如果是,则返回 true。 [ -w $file ] 返回 true。
-x file
检测文件是否可执行,如果是,则返回 true。 [ -x $file ] 返回 true。
-s file
检测文件是否为空(文件大小是否大于0),不为空返回 true。 [ -s $file ] 返回 true。
-e file
检测文件(包括目录)是否存在,如果是,则返回 true。 [ -e $file ] 返回 true。
输出重定向:
其实就三个:
< 从文件输入
> 从文件输出
<< 内联输出重定向,简单的来说就是指定一个标记来直接打印输出
例子
Shell中的 test 命令用于检查某个条件是否成立,它可以进行数值、字符和文件三个方面的测试。
就和上面的数字运算符等等就可以搭配使用了
num1=100
num2=100
if test $[num1] -eq $[num2]
then
echo '两个数相等!'
else
echo '两个数不相等!'
fi
或者不声明test 通过下面这样的方式,注意前方括号后面、后方括号前面都有空格
if [ 1 -lt 2 ]
then
echo
else
echo
fi
复合条件:
[ condition1 ] && [ condition2 ]
[ condition1 ] || [ condition2 ]
3.3、结构化命令
if-else
# 这里的if判断结果和java一样是true、false,如果后面接的是一个命令,是依据状态码的,如果返回是0,就是true,否则就是false
if command
then
commands
fi
或者
if command; then
commands
fi
# 还有就是
if command
then
commands
else
commands
fi
# 这里有个小技巧,就是上面这个结构语句的简写方式
if [ -z ""]
then
echo 0
else
echo 1
fi
可以写成下面这样:
[ -z "" ] && echo 0 || echo 1
if - then 高级用法:
1、(( expression )):支持test使用的标准数学运算符之外还有 ++、--、!、~、**、&、&&、|、||、<< 等,建议使用这个
2、[[ expression ]] :这个功能在于可以使用模式匹配,例如 if [[ $user == r*]]
循环
# for循环
for var in item1 item2 ... itemN
do
command1
command2
...
commandN
done
# while
while condition
do
command
done
# until
until condition
do
command
done
# case...esac
case 值 in
模式1)
command1
command2
...
commandN
break #和java一样
;;
模式2)
command1
command2
...
commandN
continue #和java一样
;;
esac
# 包含脚本
. filename # 注意点号(.)和文件名中间有一空格
或
source filename
被包含文件不需要显式的赋予可执行权限
4、写一个实用的脚本
#/bin/bash
#environment variable
source /etc/profile
#cpu
cpu_us=`vmstat | awk '{print $13}' | sed -n '$p'`
cpu_sy=`vmstat | awk '{print $14}' | sed -n '$p'`
cpu_id=`vmstat | awk '{print $15}' | sed -n '$p'`
cpu_sum=$(($cpu_us+$cpu_sy))
if(($cpu_sum >= 90))
then
msg="TIME:$(date +%F_%T)
HOSTNAME:$(hostname)
IPADDR:$(ifconfig |awk 'NR==2{print $2}')
MSG:CPU使用率过高!已经用了${cpu_sum}%"
echo $msg
vmstat | awk '{print $1,$13,$14,$15}' | sed -n '2,$p' > /test/tt.txt
/test/sendmail.py $msg
fi