假设我现在在 bash shell 中并执行以下操作
[me@server]$ bash script.sh
q1)是否创建了一个新的子 bash 进程来执行该脚本?
如果我做了
[me@server]$ ./script.sh
q2)是否创建了一个新的子 bash 进程来执行该脚本?
q3) 那么这两种方法有什么区别?
答案1
你所做的不同之处在于,
使用sh
,你正在运行一个程序,它将interpret the lines in your script
像你在终端的交互提示中输入的那样,
使用 ./ 可以创建一个快捷方式,假设脚本就在你当前所在的目录中,并且它是可执行的(因为例如你发出了 chmod +x myscript.sh),
附加信息来自这回答 :
对于您的特定脚本,两种方式都可以工作,但 ./script.sh 需要执行和可读位,而 bash script.sh 只需要可读位。
权限要求不同的原因在于解释脚本的程序如何加载:
./script.sh 让您的 shell 像运行常规可执行文件一样运行该文件。shell 会自行分叉并使用系统调用(例如 execve)让操作系统在分叉的进程中执行该文件。操作系统将检查文件的权限(因此需要设置执行位)并将请求转发给程序加载器,后者查看文件并确定如何执行它。在 Linux 中,编译的可执行文件以 ELF 魔数开头,而脚本以 #!(哈希邦)开头。哈希邦标头表示该文件是一个脚本,需要由哈希邦后指定的程序进行解释。这允许脚本本身告诉系统如何解释该脚本。
使用您的脚本,程序加载器将执行 /bin/bash 并传递 ./script.sh 作为命令行参数。
bash script.sh 使您的 shell 运行 bash 并将 script.sh 作为命令行参数传递,因此操作系统将加载 bash(甚至不会查看 script.sh,因为它只是一个命令行参数)。然后,创建的 bash 进程将解释 script.sh,因为它是作为命令行参数传递的。由于 script.sh 仅由 bash 作为常规文件读取,因此不需要执行位。
答案2
- 创建一个子 bash 进程
- 与上面相同(由于 shebang)
这两个是等效的,如果你不想 fork 子进程,或者想保留环境值
script.sh
,请使用. ./script.sh
但要小心
- 如果
script.sh
调用exit,你将退出当前shell。 - 如果 shell 结束时没有错误,您将返回到初始 shell。