在 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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 00:09:24  来源:igfitidea点击:

Spawn a background process in a bash function

bashshellunixbash-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 invoking cd.
  • 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 the pushdand popdcommands are bash-specific, so this code won't run in a POSIX shell.
  • ${TRUNK}变量扩展没有加引号。如果目录名包含空格,bash则在调用之前将其拆分为多个字段cd
  • cd ${TRUNK}不检查的返回值。如果目录不存在,bash将调用当前目录中的服务器。
  • 该函数不测试是否${SERVERCOMMAND}可能无法执行(例如,未找到命令)。
  • function关键字与pushdpopd命令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
}