shell脚本简单教程

shell脚本教程

1 什么是shell脚本

Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁。Shell 既是一种命令语言,又是一种程序设计语言。Shell 脚本(shell script),是一种为 shell 编写的脚本程序。

1.1 开发环境

Shell 编程跟 JavaScript、php 编程一样,只要有一个能编写代码的文本编辑器和一个能解释执行的脚本解释器就可以了。
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)
  • ……
1.2 初步体验

程序开发一般都是以一个hello world 开始,这里我们也不免俗,新建一个test.sh的文件,写入内容如下:

#!/bin/bash
echo "Hello World !"

#! 是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行,即使用哪一种 Shell。echo 命令用于向窗口输出文本。
在linux上运行shell脚本,需要先将脚本文件更改为可执行。然后执行。

chmod +x ./test.sh  #使脚本具有执行权限
./test.sh  #执行脚本
1.3 语言学习的流程

语言学习的流程我这边总结了比较通用的步骤,这里一定存在一定的狭隘的看法,仅供参考。步骤如下:

1,变量的定义、语法、使用
2,运算符
3,流程控制(条件语句、循环语句)
4,函数的定义和使用
5,...
2 shell脚本基础语法
2.1 变量
# 什么是变量?
变量的概念基本上和初中代数的方程变量是一致的,只是在计算机程序中,变量不仅可以是数字,还可以是任意数据类型.
shell脚本中的变量一般只有两种:数字和字符串。
# 变量的定义
变量的定义有两种方式,直接赋值或者语句赋值。
a,直接赋值
my_name="zhangsan"  # 定义了一个值为zcw的变量,变量的名为my_name
my_age=30   # 定义了值为30的变量,变量名为my_age
需要注意:
1、命名只能使用英文字母,数字和下划线,首个字符不能以数字开头
2、中间不能有空格,可以使用下划线(_)
3、不能使用bash里的关键字
4、变量赋值语句等号两侧不能有空格,这点和其他开发语言不一样

b,语句赋值
dir_list=`ls`  # dir_list的值即为当前文件下全部文件和文件夹名称
需要注意:
1、ls为linux命令列出当前文件下全部文件和文件夹
2、这种linux命令需要使用(`)包括
# 变量的使用
shell脚本变量的使用和其他语言不同,如java、php、python、c、c++等都是直接引用变量名即可,shell脚本中是需要在变量名前加上($)符号的。
my_name="zhangsan"
echo $my_name
echo ${my_name}   
推荐使用第二种方式,加花括号是为了帮助解释器识别变量的边界,比如下面这种情况
echo "my name is $my_namei am ok!"
# 字符串
字符串的可以用单引号,也可以用双引号,也可以不用引号。一般不推荐不用引号。
这里主要说下单引号和双引号的区别。
a,单引号
1、单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的
2、单引号必须成对出现
b,双引号
1、双引号可用有变量
2、双引号可用出现转义字符

示例
your_name="runoob"
# 使用双引号拼接
greeting="hello, "$your_name" !"
greeting_1="hello, ${your_name} !"
echo $greeting  $greeting_1
# 使用单引号拼接
greeting_2='hello, '$your_name' !'
greeting_3='hello, ${your_name} !'
echo $greeting_2  $greeting_3
hello, runoob ! hello, runoob !
hello, runoob ! hello, ${your_name} !

字符串两个方法:
1、获取字符串长度
string="abcd"
echo ${#string} #输出 4
2、提取字符串
string="runoob is a great site"
echo ${string:1:4} # 输出 unoo
# 数组
bash支持一维数组、类似于 C 语言,数组元素的下标由 0 开始编号。
array_name=(value0 value1 value2 value3) #这是一个定义的数组

读取数组
${array_name[n]}  # n这里为实际的数字,范围为0——数组长度-1
2.2 运算符

shell运算符主要包括:

  • 算数运算符
  • 关系运算符
  • 布尔运算符
  • 字符串运算符
  • 文件测试运算符
    这里我简单讲解下算数运算、关系运算和逻辑运算。
    据名知意,算数就是计算,关系是进行比较的,逻辑就是与或非。
# 算数运算
原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk 和 expr,expr 最常用。如:
val=`expr 2 + 2`   # 前面讲过(`)是执行的linux命令
echo "两数之和为 : $val"
# 关系运算
关系运算符只支持数字,不支持字符串,除非字符串的值是数字。
注:
1、需要使用[]包括
2、也可使用test 替换掉[]
2.3 流程控制

