使用“sh”和“source”有什么区别?

2024-10-11 08:36:00
admin
原创
212
摘要:问题描述:sh和有什么区别source?source: source filename [arguments] Read and execute commands from FILENAME and return. The pathnames in $PATH are used to fin...

问题描述:

sh和有什么区别source

source: source filename [arguments]
    Read and execute commands from FILENAME and return.  The pathnames
    in $PATH are used to find the directory containing FILENAME.  If any
    ARGUMENTS are supplied, they become the positional parameters when
    FILENAME is executed.

对于man sh

NAME
       bash - GNU Bourne-Again SHell

SYNOPSIS
       bash [options] [file]

COPYRIGHT
       Bash is Copyright (C) 1989-2004 by the Free Software Foundation, Inc.

DESCRIPTION
       Bash  is  an sh-compatible command language interpreter that executes commands read from the standard input or from a file.  Bash also incorporates
       useful features from the Korn and C shells (ksh and csh).

       Bash is intended to be a conformant implementation of the IEEE POSIX Shell and Tools specification (IEEE Working Group 1003.2).

解决方案 1:

当你调用source.(一个是另一个的别名。cmdsource不是 POSIX - 一种bashism )时,你将在当前shell 进程中加载​​并执行一个 shell 脚本。所以你可以

  • 读取源脚本中设置的变量,

  • 使用其中定义的函数。

  • 如果脚本执行此操作,甚至会执行 fork 和/或子进程。

当您调用 时sh,您将启动一个fork(子进程或子进程),该进程将运行 的新会话/bin/sh(通常是 的符号链接bash)。在这种情况下,子脚本设置的环境变量将在子脚本终止时被删除。

警告:可能是另一个sh符号链接 壳。

实际示例

例如,如果你想通过特定方式更改当前工作目录,你不能这样做

$ cat <<eof >myCd2Doc.sh
#!/bin/sh
cd /usr/share/doc
eof

$ chmod +x myCd2Doc.sh

这不会达到你所期望的效果:

$ cd /tmp
$ pwd
/tmp
$ ~/myCd2Doc.sh
$ pwd
/tmp

因为当前工作目录是环境的一部分并且将在子 shellmyCd2Doc.sh中运行。

但:

$ source ~/myCd2Doc.sh
$ pwd
/usr/share/doc

相同,声明一个函数:

$ cat >~/myCd2Doc.source <<eof
# Shell source file
myCd2Doc() {
    cd /usr/share/doc
}
eof

$ . ~/myCd2Doc.source
$ cd /tmp
$ pwd
/tmp
$ myCd2Doc
$ pwd
/usr/share/doc

看看mycd函数!(使用狂欢基于关联数组的完成)。

执行级别$SHLVL

$ cd /tmp
printf %b '#!/bin/bash
echo This is level $SHLVL.
' >qlvl.sh

$ bash qlvl.sh 
This is level 2.

$ source qlvl.sh 
This is level 1.

递归(当脚本从自身运行时)

$ cat <<"eoqlvl2" >qlvl2.sh 
#!/bin/bash

export startLevel recursionLimit=5
echo This is level $SHLVL started:${startLevel:=$SHLVL}.
(( SHLVL < recursionLimit )) && ./qlvl2.sh
eoqlvl2
$ chmod +x qlvl2.sh

$ ./qlvl2.sh 
This is level 2 started:2.
This is level 3 started:2.
This is level 4 started:2.
This is level 5 started:2.

$ source qlv2.sh 
This is level 1 started:1.
This is level 2 started:1.
This is level 3 started:1.
This is level 4 started:1.
This is level 5 started:1.

再远一点

$ sed '$a ps --sid $SID fw' qlvl.sh >qlvl3.sh
$ chmod +x qlvl3.sh 
$ export SID
$ read SID < <(ps ho sid $$)
$ echo $SID $$
8983 8983

(当前PID$$==进程 ID)与SID会话 ID)是相同的标识符。这并不总是正确的。)

