以任何方式退出bash脚本,但不退出终端


183

当我exit在shell脚本中使用command时,该脚本将终止终端(提示)。有什么方法可以终止脚本然后留在终端中?

我的脚本run.sh有望通过直接获取或从其他脚本获取来执行。

编辑:更具体,有两个脚本run2.sh作为

...
. run.sh
echo "place A"
...

run.sh作为

...
exit
...

当我通过运行它时. run2.sh,如果它在的exit代码行中命中run.sh,我希望它停在终端并停留在那里。但是使用exit,整个终端将关闭。

PS:我尝试使用return,但是echo代码行仍将执行...。


5
我真的真的真的要问:为什么在源脚本中使用exit?
伊格纳西奥·巴斯克斯

3
exit命令不应终止您的终端会话/登录。如果用于exit 0成功后终止脚本,则在运行脚本ex时:./test.sh应该会看到输出,但控制台将保持打开状态。
本·阿什顿

您可以使用该shell命令,该命令实际上会打开一个shell终端。但是我自己的经验是,这不会发生exit。退出通常将控制权交还给父脚本。
Willem Van Onsem 2012年

Answers:


258

“问题”实际上是您正在采购而不执行脚本。当您获取文件时,其内容将在当前shell中执行,而不是生成子shell。因此,包括退出在内的所有内容都会影响当前的shell。

exit您将要使用而不是使用return


2
这是我发现有帮助的另一种解释:askubuntu.com/a/53179/148337
3cheesewheel 2013年

尽管正确,但这不是一个很好的答案。它忽略了调用脚本可能声明了被调用脚本需要访问的变量或函数。更好地解释如何设置返回码,然后在runs.sh@ruakh 中对其进行处理,可以更好地解决此问题。
MikeSchinkel '16

5
如果函数是嵌套调用怎么办?即a呼叫b,b呼叫c,c希望立即退出a和b。
迈克尔

来源与复制粘贴几乎相同。最好使用它,sh <script>或者bash <script>如果您想运行脚本并在某个时候终止,则更好
peterchaula

42

是; 您可以使用return代替exit。它的主要目的是从shell函数返回,但是如果在source-d脚本中使用它,则它将从该脚本返回。

正如Bash参考手册》的第4.1节“ Bourne Shell Builtins”所述

     return [n]

使shell函数以返回值n退出。如果未提供n,则返回值是函数中最后执行的命令的退出状态。这也可以用于终止使用.(或source)内置函数执行的脚本的执行,返回n或脚本中执行的最后命令的退出状态作为脚本的退出状态。与RETURN陷阱关联的所有命令都在函数或脚本之后恢复执行之前执行。如果return在函数外部使用返回状态,则返回状态为非零,.或者在脚本执行期间不使用或返回状态source


