【shell】shell编程总结
总结一下在写shell脚本时的常见注意事项:
1.shell脚本中的命令最好用命令的全路径,如果不知道全路径可以用which cmd查找命令的全路径。
2.shell脚本中定义环境变量用export xxx=/dir1/dir2.....
3.shell脚本中取变量所以变量前都需加$,或者最好是${变量}
4.掌握常见的if、for、case语法的使用方法
5.shell脚本中最好写清楚注释
6. shell脚本中善于使用函数
7.用 $? 来判断上一个shell命令的执行结果,返回值是0代表正常结束,返回值是其他则代表不正常
8. 将一些命令的执行结果重定向到/dev/null,错误结果也需要重定向到/dev/null (/dev/null是linux的无底洞,我们丢进去的东西就都找不回来了)
9.善于使用ps 加grep命令判断一些服务是否启动,根据是否有相应的进程判断对应的服务是否启动。
10 善于使用awk命令提取一些需要的信息
killUser.sh (输入登录的用户名,然后强制退出用户的脚本)
#!/bin/bash #input username and kill relactive process for kill user echo "please input username for kill" read username #if username is root ,exit if [ ${username} = 'root' ] then echo "root can not kill" exit 1 fi #get user PID PID=`/usr/bin/ps -aux | /usr/bin/grep qlq | /usr/bin/awk '$1="qlq" {print $2}'` for killpid in $PID do kill -9 $killpid done echo "killed ok!"
tomcat.sh (测试tomcat服务是否启动,开启、关闭tomcat)
#!/bin/bash #chkconfig: 2345 80 90 #description:tomcat #input(start stop status) to operate tomcat service #start funciton(start tomcat service use /opt/apache-tomcat/apache-tomcat-7.0.72/bin/start.sh) export CATALINA_HOME=/opt/apache-tomcat/apache-tomcat-7.0.72 start(){ /usr/bin/sh "${CATALINA_HOME}"/bin/startup.sh if [ "$?" != "0" ] then echo "service is not success start" else echo "service is success start" fi exit 1 } #stop function stop(){ /usr/bin/sh "${CATALINA_HOME}"/bin/shutdown.sh if [ "$?" != "0" ] then echo "service is not success stop" else echo "service is success stop" fi } #status function status(){ /usr/bin/ps -le | /usr/bin/grep java >/dev/null 2> /dev/null if [ "$?" != "0" ] then echo "service is not start" else echo "service is running" fi } #read input and dispose function input=${1} case ${input} in start) start ;; stop) stop ;; status) status ;; *) echo "please use {start to start tomcat,stop to stop tomcat,status to read tomcat status!}" esac
webmin.ssh (测试webmin服务是否启动、开启、关闭webmin服务)
#!/bin/bash #start webmin service start() { /etc/webmin/start >/dev/null 2> /dev/null if [ $? = '0' ] then echo "webmin is success start" fi } #stop webmin service stop() { /etc/webmin/stop > /dev/null 2> /dev/null if [ $? = '0' ] then echo "webmin is success stop" fi } #status webmin status() { /usr/bin/netstat -ano | /usr/bin/grep 10000 > /dev/null if [ $? != '0' ] then echo "webmin is not start" else echo "webmin is running" fi } ########read input############## str=$1 if [ ${str} = 'start' ] then start elif [ ${str} = 'stop' ] then stop elif [ ${str} = 'status' ] then status else echo "please use {start,stop,status}" fi
addUserBatch.sh (批量添加用户的脚本)
#!/bin/bash #adduser batch echo "please input username:" read username echo "please input number to create:" read number #start to create user for(( i=1;i<="${number}";i++ )) do /usr/sbin/adduser "${username}${i}" > /dev/null 2> /dev/null done #add finished echo "add OK!" echo "please input passwd for users" read password for(( i=1;i<="${number}";i++ )) do /usr/sbin/usermod -p "${password}" "${username}${i}" > /dev/null 2> /dev/null done
delUserBatch.sh (批量删除用户的脚本)
#!/bin/bash #delete user batch echo "please input username word to delete" read word #get All users like word* users=`/usr/bin/grep ${word} /etc/passwd | awk -F: -v word1=${word} 'index($1,word1)>0 {print $1}'` if [ "${users}" = '' ] then echo "user is does not exist!" exit 1 fi for username in ${users} do /usr/sbin/userdel -rf ${username} > /dev/null 2>/dev/null done if [ "0" = "$?" ] then echo "delete ok!" else echo "delete failed!" fi
补充: 关于一些其他shell 常有语法
1. 关于shell 脚本里面 <<EOT 和 <<EOF 的问题
无论EOT还是EOF,都只是一个标记,只要成对出现即可。 > 是覆盖, > 是追加。
[root@redisnode1 redis]# echo "new" > 11.txt [root@redisnode1 redis]# cat 11.txt new [root@redisnode1 redis]# cat > 11.txt << EOF > this > is > new > EOF [root@redisnode1 redis]# cat 11.txt this is new [root@redisnode1 redis]# cat >> 11.txt << EOT > this > is > new2 > EOT [root@redisnode1 redis]# cat 11.txt this is new this is new2
2. 关于dirname、basename、readlink 等用法以及获取一个文件的相对路径
(1) dirname、basename
从文件名剥离非目录的后缀。打印去除了/后面部分的NAME;如果NAME没有包含/,则输出'.'(表示当前目录)
[root@redisnode1 redis]# dirname /usr/local/bin/redis-cli /usr/local/bin [root@redisnode1 redis]# dirname test.sh . [root@redisnode1 redis]# dirname /root/redis/ /root
basename 用于用于获取文件名称,与dirname 相悖。
[root@redisnode1 redis]# basename test.sh test.sh [root@redisnode1 redis]# basename /root/redis/test.sh test.sh [root@redisnode1 redis]# basename /root/redis/ redis [root@redisnode1 redis]# basename . .
(2) readlink readlink是linux用来找出符号链接所指向的位置。如果是一个链接,返回其文件位置;如果不是连接,返回文件自身全路径
[root@redisnode1 redis]# ll /usr/bin/ | grep awk | grep '^l' lrwxrwxrwx. 1 root root 4 Jul 20 2021 awk -> gawk [root@redisnode1 redis]# readlink -f test.sh /root/redis/test.sh [root@redisnode1 redis]# readlink -f /usr/bin/awk /usr/bin/gawk
awk 是一个软连接,所以readlink 找到原文件; test.sh 返回文件自身。
(3) 例如一个shell 脚本获取其绝对路径
[root@redisnode1 /]# cat /root/redis/test.sh #!/bin/bash echo $0 echo "====1" #Absolute path to this script SCRIPT=$(readlink -f $0) #Absolute path this script is in SCRIPTPATH=$(dirname $SCRIPT) echo $SCRIPT echo $SCRIPTPATH path=$(cd `dirname $0`;pwd) echo $path [root@redisnode1 /]# sh /root/redis/test.sh /root/redis/test.sh ====1 /root/redis/test.sh /root/redis /root/redis [root@redisnode1 /]#
$0 表示当前运行的命令名, 如果是以绝对路径执行的 $0 还会携带目录名称。
$() 用于将命令的输出存为变量。比如 path=$(cd `dirname $0`;pwd) 等同于pwd 输出的路径存到path 变量中。