#(感叹号)/bin/bash和#(感叹号)/bin/sh的区别,source命令和exec命令(感叹号打不出来)

Linux脚本开头#!/bin/bash和#!/bin/sh是什么意思以及区别


一、含义


#!/bin/sh是指此脚本使用/bin/sh来解释执行,#!是特殊的表示符,其后面根的是此解释此脚本的shell的路径。


其实第一句的#!是对脚本的解释器程序路径,脚本的内容是由解释器解释的,我们可以用各种各样的解释器来写对应的脚本。


比如说/bin/csh脚本,/bin/perl脚本,/bin/awk脚本,/bin/sed脚本,甚至/bin/echo等等。


#!/bin/bash同理。


二、区别


GNU/Linux操作系统中的/bin/sh本是bash (Bourne-Again Shell) 的符号链接,但鉴于bash过于复杂,有人把bash从NetBSD移植到Linux并更名为dash (Debian Almquist Shell),并建议将/bin/sh指向它,以获得更快的脚本执行速度。Dash Shell 比Bash Shell小的多,符合POSIX标准。


Ubuntu继承了Debian,所以从Ubuntu 6.10开始默认是Dash Shell。


应该说,/bin/sh与/bin/bash虽然大体上没什么区别,但仍存在不同的标准。标记为#!/bin/sh的脚本不应使用任何POSIX没有规定的特性 (如let等命令, 但#!/bin/bash可以)。Debian曾经采用/bin/bash更改/bin/dash,目的使用更少的磁盘空间、提供较少的功能、获取更快的速度。但是后来经过shell脚本测试存在运行问题。因为原先在bash shell下可以运行的shell script (shell 脚本),在/bin/sh下还是会出现一些意想不到的问题,不是100%的兼用。


上面可以这样理解,使用man sh命令和man bash命令去观察,可以发现sh本身就是dash,也就更好的说明集成Debian系统之后的更改。


补充
脚本test.sh内容:
#!/bin/sh
source pcy.sh #pcy.sh并不存在
echo hello
执行./test.sh,屏幕输出为:
./test.sh: line 2: pcy.sh: No such file or directory
由此可见,在#!/bin/sh的情况下,source不成功,不会运行source后面的代码。
修改test.sh脚本的第一行,变为#!/bin/bash,再次执行./test.sh,屏幕输出为:
./test.sh: line 2: pcy.sh: No such file or directory
hello
由此可见,在#!/bin/bash的情况下,虽然source不成功,但是还是运行了source后面的echo语句。
但是紧接着我又试着运行了一下sh ./test.sh,这次屏幕输出为:
./test.sh: line 2: pcy.sh: No such file or directory
表示虽然脚本中指定了#!/bin/bash,但是如果使用sh 方式运行,如果source不成功,也不会运行source后面的代码。


Linux source命令:


通常用法:source filepath 或 . filepath


功能:使当前shell读入路径为filepath的shell文件并依次执行文件中的所有语句,通常用于重新执行刚修改的初始化文件,使之立即生效,而不必注销并重新登录。例如,当我们修改了/etc/profile文件,并想让它立刻生效,而不用重新登录,就可以使用source命令,如source /etc/profile。


source命令(从 C Shell 而来)是bash shell的内置命令;点命令(.),就是个点符号(从Bourne Shell而来)是source的另一名称。这从用法中也能看出来。


 


source filepath 与 sh filepath 、./filepath的区别:


    当shell脚本具有可执行权限时,用sh filepath与./filepath是没有区别的。./filepath是因为当前目录没有在PATH中,所有"."是用来表示当前目录的。


    sh filepath 会重新建立一个子shell,在子shell中执行脚本里面的语句,该子shell继承父shell的环境变量,但子shell是新建的,其改变的变量不会被带回父shell,除非使用export。


    source filename其实只是简单地读取脚本里面的语句依次在当前shell里面执行,没有建立新的子shell。那么脚本里面所有新建、改变变量的语句都会保存在当前shell里面。


 


