在bash函数中生成后台进程

时间:2011-06-09 20:08:11

标签: bash shell unix bash-function

我正在编写一个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 `;'

3 个答案:

答案 0 :(得分:11)

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

对于它的价值,您可以将pushd / cd简化为一个推送:

pushd $TRUNK
$SERVERCOMMAND &
popd

或创建一个子shell,因此cd只影响一个命令:

(cd $TRUNK; $SERVERCOMMAND &)

答案 1 :(得分:3)

您也可以使用cd -

cd $TRUNK
$SERVERCOMMAND &
cd -

答案 2 :(得分:2)

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

除分号问题外,您的代码中还存在一些小错误:

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

这是一个更安全,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 "$1" >/dev/null || fatal "command '$1' not found"
        command "$@" &
    ) || exit 1
}