主要是控制程序的执行,程序运行一般都是按照顺序执行的,不过也有特殊的,如其他语言中的异步、回调等,不过在shell中一般只考虑顺序执行即可。顺序执行时我们可用通过条件语句来控制程序等运行。
条件语句这里主要介绍下三种常见的:if语句、for循环、case...esac

# if语句
a=10
b=20
if [ $a == $b ]
then
   echo "a 等于 b"
elif [ $a -gt $b ]
then
   echo "a 大于 b"
elif [ $a -lt $b ]
then
   echo "a 小于 b"
else
   echo "没有符合的条件"
fi
# for语句
for loop in 1 2 3 4 5
do
    echo "The value is: $loop"
done

for file in `ls`
do
    echo file
done
# case...esac语句
echo '输入 1 到 4 之间的数字:'
echo '你输入的数字为:'
read aNum
case $aNum in
    1)  echo '你选择了 1'
    ;;
    2)  echo '你选择了 2'
    ;;
    3)  echo '你选择了 3'
    ;;
    4)  echo '你选择了 4'
    ;;
    *)  echo '你没有输入 1 到 4 之间的数字'
    ;;
esac
2.4 函数

一次定义多处使用。

funWithReturn(){
    echo "这个函数会对输入的两个数字进行相加运算..."
    echo "输入第一个数字: "
    read aNum
    echo "输入第二个数字: "
    read anotherNum
    echo "两个数字分别为 $aNum 和 $anotherNum !"
    return $(($aNum+$anotherNum))
}
funWithReturn
echo "输入的两个数字之和为 $? !"
3 ()、(())、[]、[[]]、{}的作用和区别
$()和 ` `  
在 bash shell 中,$( ) 与` ` (反引号) 都可用做命令替换用。
例如   
version=$(uname -r)和version=`uname -r`都可以是version得到内核的版本号
各自的优缺点:
1、`  ` 基本上可用在全部的 unix shell 中使用,若写成 shell script ,其移植性比较高,但反单引号容易打错或看错。
2、$()并不是所有shell都支持。
${ } 
${ }用于变量替换。一般情况下,$var 与${var} 并没有什么不一样,但是用 ${ } 会比较精确的界定变量名称的范围。
$[] $(()) 
$[]和$(())是一样的,都是进行数学运算的。支持+ - * / %(“加、减、乘、除、取模”)。但是注意,bash只能作整数运算,对于浮点数是当作字符串处理的。
[ ] 
为test命令的另一种形式,但要注意:
1.必须在左括号的右侧和右括号的左侧各加一个空格,否则会报错。
2.test命令使用标准的数学比较符号来表示字符串的比较,而用文本符号来表示数值的比较。
3.大于符号或小于符号必须要转义,否则会被理解成重定向。
(( ))及[[ ]] 
分别是[ ]的针对数学比较表达式和字符串表达式的加强版。

[[ ]]中增加模式匹配特效。
(( ))不需要再将表达式里面的大小于符号转义。
4 实际案例
# 案例1,关闭javaweb程序
#!/bin/bash  
name=$(lsof -i:80|tail -1|awk '"$1"!=""{print $2}')  
if [ -z $name ]  
then  
    echo "No process can be used to killed!"  
    exit 0  
fi  
id=$(lsof -i:8080|tail -1|awk '"$1"!=""{print $2}')  
kill -9 $id  
  
echo "Process name=$name($id) kill!"  
exit 0
# 案例2,云平台一键配置
#!/bin/bash
# 此脚本用于一键web环境及项目配置
# ver1.0

www="/home/wwwroot/default"
commands=(all ip lnmp web)