$ ./qlvl3.sh 
This is level 2.
  PID TTY      STAT   TIME COMMAND
 8983 pts/10   Ss     0:00 /bin/bash
10266 pts/10   S+     0:00  _ /bin/bash ./qlvl3.sh
10267 pts/10   R+     0:00      _ ps --sid 8983 fw

$ . qlvl3.sh 
This is level 1.
  PID TTY      STAT   TIME COMMAND
 8983 pts/10   Ss     0:00 /bin/bash
10428 pts/10   R+     0:00  _ ps --sid 8983 fw

.是 的别名source。因此两个命令之间的唯一区别被slash取代space

最后一个测试:

$ printf %b '#!/bin/bash
echo Ending this.
sle' \n    'ep 1;exit 0
' >finalTest.sh

$ bash finalTest.sh 
Ending this.

$ source finalTest.sh
Ending this.

...您可能会注意到两种语法之间的不同行为。;-)

解决方案 2:

主要区别在于它们是在不同的进程中执行的。

因此如果你的source文件foo执行了cd,源 shell(例如终端中的交互式 shell)会受到影响(并且其当前目录将会改变)

如果你执行sh foo 不会cd影响源 shell,只有新创建的sh进程运行foo

阅读高级 Bash 脚本指南。

这种差异并非 Linux 所特有;每个 Posix 实现都会有这种差异。

解决方案 3:

正如其他人所提到的,当您运行时sh test.sh,对您的 shell 环境所做的任何更改test.sh在该过程结束后都不会保留。

test.sh不过,还请注意,当作为子进程执行(即使用)时,环境中未导出的任何元素(例如变量、别名和 shell 函数)都将无法供代码使用sh test.sh

例如:

$ cat > test.sh
echo $foo
$ foo=bar
$ sh test.sh
$ . test.sh
bar

示例 2:

lap@my-ThinkPad:~$ cat test.sh
#!/bin/sh
cd /etc
lap@my-ThinkPad:~$ sh test.sh 
lap@my-ThinkPad:~$ pwd
/home/savoury
lap@my-ThinkPad:~$ source test.sh 
lap@my-ThinkPad:/etc$ pwd
/etc
lap@my-ThinkPad:/etc$ 

解决方案 4:

source(或 . ) - 在当前 shell 内运行并改变其属性/环境。

sh执行 fork 并在子 shell 中运行,因此无法改变属性/环境。

例如

我的 shell 脚本是 -

elite12!rg6655:~/sh_pr [33]$ cat changeDir.sh
#!/bin/bash
cd /home/elt/rg6655/sh_pr/justdir
pwd
echo $$

我当前的 Shell -

elite12!rg6655:~/sh_pr [32]$ echo $$
3272

我当前 shell 的进程 ID 是 3272

使用源代码运行-

elite12!rg6655:~/sh_pr [34]$ source changeDir.sh
/home/elt/rg6655/sh_pr/justdir
3272
elite12!rg6655:~/sh_pr/justdir

观察两件事 - 1)进程 ID(3272)与我的 shell 相同,这确认源在当前 shell 中执行。2)cd 命令有效并且目录更改为 justdir。

使用sh运行-

elite12!rg6655:~/sh_pr [31]$ sh changeDir.sh
/home/elt/rg6655/sh_pr/justdir
13673
elite12!rg6655:~/sh_pr

在这种情况下,进程 ID(13673)不同而目录保持不变,这意味着它在不同的进程或子 shell 中运行。

解决方案 5:

当您使用 sh 命令执行程序时:

  • 您的终端将使用 sh 或 Bourne Shell 来执行该程序。

  • 由于 Bash 对自身进行了精确复制,因此会创建一个新进程。此子进程与其父进程具有相同的环境,只有进程 ID 号不同。(此过程称为分叉)

  • 您需要具有执行权限才能执行它(因为它是分叉的)

当您使用 source 命令时:

  • 使用默认解释器执行程序

  • 您在当前终端中执行该过程(从技术上讲,您的 *nix 命令被解释)

  • 由于该程序将在当前终端中执行,因此您无需授予其执行权限

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用