从函数构建别名

从函数构建别名

我需要很多不同的别名来创建到不同服务器的 ssh 隧道。给你其中一些:

alias tunnel_1='autossh -M 20000 -N -L 8080:localhost:8080 -N -L 9200:localhost:9200 -N -L 8090:localhost:8090 [email protected]'
alias tunnel_2='autossh -M 20000 -N -L 8000:localhost:8080 -N -L 9200:localhost:9200 -N -L 8090:localhost:8090 [email protected]'

我想出了在别名中添加的这个函数:

addPort () {
  echo "-N -L $1:localhost:$1 "
}

tunnel () {
  aliasString="autossh -M 20000 "
  for port in "${@:2}"
  do
    aliasString+=$(addPort $port)
  done
  aliasString+="$1"
  eval $aliasString
}

所以我只需要这样做来隧道到我想要的服务器:

tunnel [email protected] 8080 9000 7200

它运行良好,但如果可能的话我不想使用 eval 。还有另一种方法可以autossh直接调用并给它正确的参数而不使用 eval 吗?

答案1

使用单个 shell 函数:

tunnel () {
    local host="$1"; shift
    local port
    local args

    args=( -M 20000 )

    for port do
        args+=( -N -L "$port:localhost:$port" )
    done

    autossh "${args[@]}" "$host"
}

或者,对于/bin/sh

tunnel () {
    host="$1"; shift

    for port do
        set -- "$@" -N -L "$port:localhost:$port"
        shift
    done

    autossh -M 20000 "$@" "$host"
}

这两个函数都将第一个参数提取到变量中host,然后构建一个由提供的端口号组成的字符串组成的列表。

最后,这两个函数都会autossh使用给定的列表和主机进行调用。

答案2

aliasString除空格外不包含任何 shell 特殊字符。所以eval $aliasStringeval "$aliasString"$aliasString都是等价的。这不带引号的变量替换 aliasString执行分词和通配符扩展;因为没有通配符,所以这只是分词。eval "$aliasString"执行所有 shell 解析和评估步骤;由于除了空格之外没有特殊字符,因此唯一发生的事情就是分词。eval $aliasString从不带引号的变量替换中进行单词拆分,然后将单词连接在一起并在中间添加一个空格,然后进行整个 shell 评估,再次拆分单词。

这是用普通 sh 编写此函数的更简单方法。

tunnel () {
  command=$1
  shift
  for port do
    command="-N -L "$port:localhost:$port $command"
  done
  autossh -M 20000 $command
}

请注意,这仅适用于不包含任何空白通配符的参数。看拘萨罗南达的回答以获得更稳健的方法。

根本不涉及 shell 别名。

相关内容