lnmpSetFun(){
    echo "修改lnmp配置信息"
    # php修改
    sed -i 's|proc_open,||' /usr/local/php/etc/php.ini && is_php=1 || is_php=0
    if test $is_php -eq 0
    then
        echo "lnmp尚未安装,lnmp配置失败!"
        exit
    fi
    sed -i 's|proc_get_status,||' /usr/local/php/etc/php.ini
    sed -i '/PHP_ADMIN_VALUE/d' /usr/local/nginx/conf/fastcgi.conf
    service php-fpm restart
    # nginx修改
    sed -i '/$query_string/d' /usr/local/nginx/conf/nginx.conf
    sed -i '/include enable/a\        location / {try_files $uri $uri/ /index.php?$query_string;}' /usr/local/nginx/conf/nginx.conf
    sed -i '/root/d' /usr/local/nginx/conf/nginx.conf
    sed -i '/index index/a\        root '"$www"'/public;' /usr/local/nginx/conf/nginx.conf
    service nginx restart
    echo "lnmp配置完成!"
}

webSetFun(){
    chmod -R 777 $www/storage && is_web=1 || is_web=0
    if test $is_web -eq 0
    then
        echo "注意!网站未放入或网站路径!网站配置失败!"
        exit
    fi
    chmod -R 777 $www/public
    cp /home/wwwroot/default/back.php $www/.env
    echo "网站配置完成!"
}

webIpFun(){
    read -p "请输入本机IP: " ip
    api_ip="http://${ip}"
    if [ -z $ip ]
    then
        echo "尚未输入IP,IP配置失败!"
        exit
    else
        sed -i '/baseUrl/d' $www/public/js/config.js
        sed -i '/commandUrl/d' $www/public/js/config.js
        sed -i '/^PLATFROM_CONFIG.title/i\PLATFROM_CONFIG.baseUrl = \"'"$api_ip"'\"' $www/public/js/config.js
        sed -i '/^PLATFROM_CONFIG.title/i\PLATFROM_CONFIG.commandUrl = \"'"$ip"'\"' $www/public/js/config.js
        sed -i '/APP_URL/d' $www/.env
        sed -i '/SERVER_URL/d' $www/.env
        sed -i '/^ADMIN_HTTPS/i\APP_URL='"$api_ip"'' $www/.env
        sed -i '/^ADMIN_HTTPS/i\SERVER_URL='"$api_ip"':8080/energy_command/' $www/.env
        echo "IP配置完成!"
    fi
}

case $1 in
    ${commands[0]})
        lnmpSetFun
        webSetFun
        webIpFun
        ;;
    ${commands[1]})
        webIpFun
        ;;
    ${commands[2]})
        lnmpSetFun
        ;;
    ${commands[3]})
        webSetFun
        ;;
    *)
        echo "输入指令不正确!"
        echo "正确格式为 \"./webset.sh cmd\""
        echo "其中cmd包含有all、ip、lnmp、web"
        echo "all为一键配置全部,按照说明书正常步骤执行完即可操作"
        echo "ip单配置后台及前台ip地址"
        echo "lnmp单配置lnmp服务"
        echo "web单配置web服务"
        ;;
esac
echo "配置完成,浏览器输入\"http://本机ip\"访问项目"

# 案例3,云平台项目部署
#!/bin/bash
# 此脚本用于一键部署web项目
# ver1.0

wwwPlat="/home/wwwroot/default"
wwwServer="/home/wwwroot/server"
platMoveFun(){
    if [ -e $wwwPlat ]
    then
        echo "~~~~"
    else
        `mkdir -p ${wwwPlat}`
    fi
    `tar -xzvf ./energy_cloud_platform.tar.gz -C ${wwwPlat}`
}

serverMoveFun(){
    if [ -e $wwwServer ]
    then
        `rm -rf ${wwwServer}/*`
    else
        `mkdir -p ${wwwServer}`
    fi
    `\cp ./energy_cloud/* ${wwwServer}`
}

echo "###一键部署web文件###"
serverMoveFun
platMoveFun
echo "部署完成!"
5 结语

我这里只是带着简单过了下shell脚本的一些常用语法,实际学习还需要进一步去看文档。
shell语言其实只是简单的基本操作语言,要让其发挥作用还需要深入学习下linux命令,课程中大家应该也看到了,其实很多地方都需要用到linux的命令获取到数据给我们的变量中让我们在进一步处理。
我对于shell的理解是,其实它就是对linux命令提供了更方便的操作和处理方式。
这里我在列下自己目前常用的linux命令。https://www.jianshu.com/p/7f68c0945f2f

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,634评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,951评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,427评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,770评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,835评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,799评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,768评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,544评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,979评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,271评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,427评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,121评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,756评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,375评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,579评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,410评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,315评论 2 352

推荐阅读更多精彩内容