如何从另一个Shell脚本调用一个Shell脚本?


736

我有两个shell脚本a.shb.sh

如何b.sh在Shell脚本中调用a.sh


8
您能否提供一些细节:哪个OS和哪个Shell,或者您只是在原则上谈论该问题?示例代码也将有所帮助。
jsalonen 2011年

14
这实际上不是一个特定的问题,也没有显示出解决该问题的先前努力。
克里斯(Kris)2014年

1
我遇到的一个问题是b.sh没有可执行权限。检查可能是一件好事。
seth10

./例如,在脚本名称前添加:b.sh,使用:./b.sh
Benny

1
如果有人不断收到No such file or directory错误stackoverflow.com/a/2920431/1356559
Amr Lotfy

Answers:


955

您可以通过几种不同的方式来执行此操作:

  1. 使其他脚本可执行,#!/bin/bash在顶部添加一行,并将文件添加到$ PATH环境变量的路径。然后,您可以将其作为普通命令来调用;

  2. 或与调用它source的命令(别名.)是这样的:source /path/to/script;

  3. 或者使用bash命令来执行它:/bin/bash /path/to/script;

第一个和第三个方法将脚本作为另一个过程执行,因此另一个脚本中的变量和函数将不可访问。
第二种方法在第一个脚本的过程中执行该脚本,并从另一个脚本中提取变量和函数,以便可以从调用脚本中使用它们。

在第二种方法中,如果要exit在第二个脚本中使用,它将同样退出第一个脚本。第一种和第三种方法不会发生这种情况。


30
请记住,chmod a+x /path/to/file否则它将无法执行。仅适用于./script方法。
内森·利连塔尔

3
如果在DOS中创建了可执行文件,然后将其上载到Unix环境中,请记住要更改它们的格式/编码,然后将其上传到Unix环境-> dos2unix <脚本名称>
Abhishek Chatterjee 2014年

3
@cecemel 使用正常的后台运行语法,第一种和第三种方式可以是“异步”。
2015年

16
问题在于被调用脚本source中的一条exit语句也会退出您的...
Ohad Schneider

18
@ user528025 .不是的别名source,而是相反的别名。source是bash扩展,.可在任何POSIX兼容shell中使用。
Score_Under

207

看一下这个。

#!/bin/bash
echo "This script is about to run another script."
sh ./script.sh
echo "This script has just run another script."

4
假定script.sh与正在运行的脚本位于同一目录中。如果您想在其他地方调用脚本,您会说sh <path to script>/script.sh
Morgan Kenyon

32
这也使用两个 shell bashsh。即使sh事实上,bash它的行为也不一样。如果您正在使用,#!/bin/bash则可能要使用bash script.sh(或仅./script.sh使用该脚本的hashbang)。
马丁·图尔诺伊

1
即使将设置chmod +x为.sh文件,也保持获得拒绝权限的错误。有什么建议么?
isaac天气

@isaacweathers尝试chmod 777
Janac Meena

114

您可以通过两种方法来执行此操作。终端执行脚本:

#!/bin/bash
SCRIPT_PATH="/path/to/script.sh"

# Here you execute your script
"$SCRIPT_PATH"

# or
. "$SCRIPT_PATH"

# or
source "$SCRIPT_PATH"

# or
bash "$SCRIPT_PATH"

# or
eval '"$SCRIPT_PATH"'

# or
OUTPUT=$("$SCRIPT_PATH")
echo $OUTPUT

# or
OUTPUT=`"$SCRIPT_PATH"`
echo $OUTPUT

# or
("$SCRIPT_PATH")

# or
(exec "$SCRIPT_PATH")

所有这些对于带空格的路径都是正确的!!!


41
他们有什么区别?为什么一个,为什么另一个?
rocketspacer

。首选“ $ SCRIPT_PATH”
Harry Mumford-Turner

1
我可以补充一点,它们并不完全相同,例如sh“ $ SCRIPT_PATH”和bash“ $ SCRIPT_PATH”将不会运行#!/ usr / bin / expect脚本,而仅会运行“ $ SCRIPT_PATH”。
塔罗尔

58

我一直在寻找答案:

( exec "path/to/script" )

如前所述,exec在不创建新进程的情况下替换了外壳。但是,我们可以将其放在子外壳中,这是通过使用括号实现的。

编辑:其实( "path/to/script" )足够了。


11
这似乎令人费解。为什么不随便打电话呢/path/to/scriptexec在这里我根本不需要吗?
马丁·图尔诺伊

因为您不知道,所以也不需要该子外壳exec
卡雷尔·弗尔克

6
您将如何使用参数执行此脚本?
巴尔加夫

如果您仍要捕获子脚本的输出,请尝试$(source“ path / to / script”)
cmcginty


16

取决于。简而言之...如果您想在当前控制台上加载变量并执行,则可以source myshellfile.sh在代码上使用。例:

!#/bin/bash
set -x
echo "This is an example of run another INTO this session."
source my_lib_of_variables_and_functions.sh
echo "The function internal_function() is defined into my lib."
returned_value=internal_function()
echo $this_is_an_internal_variable

set +x

如果您只想执行一个文件,而唯一对您感兴趣的是结果,则可以执行以下操作:

!#/bin/bash
set -x
./executing_only.sh
sh i_can_execute_this_way_too.sh
bash or_this_way.sh
set +x

希望对您有帮助。谢谢。


2
请注意,这source是特定于bash的功能。标准bourne外壳仅具有.(例如. other_script.sh)。
马丁·图尔诺伊

15