3
return只能通过功能使用。如果你使用return并执行它作为一个shell脚本(如sh run.sh),bash将报告错误- return: can only 从一个函数返回”或来源script`
Tzunghsing王守业

@TzungsingDavidWong:您是否确实知道答案大部分来自官方参考手册?并且您引用的错误消息是否同意此答案,而不是您的主张?
ruakh

我不同意你的看法。我只想指出,return如果脚本作为shell脚本运行而不由来执行,则将无法正常工作。(或source)。顺便说一句,在哪里可以找到有关的文档source -d
Tzunghsing David Wong

9

. run2.sh可以使用sh run2.sh或来运行脚本,而不是使用来运行脚本。bash run2.sh

将启动一个新的子外壳程序,然后运行该脚本,然后在脚本结束时将其关闭,而另一个外壳程序处于打开状态。


如果是这样,那么为什么要第二个参数sh "." run2.sh呢?
2015年

@ H0WARD您是对的,我忘了删除圆点。我已经编辑了答案。
Viorel Mirea

1
OP明确指出源是一项要求。
乔纳森·诺伊菲尔德

3

您可以在return语句/命令之后添加一个额外的退出命令,以便它既可以从命令行执行脚本,又可以从终端进行采购,从而对两者都起作用。

脚本中的示例退出代码:

   if [ $# -lt 2 ]; then
     echo "Needs at least two arguments"
     return 1 2>/dev/null
     exit 1
   fi

exit当您在return命令之后获取脚本时,将不会调用带有命令的行。

执行脚本时, return命令给出错误。因此,我们通过将错误消息转发到来抑制错误消息/dev/null


3

其实,我认为您可能会对自己的追求感到困惑 run a script

如果您sh用来运行脚本,请说sh ./run2.sh,即使嵌入式脚本以exit,您的终端窗口仍将保留。

但是,如果您使用.source,则下标结束时,终端窗口也会退出/关闭。

有关更多详细信息,请参阅使用sh和之间有什么区别source


2

就像您在脚本run2.sh中放入运行功能一样。在bash tty中将run2.sh文件作为源文件时,可以在run内使用退出代码。如果赋予run函数退出脚本的权力,赋予run2.sh退出终结器的权力。然后,运行功能可以退出您的终止程序。

    #! /bin/sh
    # use . run2.sh

    run()
    {
        echo "this is run"
        #return 0
        exit 0
    }

    echo "this is begin"
    run
    echo "this is end"

无论如何,我同意卡兹(Kaz)的设计问题。


从文字上不清楚这个答案试图做什么,但是它当然不能解决眼前的问题。
路易斯·德索萨

2

我遇到了同样的问题,根据上面的答案,根据我的理解,最终对我有用的是:

  1. 有一个shebang行来调用预期的脚本,例如,

    #!/bin/bash用于bash执行脚本

我有两种shebang的脚本。因此,使用sh.不可靠,因为它会导致执行错误(例如,脚本无法完全运行而无法正常运行时)

因此,答案是

    • 确保脚本具有shebang,因此毫无疑问要使用它的处理程序。
    • chmod .sh文件,以便可以执行它。 (chmod +x file.sh)
    • 无需任何sh或直接调用.

      (./myscript.sh)

希望这可以帮助有类似问题的人。



1

正如其他人指出的那样,源脚本与执行脚本使用returnvs exit来保持同一会话打开是正确的。

这是一个相关的技巧,如果您想使用一个脚本来保持会话的打开状态,无论它是否是源代码。

以下示例可以直接foo.sh. foo.sh/ 一样运行,也可以像/ 一样来获取source foo.sh。无论哪种方式,它将在“退出”后保持会话打开。该$@字符串传递,这样函数可以访问外部脚本的参数。

#!/bin/sh
foo(){
    read -p "Would you like to XYZ? (Y/N): " response;
    [ $response != 'y' ] && return 1;
    echo "XYZ complete (args $@).";
    return 0;
    echo "This line will never execute.";
}
foo "$@";

最终结果:

$ foo.sh
$您要XYZ吗?(是/否):n
$。foo.sh
$您要XYZ吗?(是/否):n
$ |
(终端窗口保持打开状态并接受其他输入)

这对于在单个终端中快速测试脚本更改,同时在工作时将一堆废代码保持在main exit/ 下很有用return。它还可以使代码在一定意义上更轻便的(如果你有吨,可能会或可能不会被以不同的方式被称为脚本),虽然它更笨重只使用returnexit适当的地方。


0

如果您的终端仿真器没有,-hold您可以清理源脚本并使用以下命令保存终端:

#!/bin/sh
sed "s/exit/return/g" script >/tmp/script
. /tmp/script
read

否则你可以使用 $TERM -hold -e script


0

还要确保以期望的​​返回值返回。否则,如果您在遇到出口时使用exit,则它将从您的基本shell退出,因为source不会创建另一个进程(实例)。


0

要编写一个脚本,是安全要运行无论是作为shell脚本或来源为RC文件,脚本可以检查和比较$0,并$BASH_SOURCE和确定是否exit可以安全使用。

这是一个简短的代码片段

[ "X$(basename $0)" = "X$(basename $BASH_SOURCE)" ] && \
    echo "***** executing $name_src as a shell script *****" || \
    echo "..... sourcing $name_src ....."

-1

1)如果成功,退出0将从脚本中退出。

2)如果失败,则退出1将退出脚本。

您可以根据您的要求尝试以上两种方法。

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.