bash ./xx.sh 与 bash -c './xx.sh' 区别
bash ./xx.sh
与 bash -c './xx.sh'
两者大家肯定肯用的是前者.或者用的最多的是: sh xx.sh
或者是 ./xx.sh
两种. 但是经常写复杂的代码或者是看别人写的代码. 就会出现这里比较复杂的调用方式. 我们来看看两者有什么区别.
bash ./xx.sh
理解
这个本质上与sh ./xx.sh
没有区别. 只是我们是使用bash解释器来运行我们指定的脚本文件: ./xx.sh
;
同时, 这里的第一个参数: ./xx.sh
就是要解释执行的脚本文件的路径. 如果有参数. 则可以写在后面部分. 比如: bash ./xx.sh param1 param2
我们写一个脚本:
echo "param1:$1,param2:$2"
使用执行命令: bash ./a.sh a b
输出:
param1:a,param2:b
小知识: 这里的文件名实际也可以直接写文件名.不用写
./
的前缀. 比如:bash a.sh a b
bash -c String
使用
我们看这个的man手册中的定义:
-c string If the -c option is present, then commands are read from string. If there are arguments after the string, they are assigned to the positional parame-
ters, starting with $0.
这个说明 -c
后面的string参数实际就是命令序列. 或者说其就是shell的文件内容本身.
比如我们可以这样写:bash -c 'ls'
这样还不能说明这个string是什么意思. 上面的string里面是命令序列. 比如这样写:
bash -c 'ls -lash;pwd'
以上的命令会先执行ls
命令,再执行pwd
命令.
上面这样写命令序列,可能还不是很好理解. 我们再把它写得更通用:
bash -c '
echo "hello world"
echo "pid:$$"
echo "`pwd`"
'
这样上面的string
就更符合我们所说的命令序列.
bash -c './xx.sh'
的真实含义
有了以上的背景后, 我们知道实际上 -c
参数后面的string是一个命令序列. 更直白的理解就是一个直接输入的shell
文件内容. 就像上面示例中有多行的例子一样.
那这里的./xx.sh
实际就是调用一个另外一个外部脚本命令的意思. 因此, 这里的这个脚本的调用. 和我们直接在终端里面输入 ./xx.sh 没有什么区别. 所以,这个文件使用这种执行方法的话,一定要有可执行权限.
另外这里还有一个特别之处: 这个实际是启动了两层的子shell.
- 首先:
String
中的内容就在一个子shell进程与环境中运行的. - 然后:
String
中的命令:./xx.sh
中又调用了一个shell脚本,必定会再启一个子shell进程.
我们可以使用如下的命令来进行测试:
bash -c 'echo "pid in bash -c: $$"; ./echo_pid.sh'
其中echo_pid.sh
文件的内容可以写成如下:
#!/bin/bash
echo "pid in echo_pid.sh:$$"
如果此时: echo_pid.sh
没有执行权限我们会得到如下的输出:
$bash -c 'echo "pid in bash -c: $$"; ./echo_pid.sh'
pid in bash -c: 3799
bash: ./echo_pid.sh: Permission denied
此时给echo_pid.sh
添加上执行权限后.再运行得到结果:
$bash -c 'echo "pid in bash -c: $$"; ./echo_pid.sh'
pid in bash -c: 3818
pid in echo_pid.sh:3819
我们再加一个命令来观察pid
: echo "root pid:$$" && bash -c 'echo "pid in bash -c: $$"; ./echo_pid.sh'
得到如下的输出:
root pid:3773
pid in bash -c: 3829
pid in echo_pid.sh:3830
可以看到. 我们所说的有三个shell环境.
总结
bash shellFile.sh
这个是直接解释执行文件shellFile.sh
的内容- `bash -c 'String' 是直接把Sring的内容当成脚本内容进行执行.
- 两种方法都可以给执行的脚本传递参数. 也就是直接写到
命令
或者shellFile.sh
参数后面.
需要注意的是:
bash a.sh a b
这个可以直接把参数传递进入到a.sh
中,且参数是以$1
开始编号的.bash -c "String" a b
这个是把参数传递给 String 命令. 如果我们写:bash -c './a.sh' a b
是无法把参数传递给a.sh
脚本. 需要这样写才可能:bash -c './a.sh "$@"' a b
- bash -c 后面传递的参数是以 $0编号的.
我们可以看如下的内容:
$bash -c 'echo "p1:$1";./a.sh "$@"' a 参数2
p1:参数2
param1:参数2,param2: