在 bash 函数中生成后台进程
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6298623/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spawn a background process in a bash function
提问by foxxtrot
I am working on writing a Bash function to start a server that needs to be started from a certain folder, but I don't want starting this server to impact my current work. I've written the following:
我正在编写一个 Bash 函数来启动一个需要从某个文件夹启动的服务器,但我不希望启动这个服务器影响我当前的工作。我写了以下内容:
function startsrv {
pushd .
cd ${TRUNK}
${SERVERCOMMAND} &
popd
}
My variables are all set, but when this executes, I get an error regarding an unexpected semicolon in the output, it appears that Bash is inserting a semicolon after the ampersand starting ${SERVERCOMMAND}in the background.
我的变量都已设置,但是当执行此操作时,我收到有关输出中意外分号的错误,看来 Bash 正在${SERVERCOMMAND}后台开始的与号之后插入分号。
Is there anything I can do to start ${SERVERCOMMAND}in the background while still using pushd and popd to make sure I end up back in my current directory?
我可以做些什么来${SERVERCOMMAND}在后台启动,同时仍然使用 pushd 和 popd 以确保我最终回到当前目录?
Edit: Output of echo ${SERVERCOMMAND}, since it was requested:
编辑: 的输出echo ${SERVERCOMMAND},因为它被要求:
yeti --server --port 8727
Error message:
错误信息:
-bash: syntax error near unexpected token `;'
回答by John Kugelman
What is the value of $SERVERCOMMAND? You must have a semi-colon in it.
的价值是$SERVERCOMMAND什么?您必须在其中包含一个分号。
For what it's worth you can simplify the pushd/cd to one pushd:
为了它的价值,您可以将 pushd/cd 简化为一个 pushd:
pushd $TRUNK
$SERVERCOMMAND &
popd
Or create a subshell so the cd only affects the one command:
或者创建一个子shell,这样 cd 只影响一个命令:
(cd $TRUNK; $SERVERCOMMAND &)
回答by Eugene Yarmash
You can also use cd -
你也可以使用 cd -
cd $TRUNK
$SERVERCOMMAND &
cd -
回答by Richard Hansen
A semicolon in ${SERVERCOMMAND}should not trigger a syntax error unless there is a bug in bashitself. The semicolon problem must be located elsewhere, in a part of the code we don't see.
${SERVERCOMMAND}除非bash本身存在错误,否则分号 in不应触发语法错误。分号问题必须位于其他地方,在我们看不到的代码部分。
Aside from the semicolon issue, there are some minor bugs in your code:
除了分号问题,您的代码中还有一些小错误:
- The
${TRUNK}variable expansion isn't quoted. If the directory name contains whitespace,bashwill split it into multiple fields before invokingcd. - The return value of
cd ${TRUNK}isn't checked. If the directory doesn't exist,bashwill invoke the server in the current directory. - The function doesn't test whether
${SERVERCOMMAND}might fail to execute (e.g., command not found). - The
functionkeyword and thepushdandpopdcommands arebash-specific, so this code won't run in a POSIX shell.
- 该
${TRUNK}变量扩展没有加引号。如果目录名包含空格,bash则在调用之前将其拆分为多个字段cd。 cd ${TRUNK}不检查的返回值。如果目录不存在,bash将调用当前目录中的服务器。- 该函数不测试是否
${SERVERCOMMAND}可能无法执行(例如,未找到命令)。 - 该
function关键字与pushd和popd命令bash特异性,所以这个代码将无法在POSIX shell中运行。
Here's a safer, POSIX-compatible rewrite:
这是一个更安全、兼容 POSIX 的重写:
log() { printf '%s\n' "$*"; }
error() { log "ERROR: $*" >&2; }
fatal() { error "$*"; exit 1; }
startsrv() {
(
cd "${TRUNK}" || fatal "failed to cd to '${TRUNK}'"
set -- ${SERVERCOMMAND}
command -v "" >/dev/null || fatal "command '' not found"
command "$@" &
) || exit 1
}

