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

时间:2012-03-09 20:38:24

标签: linux bash

当我在shell脚本中使用exit命令时,脚本将终止终端(提示)。有没有办法终止脚本然后留在终端?

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

编辑: 更具体地说,有两个脚本run2.sh

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

run.sh

...
exit
...

当我按. run2.sh运行时,如果它在exit中点击run.sh代码行,我希望它停在终端并停留在那里。但是使用exit,整个终端都会被关闭。

PS:我曾尝试使用return,但echo代码行仍会被执行....

15 个答案:

答案 0 :(得分:226)

“问题”实际上是你在寻找而不是执行脚本。当您获取文件时,其内容将在当前shell中执行,而不是生成子shell。所以包括exit在内的所有内容都会影响当前的shell。

您需要使用exit

,而不是使用return

答案 1 :(得分:32)

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

正如§4.1 "Bourne Shell Builtins" of the Bash Reference Manual所说:

     return [n]
     

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

答案 2 :(得分:9)

您可以使用. run2.shsh run2.sh运行脚本,而不是使用bash run2.sh运行代码 将打开一个新实例来运行该脚本,然后在脚本结束时将其关闭,而另一个shell将打开。 `

答案 3 :(得分:3)

这就像你在脚本run2.sh中放置一个run函数一样。 您可以在运行时使用退出代码,同时在bash tty中获取run2.sh文件。 如果给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这是一个设计问题。

答案 4 :(得分:1)

我认为这是因为您在源模式下运行它 用点

. myscript.sh

您应该在子shell中运行它:

/full/path/to/script/myscript.sh

'来源'http://ss64.com/bash/source.html

答案 5 :(得分:1)

正如其他人所指出的那样,源代码执行脚本与执行脚本使用returnexit保持同一会话开放是正确的。

这是一个相关的提示,如果你想要一个能保持会话开放的脚本,无论它是否来源。

以下示例可以像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
  $ |
  (终端窗口保持打开状态并接受其他输入)

这对于快速测试单个终端中的脚本更改非常有用,同时在您工作时在主exit / return下方保留一堆剪贴簿代码。它还可以使代码在某种意义上更具可移植性(如果你有大量的脚本可能会以不同的方式调用,也可能不会以不同的方式调用),尽管在适当的地方使用returnexit会更加笨拙

答案 6 :(得分:1)

您可以在return命令之后添加一个额外的退出命令,以便它既可以从命令行执行脚本,也可以从终端采购。

脚本中的退出代码示例:

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

exit命令之后获取脚本时,不会调用与return命令相同的行。

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

答案 7 :(得分:1)

我遇到了同样的问题,从上面的答案以及我所了解的最终对我有用的是

  1. 具有一个调用目标脚本的shebang行,例如,#!/bin/bash使用bash执行脚本

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

因此,答案是

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

./myscript.sh

希望这对有类似要求/情况的人有所帮助

答案 8 :(得分:0)

如果您的终端模拟器没有-hold,您可以清理源脚本并按住终端:

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

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

答案 9 :(得分:0)

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

答案 10 :(得分:0)

要编写防弹脚本以作为Shell脚本运行或作为rc文件运行,该脚本可以检查并比较$0$BASH_SOURCE并确定是否{{1} }是可以安全使用的。

这是此的简短代码段

exit

答案 11 :(得分:0)

实际上,我认为您可能会对“运行脚本”的方式感到困惑。

如果您使用<span data-names="{{ names }}">...</span> <script> console.log(type($('span').attr('data-names'))); </script> 运行脚本,例如['Michael Kors', 'Luca + Grae', 'Rebecca Minkoff', 'Aritzia', 'Nest Boutique', 'Ruby Claire Boutique', 'Bella Ella Boutique', 'Called to Surf', 'Adidas', 'Lime Lush', 'Farfetch', 'AGACI', 'The Mint Julep Boutique', 'Free People', 'Current Boutique', 'Hazel and Olive', 'DownEast Basics', 'Roolee', 'J.Crew'] ,即使嵌入式脚本以sh结尾,您的终端窗口仍将保留。

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

有关更多详细信息,请参阅What is the difference between using sh and source?

答案 12 :(得分:0)

改进了 Tzunghsing 的答案,结果更清晰,错误重定向,静默使用:

#!/usr/bin/env bash

echo -e "Testing..."

if [ "X$(basename $0 2>/dev/null)" = "X$(basename $BASH_SOURCE)" ]; then
    echo "***** You are Executing $0 in a sub-shell."
    exit 0
else
    echo "..... You are Sourcing $BASH_SOURCE in this terminal shell."
    return 0
fi

echo "This should never be seen!"

或者如果你想把它放到一个无声的函数中:

function sExit() {
    # Safe Exit from script, not closing shell.
    [ "X$(basename $0 2>/dev/null)" = "X$(basename $BASH_SOURCE)" ] && exit 0 || return 0
}

...

# ..it have to be called with an error check, like this: 
sExit && return 0

echo "This should never be seen!"

请注意:

  • 如果您在脚本 (set -e) 中启用了 errexit 并且您使用 return N N != 0,则您的整个脚本将立即退出。要查看所有shell 设置,请使用set -o
  • 在函数中使用时,第一个 return 0 退出函数,第二个 return 0 退出脚本。

答案 13 :(得分:0)

如果命令成功,返回值为0,我们可以在后面查看它的返回值。

Is there a “goto” statement in bash?

<块引用>

这是使用 trap 的一些肮脏的解决方法,它只向后跳转。


#!/bin/bash
set -eu
trap 'echo "E: failed with exitcode $?" 1>&2' ERR

my_function () {
    if git rev-parse --is-inside-work-tree > /dev/null 2>&1; then
        echo "this is run"
        return 0
    else
        echo "fatal: not a git repository (or any of the parent directories): .git"
        goto trap 2> /dev/null
    fi
}

my_function
echo "Command succeeded"  # If my_function failed this line is not printed

相关:

答案 14 :(得分:-1)

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

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

您可以根据您的要求尝试上述两项。