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

Pra*_*een 669 bash shell

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

如何b.sh从shell脚本中调用a.sh

Som*_*ude 868

您可以通过以下几种方式执行此操作:

  1. 使另一个脚本可执行,#!/bin/bash在顶部添加行,并将文件所在的路径添加到$ PATH环境变量.然后你可以把它称为普通命令;

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

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

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

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

  • 记得`chmod a + x/path/to/file`或者它不会是可执行的.仅适用于./script方法. (24认同)
  • @ user528025` .`不是`source`的别名,而是另一种方式.`source`是一个bash扩展,而`.`适用于任何POSIX兼容的shell. (16认同)
  • `source`的问题是被调用脚本中的`exit`语句也将退出你的... (14认同)
  • 如果在Unix中创建可执行文件的格式/编码,然后将其上传到unix环境,请记住更改unix中可执行文件的格式/编码 - > dos2unix <script name> (3认同)
  • @cecemel第一种和第三种方式*可以通过使用普通的运行后语法来"异步". (3认同)
  • 另外,请注意,每个脚本的作用域是项目目录的顶层——如果`./.git/hooks/pre-commit` 有`source foo`,你最好有`./foo`! (2认同)
  • @OhadSchneider 在我的例子中,如果被调用的脚本退出,则需要退出脚本。 (2认同)
  • 如果您的两个脚本都位于同一目录中,但您仍然不确定[从哪里调用](https://en.wikipedia.org/wiki/Where_I%27m_Calling_From),那么您必须构建首先找到脚本目录`SCRIPT_DIRECTORY="$(dirname $(realpath "$0"))"`,然后调用它:`source $SCRIPT_DIRECTORY/script.sh`。 (2认同)

小智 195

看一下这个.

#!/bin/bash
echo "This script is about to run another script."
sh ./script.sh
echo "This script has just run another script."
Run Code Online (Sandbox Code Playgroud)

  • 这也使用*two*shells,`bash`和`sh`.即使`sh`实际上是'bash`,它的行为也不一样.如果你正在使用`#!/ bin/bash`那么你可能想使用`bash script.sh`(或者只是`./ script.sh`来使用那些脚本的hashbang). (27认同)
  • 这假定script.sh与正在运行的脚本位于同一目录中.如果你想在其他地方调用脚本,你会说`sh <path to script>/script.sh` (4认同)

And*_*ski 102

有几种方法可以做到这一点.终端执行脚本:

#!/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")
Run Code Online (Sandbox Code Playgroud)

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

  • 他们有什么不同?为什么一个,为什么另一个 (33认同)

Max*_*sca 56

我正在寻找的答案:

( exec "path/to/script" )
Run Code Online (Sandbox Code Playgroud)

如上所述,exec替换shell而不创建新进程.但是,我们可以将它放在子shell中,这是使用parantheses完成的.

编辑:其实( "path/to/script" )就够了.

  • 这看起来很复杂.为什么不用`/ path/to/script`来调用它?我觉得这里根本不需要`exec`? (9认同)
  • 你会如何用参数执行这个脚本? (6认同)

Shi*_*hah 32

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

bash another_script.sh
Run Code Online (Sandbox Code Playgroud)

或者

source another_script.sh
Run Code Online (Sandbox Code Playgroud)

或者

. another_script.sh
Run Code Online (Sandbox Code Playgroud)

当您使用bash代替时source,脚本不能改变父脚本的环境。该.命令是POSIX标准而source命令为更可读的bash同义词.(我喜欢source.)。如果您的脚本驻留在别处,只需提供该脚本的路径。相对路径和完整路径都应该有效。


Ran*_*r T 14

您可以/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
Run Code Online (Sandbox Code Playgroud)

输出将是:

 # ./mainscript.sh
 You are login as: root
 Date is: Thu Oct 17 02:56:36 EDT 2013
Run Code Online (Sandbox Code Playgroud)

  • 这肯定会在 /bin/sh 而不是 /bin/bash 下运行 `showdate.sh` 吗? (3认同)

小智 14

依赖于取决于.简单地说......如果你想在当前控制台上执行加载变量并执行,你可以使用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
Run Code Online (Sandbox Code Playgroud)

如果你只想执行一个文件,结果就是你唯一有趣的事情,你可以这样做:

!#/bin/bash
set -x
./executing_only.sh
sh i_can_execute_this_way_too.sh
bash or_this_way.sh
set +x
Run Code Online (Sandbox Code Playgroud)

我希望能帮助你.谢谢.

  • 请注意,`source`是特定于bash的功能.标准的bourne shell只有`.`(例如`.other_script.sh`). (2认同)

小智 10

只需添加一行就可以在终端中输入任何内容来执行脚本!
例如:

#!bin/bash
./myscript.sh &
Run Code Online (Sandbox Code Playgroud)

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


小智 9

首先,您必须包含您调用的文件:

#!/bin/bash
. includes/included_file.sh
Run Code Online (Sandbox Code Playgroud)

然后你像这样调用你的函数:

#!/bin/bash
my_called_function
Run Code Online (Sandbox Code Playgroud)


小智 8

简单的资源将帮助您.对于Ex.

#!/bin/bash
echo "My shell_1"
source my_script1.sh
echo "Back in shell_1"
Run Code Online (Sandbox Code Playgroud)


sub*_*arb 8

这对我有用,这是执行另一个脚本的主 sh 脚本的内容。

#!/bin/bash 
source /path/to/other.sh
Run Code Online (Sandbox Code Playgroud)


Abd*_*UMI 5

pathToShell="/home/praveen/"   
chmod a+x $pathToShell"myShell.sh"
sh $pathToShell"myShell.sh"
Run Code Online (Sandbox Code Playgroud)


Val*_*ero 5

 #!/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=$?
Run Code Online (Sandbox Code Playgroud)


Asq*_*qan 5

chmod a+x /path/to/file-to-be-executed
Run Code Online (Sandbox Code Playgroud)

那是我唯一需要的东西。一旦要执行的脚本像这样可以执行,您(至少在我的情况下)不需要任何其他额外的操作,例如sh./在调用脚本时。

感谢@Nathan Lilienthal 的评论


cmc*_*nty 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
Run Code Online (Sandbox Code Playgroud)

输出:

~ ??? 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
Run Code Online (Sandbox Code Playgroud)

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