人生苦短,务必性感。
目录
说的再多,不如动手试试来的明白。
一、执行shell脚本方式多样化
Shell 就是一种脚本语言,我们编写完源码后不用编译,直接运行源码即可。
比如/home/bin/下有个脚本 test.sh
#!/bin/bash
echo "hello world!"
第一种,以绝对路径方式去执行shell脚本
test.sh无执行权限时,执行/home/bin/test.sh,执行失败
我们给脚本赋权,chmod +x tets.sh,再次执行/home/bin/test.sh,执行成功
去掉首行解释器,再次执行,执行失败
其实,以绝对路径方式去执行shell脚本,也可以使用`pwd`命令
注意:pwd前后的 ` 不是英文的单引号,
而是英文输入法下的“~”同一个按键下面的那个符号,就在键盘esc下面那个键
总结:使用绝对路径方式必须为脚本首行指定解释器,也要给脚本添加执行权限
---------------------------------------------------------------------------------------------------------
第二种,最常用的执行方式,sh test.sh
test.sh无执行权限时,执行sh test.sh成功,说明sh方式不需要脚本拥有执行权限
去掉第一行#!/bin/bash ,再执行sh test.sh,仍能成功,
说明这是将test.sh作为参数传给sh(bash)命令来执行的,所有不必再第一行指定解释器
总结:sh方式不必为脚本首行指定解释器,不必给脚本添加执行权限
---------------------------------------------------------------------------------------------------------
第三种,以. 或 source 执行脚本
当test.sh未赋予执行权限时,执行失败
我们给test.sh赋执行权限,再次执行成功了
我们去掉首行解释器,再次执行,也是成功的
如果用. test.sh执行脚本,需要注意:点号.
和文件名中间有一个空格
总结: . 或souece方式不必为脚本首行指定解释器,但必需给脚本添加执行权限
---------------------------------------------------------------------------------------------------------
第四种,以. / 执行脚本
这种必须进入脚本当前路径下,执行./test.sh,成功。这种执行方式必须给脚本赋下执行权限
使用./方式我们一般会在首行指定解释器,好让系统查找到正确的解释器
总结: ./方式必须为脚本首行指定解释器,也必需给脚本添加执行权限
---------------------------------------------------------------------------------------------------------
二、sh和bash区别
#!/bin/sh 和#!/bin/bash
#!是一个特殊标记,说明这是一个可执行的脚本,#!后面跟是脚本的解释器程序路径。
除了第一行,其他以#开头都表示注释。
那他们究竟有没有区别呢?
sh 遵循POSIX规范:“当某行代码出错时,不继续往下解释”。
bash 就算出错,也会继续向下执行。
简单说,sh是bash的一种特殊的模式,sh就是开启了POSIX标准的bash, /bin/sh 相当于 /bin/bash --posix
我们常用的Centos,/bin/sh都是指向/bin/bash的符号链接(其它Linux发行版本这里不做分析,没怎么使用过)
ln -s /bin/bash /bin/sh
看下图,其实 sh就是bash,我们man sh manbash也可以看出没啥区别,个人惯用#!/bin/bash
总结:随便用
三、如果脚本的首行指定的解释器不是#!/bin/bash呢
上面我们有说到,sh是一个shell,运行sh test.sh,表示我使用sh来解释这个脚本。
如果我运行./test.sh,它一般会查找脚本第一行是否指定了解释器,如果没指定,那么就用当前系统默认的shell(大多数linux默认是bash),如果指定了解释器,那么就将该脚本交给指定的解释器。
我们修改下test.sh代码
#!/usr/bin/python
print("Hello World")
那么你运行./test.sh,结果是Hello,但是如果你运行sh a.run,会报语法错误,
因为这是一个python脚本,sh看不懂。
有人提出疑问,
四、.sh不是shell脚本后缀吗?
其实,Linux系统不是通过扩展名来识别文件类型的,在Linux中,带有扩展名的文件,只能代表程序的关联,并不能说明文件是可以执行,
给Shell脚本加.sh后缀只是一种规范和习惯,后缀我们也可以随意命名,甚至不写后缀。
我们把test.sh改为test执行以下看看,仍能成功
五、切换路径的影响
脚本在/home目录下 ,test.sh内容为:
#!/bin/sh
cd /home/peim
pwd
ls -l
如果在/home下执行./test.sh 或者sh test.sh,可以看到/home/peim/下的内容,但shell退出后还是在原来的工作目录/home。
如果/home下执行source test.sh,可以看到/home/peim/下的内容,且shell退出后在目录/home/peim下。
六、进程问题
source
命令和 sh
命令的执行机制是不同的:
-
source
在当前 Shell 环境下来执行脚本文件中的内容 -
sh
重新开辟一个新的子Shell
,在子Shell
中执行脚本文件中的内容,执行完毕后再返回父Shell
。
什么意思呢,举一个非常简单的例子:
我们在test.sh脚本最后一行添加exit 0,再用sh 和source执行看一下
#!/bin/sh
cd /home/peim
pwd
ls -l
exit 0
使用sh或./执行,可以看出像什么都没发生一样,感觉加上exit 0也没有任何影响
我们再使用source执行一下,可以看到居然退出到登录界面了
补充:
子shell里面的变量父shell无法使用,对环境变量的修改也不影响父shell。
父shell中的局部变量,子shell无法使用,只有父shell的环境变量,子shell能够使用。
sh 创建子shell和当前的shell并行执行,子shell中执行,脚本设置的变量不会影响当前shell。
一旦子Shell中的执行完毕,此子Shell随即结束,回到父Shell中,不会影响父Shell原本的环境。
子Shell环境拥有与父Shell相同的环境变量、标准输入、输出、错误。
未完