在bash函数中生成一个后台进程



我正在编写一个Bash函数来启动一个需要从某个文件夹启动的服务器,但我不希望启动这个服务器会影响我当前的工作。我写了以下内容:

function startsrv {
        pushd .
        cd ${TRUNK}
        ${SERVERCOMMAND} & 
        popd
}

我的变量都设置好了,但当执行此操作时,我在输出中收到一个关于意外分号的错误,似乎Bash在与号后面插入了一个分号,并在后台启动${SERVERCOMMAND}

我能做些什么来在后台启动${SERVERCOMMAND},同时仍然使用pushd和popd来确保我最终回到当前目录中吗?

编辑:echo ${SERVERCOMMAND}的输出,因为它被请求:

yeti --server --port 8727

错误消息:

-bash: syntax error near unexpected token `;'

$SERVERCOMMAND的值是多少?你必须有一个分号在里面。

值得一提的是,您可以将pushd/cd简化为一个pushd:

pushd $TRUNK
$SERVERCOMMAND &
popd

或者创建一个子shell,使cd只影响一个命令:

(cd $TRUNK; $SERVERCOMMAND &)

您也可以使用cd -

cd $TRUNK
$SERVERCOMMAND &
cd -

${SERVERCOMMAND}中的分号不应触发语法错误,除非bash本身存在错误。分号问题必须位于其他地方,在我们看不到的代码部分中。

除了分号问题,您的代码中还有一些小错误:

  • 未引用${TRUNK}变量展开式。如果目录名包含空白,bash将在调用cd之前将其拆分为多个字段
  • 未检查cd ${TRUNK}的返回值。如果目录不存在,bash将调用当前目录中的服务器
  • 该函数不测试${SERVERCOMMAND}是否可能无法执行(例如,找不到命令)
  • function关键字以及pushdpopd命令都是特定于bash的,因此此代码不会在POSIXshell中运行

这里有一个更安全、兼容POSIX的重写:

log() { printf '%sn' "$*"; }
error() { log "ERROR: $*" >&2; }
fatal() { error "$*"; exit 1; }
startsrv() {
    (
        cd "${TRUNK}" || fatal "failed to cd to '${TRUNK}'"
        set -- ${SERVERCOMMAND}
        command -v "$1" >/dev/null || fatal "command '$1' not found"
        command "$@" &
    ) || exit 1
}

最新更新