如何执行shell脚本
问题描述
- 接着上一篇简书继续分析关于脚本部分的
- 在该job中让其执行以下shell
#注意$script指的是一段脚本
SHELL_SCRIPT=test.sh
echo $script > $SHELL_SCRIPT
docker copy . $container:/var/app
docker exec -i $container sh -c "cd /var/app && chmod +x $SHELL_SCRIPT && sh $SHELL_SCRIPT"
#$script如下
#!/bin/bash
master_branch=$(git branch | grep master)
test_branch=$(git branch | grep test)
if [[ ! -n $master_branch -o ! -n $test_branch ]]; then
echo "分支不存在!";
exit 1;
fi
echo "分支存在!";
- 发现脚本报错:'[['出错
- sh 改成bash
chmod +x $SHELL_SCRIPT && bash $SHELL_SCRIPT
发现不报错,但是出现git not found - 将当前的conatiner从afaren/alpine-gradle 改成 node发现git不报错了但是执行结果却是分支存在
- 使用conatiner是node发现并提交一个包含所有分支的仓库却发现被echo出分支不存在
问题分析
Q1: 如何执行一个script文件?
-
A1: 执行方式可以大致分成两种:
- 第一种:形如
sh script.sh 或者 bash script.sh 或者 source script.sh
- 这种方式是使用一个命令运行一个shell脚本,因此这个脚本不需要具有可执行权限
- 但是需要保证当前的shell中有
sh 或者 bash 或者source指令
否则会报错 - 在这种情况下,对于script文件中可以不用书写第一行
#!/bin/**
,因为脚本一定会使用指令中确定的shell执行 - 此时外部的指令(sh bash)的优先级高于文件中的
#!/bin/bash
,换句话说当文件中定义的shell执行器类型不同于指令中的shell执行器,该shell文件还是会被使用指令中的执行器执行 - 指令中三种不同的shell区别
- sh:
- 包含命令少,因此可能会导致脚本中有些指令not found,并且在执行脚本文件的时候。
- 会开启一个新的子shell执行该脚本
- bash:
- 包含命令多
- 会开启一个新的子shell执行该脚本
- source
- 会在当前的shell执行该脚本
- 第二种:形如
./script.sh
- 要求该脚本一定是具备可执行权限的
- 并且脚本的执行器由脚本第一行的
#!
定义 - 如果没有在脚本中定义第一行
#!
,那么就会使用当前shell中的默认执行器执行脚本文件
- 也就是说,对于本例子中,根本没有必要在
docker exec -i $container sh -c "cd /var/app && chmod +x $SHELL_SCRIPT && sh $SHELL_SCRIPT"
我们希望使用sh执行脚本。
- 第一种:形如
Q2:那么使用sh执行脚本为什么会报错?使用bash就不会?
-
A2:因为
- bash和sh区别之一:bash的命令多于sh所以,有些命令bash可以执行,但是sh不可以,那么如何分辨呢?
- 可以使用:
sh -c "type **"
或者bash -c "type **"
如果返回值是**: not found
说明sh或者bash中没有这个指令,** is a shell keyword
说明有
- 可以使用:
- bash和sh还有一点区别:sh执行的时候某些指令如果file not found会在这句出现的时候停止,但是bash会继续执行下去(不是说sh是bash的严格模式)
- bash和sh区别之一:bash的命令多于sh所以,有些命令bash可以执行,但是sh不可以,那么如何分辨呢?
Q3:为什么git not found?
-
A3:我们使用的docker镜像主要分成两大类:
- 一种是正常的镜像
- 一种是alpine镜像:比较小,所有包含的功能少,最主要的体现就是没有
bash 和git
两种指令
Q4:既然shell脚本可以正常执行了,为什么无法echo出“分支不存在”这样正确的结果呢?
-
A4:首先看一下if判断语句,先保证两个变量都可以拿到想拿到的值,看看变量定义,使用
$()
包住指令拿到指令的标准输出,没问题。然后查看判断变量为空的操作是否正确。判断变量是否为空的操作有三种做法,我的判断变量是否为空的做法一定是错的:- 方法一:
if [ ! -n "$test_branch" ]
使用-n
但是请注意,变量一定要使用""
包裹住,将变量的值先变成一个字符串。 - 方法二:
if [ ! $test_branch ]
- 方法三:
if [ "$test_branch" = "" ]
- 方法一: