bash ./xx.sh 与 bash -c './xx.sh' 区别

  |   0 评论   |   550 浏览

bash ./xx.shbash -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:

评论

发表评论


取消