举例说明:


    新建一个test.sh脚本,内容为:A=1;


    修改其可执行权限:chmod +x test.sh;


    运行sh test.sh后,echo $A,显示为空,因为A=1并未传回给当前shell;


    运行./test.sh后,也是一样的效果;


    运行source test.sh 或者 . test.sh,然后echo $A,则会显示1,说明A=1的变量在当前shell中;


Linux中exec命令相关:

exec和source都属于bash内部命令(builtins commands),在bash下输入man exec或man source可以查看所有的内部命令信息。
  bash shell的命令分为两类:外部命令和内部命令。外部命令是通过系统调用或独立的程序实现的,如sed、awk等等。内部


命令是由特殊的文件格式(.def)所实现,如cd、history、exec等等。


  在说明exe和source的区别之前,先说明一下fork的概念。


  fork是linux的系统调用,用来创建子进程(child process)。子进程是父进程(parent process)的一个副本,从父进程那里


获得一定的资源分配以及继承父进程的环境。子进程与父进程唯一不同的地方在于pid(process id)。


  环境变量(传给子进程的变量,遗传性是本地变量和环境变量的根本区别)只能单向从父进程传给子进程。不管子进程的环境


变量如何变化,都不会影响父进程的环境变量。


  shell script:


  有两种方法执行shell scripts,一种是新产生一个shell,然后执行相应的shell scripts;一种是在当前shell下执行,不


再启用其他shell。


  新产生一个shell然后再执行scripts的方法是在scripts文件开头加入以下语句


  #!/bin/sh


  一般的script文件(.sh)即是这种用法。这种方法先启用新的sub-shell(新的子进程),然后在其下执行命令。


  另外一种方法就是上面说过的source命令,不再产生新的shell,而在当前shell下执行一切命令。


  source:


  source命令即点(.)命令。


  在bash下输入man source,找到source命令解释处,可以看到解释”Read and execute commands from filename in the


current shell environment and …”。从中可以知道,source命令是在当前进程中执行参数文件中的各个命令,而不是另起子


进程(或sub-shell)。


  exec:


  在bash下输入man exec,找到exec命令解释处,可以看到有”No new process is created.”这样的解释,这就是说exec命


令不产生新的子进程。那么exec与source的区别是什么呢?


  exec命令在执行时会把当前的shell process关闭,然后换到后面的命令继续执行。


 


系统调用exec是以新的进程去代替原来的进程,但进程的PID保持不变。因此,可以这样认为,exec系统调用并没有创建新的


进程,只是替换了原来进程上下文的内容。原进程的代码段,数据段,堆栈段被新的进程所代替。


  一个进程主要包括以下几个方面的内容:


  (1)一个可以执行的程序


  (2) 与进程相关联的全部数据(包括变量,内存,缓冲区)


  (3)程序上下文(程序计数器PC,保存程序执行的位置)

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
#!/bin/sh 和 #!/bin/bash 是脚本文件的特殊注释行,用于指定解释器执行脚本。 #!/bin/sh 是指定使用默认的shell解释器来执行脚本,通常是Bourne shell或其兼容版本。 而#!/bin/bash 则指定使用Bash shell来执行脚本。 在引用,将mybash_1.sh的第一行改为#!/bin/sh,然后执行脚本时,会使用默认的shell解释器执行脚本。而在引用和引用,将脚本的第一行改为#!/bin/bash,这样执行脚本时会使用Bash shell来解释执行脚本。 需要注意的是,在引用提到的/bin/sh相当于/bin/bash --posix,这意味着将使用Bash shell的posix模式来解释执行脚本。而在引用提到,当执行完source命令时并没有继续执行,这是因为脚本的#!/bin/bash这一行只是一个注释,并没有起到指定解释器的作用。 所以,使用不同的注释行可以指定不同的shell解释器来执行脚本,这也会影响脚本的执行结果和行为。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [#!/bin/bash和#!/bin/sh区别](https://blog.csdn.net/qianniuwei321/article/details/126428896)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [关于#!/bin/bash和#!/bin/sh详细解析](https://blog.csdn.net/ankang654321/article/details/88698880)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值