您可以/bin/sh用来调用或执行另一个脚本(通过您的实际脚本):

 # cat showdate.sh
 #!/bin/bash
 echo "Date is: `date`"

 # cat mainscript.sh
 #!/bin/bash
 echo "You are login as: `whoami`"
 echo "`/bin/sh ./showdate.sh`" # exact path for the script file

输出为:

 # ./mainscript.sh
 You are login as: root
 Date is: Thu Oct 17 02:56:36 EDT 2013

1
当然,这将showdate.sh在/ bin / sh下而不是/ bin / bash下运行吗?
克里斯·瓦茨

我已经尝试使用“ /bin/sh ./showdate.sh”,“ /bin/bash ./showdate.sh”,“ ./showdate.sh”并运行文件:mainscript.sh并获得了相同的输出。
Ranjithkumar T

10

只需在命令行中添加您在终端中键入的任何内容即可执行脚本!
例如:

#!bin/bash
./myscript.sh &

如果要执行的脚本不在同一目录中,请使用脚本的完整路径。
例如:`/ home / user / script-directory /./ myscript.sh&


@Carpetsmoker &负责后台任务
Andrei Krasutski



8

如果您在同一目录中还有另一个文件,则可以执行以下操作:

bash another_script.sh

要么

source another_script.sh

要么

. another_script.sh

当您使用bash而不是时source,脚本不能更改父脚本的环境。该.命令是POSIX标准而source命令为更可读的bash同义词.(我喜欢source.)。如果您的脚本位于其他位置,请提供该脚本的路径。相对路径和完整路径都应该起作用。


5

最佳答案建议#!/bin/bash在要调用的子脚本的第一行中添加一行。但是,即使添加了shebang,在子shell中运行脚本并捕获输出也要快得多*

$(source SCRIPT_NAME)

当您想继续运行相同的解释器(例如,从bash到另一个bash脚本)并确保不执行子脚本的shebang行时,此方法有效。

例如:

#!/bin/bash
SUB_SCRIPT=$(mktemp)
echo "#!/bin/bash" > $SUB_SCRIPT
echo 'echo $1' >> $SUB_SCRIPT
chmod +x $SUB_SCRIPT
if [[ $1 == "--source" ]]; then
  for X in $(seq 100); do
    MODE=$(source $SUB_SCRIPT "source on")
  done
else
  for X in $(seq 100); do
    MODE=$($SUB_SCRIPT "source off")
  done
fi
echo $MODE
rm $SUB_SCRIPT

输出:

~ ❯❯❯ time ./test.sh
source off
./test.sh  0.15s user 0.16s system 87% cpu 0.360 total

~ ❯❯❯ time ./test.sh --source
source on
./test.sh --source  0.05s user 0.06s system 95% cpu 0.114 total

*例如,当病毒或安全工具在设备上运行时,执行新进程可能需要花费额外的100毫秒。



4
 #!/bin/bash

 # Here you define the absolute path of your script

 scriptPath="/home/user/pathScript/"

 # Name of your script

 scriptName="myscript.sh"

 # Here you execute your script

 $scriptPath/$scriptName

 # Result of script execution

 result=$?

1
带有空格的文件夹scriptPath或文件名不正确scriptName
Andrei Krasutski

3

假设新文件是“ / home / satya / app / app_specific_env”,文件内容如下

#!bin/bash

export FAV_NUMBER="2211"

将此文件引用附加到〜/ .bashrc文件

source /home/satya/app/app_specific_env

每当您重启机器或重新登录时,请echo $FAV_NUMBER在终端中尝试。它将输出值。

万一您想source ~/.bashrc在命令行中立即看到效果,以防万一。


3
chmod a+x /path/to/file-to-be-executed

那是我唯一需要的。一旦要执行的脚本由可执行这样,你(在我的情况下,至少)不需要像其他任何额外的操作sh./当您呼叫的脚本。

感谢@Nathan Lilienthal的评论


1

从其他文件导入功能存在一些问题。
首先:您不需要执行此文件可执行文件。最好不要这样做!只需添加

. file

导入所有功能。所有这些都好像它们是在文件中定义的一样。
第二:您可以使用相同的名称定义函数。它将被覆盖。这不好。您可以这样声明

declare -f new_function_name=old_function_name 

并且只有在此之后才导入。因此,您可以使用新名称调用旧函数。
第三:您只能导入文件中定义的完整功能列表。如果不需要,可以取消设置。但是,如果您在取消设置后重写函数,它们将会丢失。但是,如果您如上所述设置对它的引用,则可以在取消设置后使用相同的名称进行恢复。
最后通常,导入过程很危险,而不是那么简单。小心!您可以编写脚本来更轻松,更安全地执行此操作。如果仅使用部分功能(不是全部),最好将其拆分为不同的文件。不幸的是,这项技术在bash中效果不佳。以python和其他一些脚本语言为例,它既简单又安全。可以使用自己的名称仅部分导入所需的功能。我们都希望在下一个版本中,布什将具有相同的功能。但是现在我们必须写很多其他的鳕鱼才能做你想做的。


(欢迎SO!)作为用户普利文中最后一次出现在2011年,注定是难以理清的问题究竟是如何使外壳执行 a.sh 执行 b.sh (并继续执行 a.sh 如果不是命令否则),或字面上呼叫b.sh。(我的拼写检查程序没有抓住bush versions。)(您是否有人寻求帮助来帮助您进行英语语法?(有时是我希望的。))
greybeard

0

使用反引号。

$ ./script-that-consumes-argument.sh `sh script-that-produces-argument.sh`

然后获取生产者脚本的输出作为消费者脚本的参数。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.