当我在shell脚本中使用exit
命令时,脚本将终止终端(提示)。有没有办法终止脚本,然后留在终端?
我的脚本run.sh
应该通过直接来源或从另一个脚本来源来执行。
编辑:更具体地说,有两个脚本run2.sh
作为
...
. run.sh
echo "place A"
...
run.sh
作为
...
exit
...
当我通过. run2.sh
运行它时,如果它碰到run.sh
中的exit
代码行,我希望它停在终端并停留在那里。但是使用exit
,整个终端都关闭了。
PS:我已经尝试过使用return
,但echo
代码行仍然会被执行。。。。
真正的"问题"是您正在寻找而没有执行脚本。当您源文件时,其内容将在当前shell中执行,而不是生成子shell。因此,包括退出在内的所有内容都将影响当前shell。
您将希望使用return
,而不是使用exit
。
是;您可以使用return
而不是exit
。它的主要用途是从shell函数返回,但如果在source
-d脚本中使用它,它将从该脚本返回。
作为§4.1Bash参考手册的"Bourne Shell Builtins"将其放在:
return [n]
导致shell函数退出并返回值n。如果未提供n,则返回值为函数中执行的最后一个命令。这也可以用于终止正在执行的脚本的执行带有
.
(或source
)内建,返回n或作为出口在脚本中执行的最后一个命令的出口状态脚本的状态。执行任何与RETURN
陷阱相关的命令在函数或脚本之后恢复执行之前。如果在函数外部使用return
,则返回状态为非零而不是在CCD_ 20或CCD_。
您可以在return语句/命令之后添加一个额外的exit命令,以便它同时适用于这两种情况,从命令行执行脚本并从终端获取源代码。
脚本中的退出代码示例:
if [ $# -lt 2 ]; then
echo "Needs at least two arguments"
return 1 2>/dev/null
exit 1
fi
在return
命令之后获取脚本时,将不会调用带有exit
命令的行。
执行脚本时,return
命令会出现错误。因此,我们通过将错误消息转发到/dev/null
来抑制错误消息。
您可以使用sh run2.sh
或bash run2.sh
运行脚本,而不是使用. run2.sh
运行脚本
将启动一个新的子shell,然后运行脚本,它将在脚本结束时关闭,另一个shell将打开。
实际上,我认为您可能会对run a script
的使用方式感到困惑。
如果使用sh
运行脚本,例如sh ./run2.sh
,即使嵌入的脚本以exit
结束,您的终端窗口仍将保留。
但是,如果您使用.
或source
,当下标结束时,您的终端窗口也将退出/关闭。
有关更多详细信息,请参阅使用sh
和source
有什么区别?
这就像在脚本run2.sh中放入一个run函数一样。您在run中使用退出代码,同时在bash-tty中获取run2.sh文件。如果赋予run函数退出脚本并赋予run2.sh的权限其退出终止器的能力。当然,run函数有权退出teminator。
#! /bin/sh
# use . run2.sh
run()
{
echo "this is run"
#return 0
exit 0
}
echo "this is begin"
run
echo "this is end"
不管怎样,我同意卡兹的看法,这是一个设计问题。
我也遇到了同样的问题,从上面的答案和我所理解的最终对我有效的是:
-
有一个shebang行,它调用预期的脚本,例如
#!/bin/bash
使用bash
执行脚本
我有两种shebang的剧本。正因为如此,使用sh
或.
是不可靠的,因为它会导致错误执行(比如当脚本未完全运行时退出)
因此,答案是
-
- 确保脚本有一个shebang,这样就不会怀疑它的预期处理程序
- 对.sh文件进行chmod处理,以便可以执行该文件。
(chmod +x file.sh)
-
直接调用它,不需要任何
sh
或.
(./myscript.sh)
希望这能帮助到有类似问题的人。
要编写一个既可以作为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 ....."
我认为发生这种情况是因为您在源代码模式下运行它带点
. myscript.sh
你应该在子shell中运行它:
/full/path/to/script/myscript.sh
"源"http://ss64.com/bash/source.html
正如其他人所指出的,源脚本与执行脚本使用return
与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
$|
(终端窗口保持打开并接受额外输入)
这对于在单个终端中快速测试脚本更改非常有用,同时在工作时在主exit
/return
下面保留一堆废弃代码。从某种意义上说,它还可以使代码更具可移植性(如果你有大量的脚本,可以用不同的方式调用,也可以不调用),尽管在适当的情况下只使用return
和exit
就不会那么笨重了。
同时确保返回预期的返回值。否则,如果在遇到出口时使用出口,它将从基本shell中退出,因为源程序不会创建另一个进程(实例)。
改进了Tzunghing的答案,具有更清晰的结果和错误重定向,用于静默使用:
#!/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,并且使用N != 0
启用了return N
,则整个脚本将立即退出。要查看所有shell设置,请使用set -o
- 当在函数中使用时,第一个
return 0
正在退出函数,第二个return 0
正在退出脚本
如果您的终端模拟器没有-hold
,您可以对源脚本进行清理,并使用保存终端
#!/bin/sh
sed "s/exit/return/g" script >/tmp/script
. /tmp/script
read
否则,您可以使用$TERM -hold -e script
如果命令成功,返回值将为0。之后我们可以检查它的返回值。
bash中有"goto"语句吗?
以下是使用仅向后跳转的
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
相关:
- https://stackoverflow.com/a/19091823/2402577
- 如何使用$?并测试以检查功能
我找不到解决方案,所以对于那些想在不离开终端窗口的情况下离开嵌套脚本的人来说:
# this is just script which goes to directory if path satisfies regex
wpr(){
leave=false
pwd=$(pwd)
if [[ "$pwd" =~ ddev.*web ]]; then
# echo "your in wordpress instalation"
wpDir=$(echo "$pwd" | grep -o '.*/web')
cd $wpDir
return
fi
echo 'please be in wordpress directory'
# to leave from outside the scope
leave=true
return
}
wpt(){
# nested function which returns $leave variable
wpr
# interupts the script if $leave is true
if $leave; then
return;
fi
echo 'here is the rest of the script, executes if leave is not defined'
}
我不知道这对你是否有用,但在zsh中,你可以退出一个脚本,但只有在有脚本的情况下才返回提示,方法是对不存在的变量使用参数展开,如下所示。
${missing_variable_ejector:?}
尽管这确实会在脚本中创建一条错误消息,但您可以通过以下方法防止它。
{ ${missing_variable_ejector:?} } 2>/dev/null
1)如果成功,退出0将从脚本中出来。
2) 如果失败,则脚本中会出现出口1。
你可以根据你的需求尝试以上两种。